added 3dengfx into the repo, probably not the correct version for this
authorJohn Tsiombikas <nuclear@member.fsf.org>
Thu, 31 Dec 2020 05:14:26 +0000 (07:14 +0200)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Thu, 31 Dec 2020 05:14:26 +0000 (07:14 +0200)
demo, probably needs fixing.

199 files changed:
.gitignore [new file with mode: 0644]
Makefile
src/3dengfx [deleted symlink]
src/3dengfx/AUTHORS [new file with mode: 0644]
src/3dengfx/COPYING [new file with mode: 0644]
src/3dengfx/Makefile [new file with mode: 0644]
src/3dengfx/libs/lib3ds/atmosphere.c [new file with mode: 0644]
src/3dengfx/libs/lib3ds/atmosphere.h [new file with mode: 0644]
src/3dengfx/libs/lib3ds/background.c [new file with mode: 0644]
src/3dengfx/libs/lib3ds/background.h [new file with mode: 0644]
src/3dengfx/libs/lib3ds/camera.c [new file with mode: 0644]
src/3dengfx/libs/lib3ds/camera.h [new file with mode: 0644]
src/3dengfx/libs/lib3ds/chunk.c [new file with mode: 0644]
src/3dengfx/libs/lib3ds/chunk.h [new file with mode: 0644]
src/3dengfx/libs/lib3ds/chunktable.h [new file with mode: 0644]
src/3dengfx/libs/lib3ds/ease.c [new file with mode: 0644]
src/3dengfx/libs/lib3ds/ease.h [new file with mode: 0644]
src/3dengfx/libs/lib3ds/file.c [new file with mode: 0644]
src/3dengfx/libs/lib3ds/file.h [new file with mode: 0644]
src/3dengfx/libs/lib3ds/float.c [new file with mode: 0644]
src/3dengfx/libs/lib3ds/float.h [new file with mode: 0644]
src/3dengfx/libs/lib3ds/io.c [new file with mode: 0644]
src/3dengfx/libs/lib3ds/io.h [new file with mode: 0644]
src/3dengfx/libs/lib3ds/light.c [new file with mode: 0644]
src/3dengfx/libs/lib3ds/light.h [new file with mode: 0644]
src/3dengfx/libs/lib3ds/makefile.part [new file with mode: 0644]
src/3dengfx/libs/lib3ds/material.c [new file with mode: 0644]
src/3dengfx/libs/lib3ds/material.h [new file with mode: 0644]
src/3dengfx/libs/lib3ds/matrix.c [new file with mode: 0644]
src/3dengfx/libs/lib3ds/matrix.h [new file with mode: 0644]
src/3dengfx/libs/lib3ds/mesh.c [new file with mode: 0644]
src/3dengfx/libs/lib3ds/mesh.h [new file with mode: 0644]
src/3dengfx/libs/lib3ds/node.c [new file with mode: 0644]
src/3dengfx/libs/lib3ds/node.h [new file with mode: 0644]
src/3dengfx/libs/lib3ds/quat.c [new file with mode: 0644]
src/3dengfx/libs/lib3ds/quat.h [new file with mode: 0644]
src/3dengfx/libs/lib3ds/shadow.c [new file with mode: 0644]
src/3dengfx/libs/lib3ds/shadow.h [new file with mode: 0644]
src/3dengfx/libs/lib3ds/tcb.c [new file with mode: 0644]
src/3dengfx/libs/lib3ds/tcb.h [new file with mode: 0644]
src/3dengfx/libs/lib3ds/tracks.c [new file with mode: 0644]
src/3dengfx/libs/lib3ds/tracks.h [new file with mode: 0644]
src/3dengfx/libs/lib3ds/types.h [new file with mode: 0644]
src/3dengfx/libs/lib3ds/vector.c [new file with mode: 0644]
src/3dengfx/libs/lib3ds/vector.h [new file with mode: 0644]
src/3dengfx/libs/lib3ds/viewport.c [new file with mode: 0644]
src/3dengfx/libs/lib3ds/viewport.h [new file with mode: 0644]
src/3dengfx/src/3dengfx/3dengfx.hpp [new file with mode: 0644]
src/3dengfx/src/3dengfx/3denginefx.cpp [new file with mode: 0644]
src/3dengfx/src/3dengfx/3denginefx.hpp [new file with mode: 0644]
src/3dengfx/src/3dengfx/3denginefx_types.hpp [new file with mode: 0644]
src/3dengfx/src/3dengfx/3dscene.cpp [new file with mode: 0644]
src/3dengfx/src/3dengfx/3dscene.hpp [new file with mode: 0644]
src/3dengfx/src/3dengfx/camera.cpp [new file with mode: 0644]
src/3dengfx/src/3dengfx/camera.hpp [new file with mode: 0644]
src/3dengfx/src/3dengfx/gfxprog.cpp [new file with mode: 0644]
src/3dengfx/src/3dengfx/gfxprog.hpp [new file with mode: 0644]
src/3dengfx/src/3dengfx/ggen.cpp [new file with mode: 0644]
src/3dengfx/src/3dengfx/ggen.hpp [new file with mode: 0644]
src/3dengfx/src/3dengfx/light.cpp [new file with mode: 0644]
src/3dengfx/src/3dengfx/light.hpp [new file with mode: 0644]
src/3dengfx/src/3dengfx/makefile.part [new file with mode: 0644]
src/3dengfx/src/3dengfx/material.cpp [new file with mode: 0644]
src/3dengfx/src/3dengfx/material.hpp [new file with mode: 0644]
src/3dengfx/src/3dengfx/mcube_tables.h [new file with mode: 0644]
src/3dengfx/src/3dengfx/object.cpp [new file with mode: 0644]
src/3dengfx/src/3dengfx/object.hpp [new file with mode: 0644]
src/3dengfx/src/3dengfx/opengl.h [new file with mode: 0644]
src/3dengfx/src/3dengfx/ply.cpp [new file with mode: 0644]
src/3dengfx/src/3dengfx/psys.cpp [new file with mode: 0644]
src/3dengfx/src/3dengfx/psys.hpp [new file with mode: 0644]
src/3dengfx/src/3dengfx/rend_curve.cpp [new file with mode: 0644]
src/3dengfx/src/3dengfx/rend_curve.hpp [new file with mode: 0644]
src/3dengfx/src/3dengfx/sceneloader.cpp [new file with mode: 0644]
src/3dengfx/src/3dengfx/sceneloader.hpp [new file with mode: 0644]
src/3dengfx/src/3dengfx/scfield.cpp [new file with mode: 0644]
src/3dengfx/src/3dengfx/scfield.hpp [new file with mode: 0644]
src/3dengfx/src/3dengfx/sdrman.cpp [new file with mode: 0644]
src/3dengfx/src/3dengfx/sdrman.hpp [new file with mode: 0644]
src/3dengfx/src/3dengfx/sgi_glext.h [new file with mode: 0644]
src/3dengfx/src/3dengfx/shadows.cpp [new file with mode: 0644]
src/3dengfx/src/3dengfx/shadows.hpp [new file with mode: 0644]
src/3dengfx/src/3dengfx/teapot.h [new file with mode: 0644]
src/3dengfx/src/3dengfx/texman.cpp [new file with mode: 0644]
src/3dengfx/src/3dengfx/texman.hpp [new file with mode: 0644]
src/3dengfx/src/3dengfx/textures.cpp [new file with mode: 0644]
src/3dengfx/src/3dengfx/textures.hpp [new file with mode: 0644]
src/3dengfx/src/3dengfx_config.h [new file with mode: 0644]
src/3dengfx/src/common/byteorder.c [new file with mode: 0644]
src/3dengfx/src/common/byteorder.h [new file with mode: 0644]
src/3dengfx/src/common/config_parser.c [new file with mode: 0644]
src/3dengfx/src/common/config_parser.h [new file with mode: 0644]
src/3dengfx/src/common/err_msg.c [new file with mode: 0644]
src/3dengfx/src/common/err_msg.h [new file with mode: 0644]
src/3dengfx/src/common/fps_counter.c [new file with mode: 0644]
src/3dengfx/src/common/fps_counter.h [new file with mode: 0644]
src/3dengfx/src/common/hashtable.hpp [new file with mode: 0644]
src/3dengfx/src/common/linkedlist.hpp [new file with mode: 0644]
src/3dengfx/src/common/locator.c [new file with mode: 0644]
src/3dengfx/src/common/locator.h [new file with mode: 0644]
src/3dengfx/src/common/makefile.part [new file with mode: 0644]
src/3dengfx/src/common/psort.hpp [new file with mode: 0644]
src/3dengfx/src/common/string_hash.cpp [new file with mode: 0644]
src/3dengfx/src/common/string_hash.hpp [new file with mode: 0644]
src/3dengfx/src/common/timer.c [new file with mode: 0644]
src/3dengfx/src/common/timer.h [new file with mode: 0644]
src/3dengfx/src/common/types.h [new file with mode: 0644]
src/3dengfx/src/dsys/cmd.cpp [new file with mode: 0644]
src/3dengfx/src/dsys/cmd.h [new file with mode: 0644]
src/3dengfx/src/dsys/cmd.hpp [new file with mode: 0644]
src/3dengfx/src/dsys/demosys.hpp [new file with mode: 0644]
src/3dengfx/src/dsys/dsys.cpp [new file with mode: 0644]
src/3dengfx/src/dsys/dsys.hpp [new file with mode: 0644]
src/3dengfx/src/dsys/fx.cpp [new file with mode: 0644]
src/3dengfx/src/dsys/fx.hpp [new file with mode: 0644]
src/3dengfx/src/dsys/makefile.part [new file with mode: 0644]
src/3dengfx/src/dsys/part.cpp [new file with mode: 0644]
src/3dengfx/src/dsys/part.hpp [new file with mode: 0644]
src/3dengfx/src/dsys/scene_part.cpp [new file with mode: 0644]
src/3dengfx/src/dsys/scene_part.hpp [new file with mode: 0644]
src/3dengfx/src/dsys/script.c [new file with mode: 0644]
src/3dengfx/src/dsys/script.h [new file with mode: 0644]
src/3dengfx/src/fxwt/fxwt.cpp [new file with mode: 0644]
src/3dengfx/src/fxwt/fxwt.hpp [new file with mode: 0644]
src/3dengfx/src/fxwt/fxwt_glut.cpp [new file with mode: 0644]
src/3dengfx/src/fxwt/fxwt_gtk.cpp [new file with mode: 0644]
src/3dengfx/src/fxwt/fxwt_sdl.cpp [new file with mode: 0644]
src/3dengfx/src/fxwt/fxwt_win32.cpp [new file with mode: 0644]
src/3dengfx/src/fxwt/fxwt_x.cpp [new file with mode: 0644]
src/3dengfx/src/fxwt/gfx_library.h [new file with mode: 0644]
src/3dengfx/src/fxwt/init.cpp [new file with mode: 0644]
src/3dengfx/src/fxwt/init.hpp [new file with mode: 0644]
src/3dengfx/src/fxwt/init_glut.cpp [new file with mode: 0644]
src/3dengfx/src/fxwt/init_gtk.cpp [new file with mode: 0644]
src/3dengfx/src/fxwt/init_sdl.cpp [new file with mode: 0644]
src/3dengfx/src/fxwt/init_win32.cpp [new file with mode: 0644]
src/3dengfx/src/fxwt/init_x.cpp [new file with mode: 0644]
src/3dengfx/src/fxwt/keysyms.hpp [new file with mode: 0644]
src/3dengfx/src/fxwt/makefile.part [new file with mode: 0644]
src/3dengfx/src/fxwt/text.cpp [new file with mode: 0644]
src/3dengfx/src/fxwt/text.hpp [new file with mode: 0644]
src/3dengfx/src/gfx/3dgeom.cpp [new file with mode: 0644]
src/3dengfx/src/gfx/3dgeom.hpp [new file with mode: 0644]
src/3dengfx/src/gfx/3dgeom.inl [new file with mode: 0644]
src/3dengfx/src/gfx/animation.cpp [new file with mode: 0644]
src/3dengfx/src/gfx/animation.hpp [new file with mode: 0644]
src/3dengfx/src/gfx/animation.inl [new file with mode: 0644]
src/3dengfx/src/gfx/base_cam.cpp [new file with mode: 0644]
src/3dengfx/src/gfx/base_cam.hpp [new file with mode: 0644]
src/3dengfx/src/gfx/bvol.cpp [new file with mode: 0644]
src/3dengfx/src/gfx/bvol.hpp [new file with mode: 0644]
src/3dengfx/src/gfx/color.cpp [new file with mode: 0644]
src/3dengfx/src/gfx/color.hpp [new file with mode: 0644]
src/3dengfx/src/gfx/color.inl [new file with mode: 0644]
src/3dengfx/src/gfx/color_bits.h [new file with mode: 0644]
src/3dengfx/src/gfx/controller.cpp [new file with mode: 0644]
src/3dengfx/src/gfx/controller.hpp [new file with mode: 0644]
src/3dengfx/src/gfx/curves.cpp [new file with mode: 0644]
src/3dengfx/src/gfx/curves.hpp [new file with mode: 0644]
src/3dengfx/src/gfx/image.c [new file with mode: 0644]
src/3dengfx/src/gfx/image.h [new file with mode: 0644]
src/3dengfx/src/gfx/image_jpg.c [new file with mode: 0644]
src/3dengfx/src/gfx/image_png.c [new file with mode: 0644]
src/3dengfx/src/gfx/image_ppm.c [new file with mode: 0644]
src/3dengfx/src/gfx/image_tga.c [new file with mode: 0644]
src/3dengfx/src/gfx/img_manip.cpp [new file with mode: 0644]
src/3dengfx/src/gfx/img_manip.hpp [new file with mode: 0644]
src/3dengfx/src/gfx/makefile.part [new file with mode: 0644]
src/3dengfx/src/gfx/pbuffer.hpp [new file with mode: 0644]
src/3dengfx/src/gfx/timeline.cpp [new file with mode: 0644]
src/3dengfx/src/gfx/timeline.hpp [new file with mode: 0644]
src/3dengfx/src/n3dmath2/makefile.part [new file with mode: 0644]
src/3dengfx/src/n3dmath2/n3dmath2.cpp [new file with mode: 0644]
src/3dengfx/src/n3dmath2/n3dmath2.hpp [new file with mode: 0644]
src/3dengfx/src/n3dmath2/n3dmath2.inl [new file with mode: 0644]
src/3dengfx/src/n3dmath2/n3dmath2_mat.cpp [new file with mode: 0644]
src/3dengfx/src/n3dmath2/n3dmath2_mat.hpp [new file with mode: 0644]
src/3dengfx/src/n3dmath2/n3dmath2_mat.inl [new file with mode: 0644]
src/3dengfx/src/n3dmath2/n3dmath2_qdr.cpp [new file with mode: 0644]
src/3dengfx/src/n3dmath2/n3dmath2_qdr.hpp [new file with mode: 0644]
src/3dengfx/src/n3dmath2/n3dmath2_qua.cpp [new file with mode: 0644]
src/3dengfx/src/n3dmath2/n3dmath2_qua.hpp [new file with mode: 0644]
src/3dengfx/src/n3dmath2/n3dmath2_ray.cpp [new file with mode: 0644]
src/3dengfx/src/n3dmath2/n3dmath2_ray.hpp [new file with mode: 0644]
src/3dengfx/src/n3dmath2/n3dmath2_sph.cpp [new file with mode: 0644]
src/3dengfx/src/n3dmath2/n3dmath2_sph.hpp [new file with mode: 0644]
src/3dengfx/src/n3dmath2/n3dmath2_types.hpp [new file with mode: 0644]
src/3dengfx/src/n3dmath2/n3dmath2_vec.cpp [new file with mode: 0644]
src/3dengfx/src/n3dmath2/n3dmath2_vec.hpp [new file with mode: 0644]
src/3dengfx/src/n3dmath2/n3dmath2_vec.inl [new file with mode: 0644]
src/3dengfx/src/sim/makefile.part [new file with mode: 0644]
src/3dengfx/src/sim/rigid.cpp [new file with mode: 0644]
src/3dengfx/src/sim/rigid.hpp [new file with mode: 0644]
src/3dengfx/src/sim/rope.cpp [new file with mode: 0644]
src/3dengfx/src/sim/rope.hpp [new file with mode: 0644]
src/3dengfx/src/sim/sim.cpp [new file with mode: 0644]
src/3dengfx/src/sim/sim.hpp [new file with mode: 0644]
src/3dengfx/src/sim/spring.cpp [new file with mode: 0644]
src/3dengfx/src/sim/spring.hpp [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..c60fd20
--- /dev/null
@@ -0,0 +1,7 @@
+*.o
+*.swp
+*.d
+*.a
+*.so*
+sumhack-thelab
+data/
index 459126d..d5f022e 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -4,38 +4,27 @@ bin = sumhack-thelab
 include src/parts/Makefile-part
 include src/sdlvf/Makefile-part
 
+
 obj = $(src:.cpp=.o) $(csrc:.c=.o)
 
 opt = -O1
 opt = -g
-CXXFLAGS = -ansi -pedantic -Wall $(opt) -Isrc/3dengfx/src `src/3dengfx/3dengfx-config --cflags`
-CFLAGS = -std=c89 -pedantic -Wall $(opt) `src/3dengfx/3dengfx-config --cflags`
-libs = src/3dengfx/lib3dengfx.a `src/3dengfx/3dengfx-config --libs-no-3dengfx` -lGL -lvorbisfile
+CXXFLAGS = -ansi -pedantic -Wall $(opt) -Isrc/3dengfx/src -MMD `sdl-config --cflags`
+CFLAGS = -std=c89 -pedantic -Wall $(opt) -MMD `sdl-config --cflags`
+libs = src/3dengfx/lib3dengfx.a `sdl-config --libs` -lGL -lvorbisfile -ljpeg -lpng -lz
 
-$(bin): $(obj) src/3dengfx/lib3dengfx.a data/tex_list
+$(bin): $(obj) src/3dengfx/lib3dengfx.a
        $(CXX) -o $@ $(obj) $(libs)
 
 src/3dengfx/lib3dengfx.a:
-       cd src/3dengfx;\
-       ./configure --with-gfxlib=sdl --disable-ft --enable-opt --disable-debug && make
-
-data/tex_list: $(src)
-       tools/find_textures >$@
+       $(MAKE) -C src/3dengfx
 
 -include $(obj:.o=.d)
 
-%.d: %.cpp
-       @set -e; rm -f $@; $(CXX) -MM $(CXXFLAGS) $< > $@.$$$$; \
-       sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; rm -f $@.$$$$
-
-%.d: %.c
-       @set -e; rm -f $@; $(CC) -MM $(CFLAGS) $< > $@.$$$$; \
-       sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; rm -f $@.$$$$
-
 .PHONY: clean
 clean:
        $(RM) $(obj) $(bin)
 
 .PHONY: cleandep
 cleandep:
-       find src \( -name '*.d' -o -name '*.d.*' \) -exec $(RM) '{}' ';'
+       $(RM) $(obj:.o=.d)
diff --git a/src/3dengfx b/src/3dengfx
deleted file mode 120000 (symlink)
index 86b5175..0000000
+++ /dev/null
@@ -1 +0,0 @@
-/home/nuclear/code/graphics/3dengfx_dev/3dengfx
\ No newline at end of file
diff --git a/src/3dengfx/AUTHORS b/src/3dengfx/AUTHORS
new file mode 100644 (file)
index 0000000..4417de8
--- /dev/null
@@ -0,0 +1,9 @@
+Original 3dengfx author and maintainer:
+       John Tsiombikas <nuclear@siggraph.org>
+       
+Developers:
+       John Tsiombikas <nuclear@siggraph.org>
+       Mihalis Georgoulopoulos <msamurai@freemail.gr>
+
+Cross-platform compatibility testers:
+       Leonidas Tsampros <ltsampros@upnet.gr> (FreeBSD)
diff --git a/src/3dengfx/COPYING b/src/3dengfx/COPYING
new file mode 100644 (file)
index 0000000..3912109
--- /dev/null
@@ -0,0 +1,340 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+           How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/src/3dengfx/Makefile b/src/3dengfx/Makefile
new file mode 100644 (file)
index 0000000..73b00ee
--- /dev/null
@@ -0,0 +1,43 @@
+PREFIX = /usr/local
+dbg = -g
+opt = -O1 -ffast-math -fomit-frame-pointer
+
+inc_flags = -Isrc -Ilibs -I/usr/local/include
+warn_flags = -Wall -Wno-sign-compare -Wno-strict-aliasing -Wno-char-subscripts
+
+CXXFLAGS = $(opt) $(dbg) -ansi -pedantic $(warn_flags) -MMD $(inc_flags) \
+                  `sdl-config --cflags`
+CFLAGS = $(opt) $(dbg) -std=c89 -pedantic $(warn_flags) -MMD $(inc_flags) \
+                `sdl-config --cflags`
+
+include src/3dengfx/makefile.part
+include src/gfx/makefile.part
+include src/n3dmath2/makefile.part
+include src/dsys/makefile.part
+include src/common/makefile.part
+include src/fxwt/makefile.part
+include src/sim/makefile.part
+include libs/lib3ds/makefile.part
+
+# get all the object files in one variable $(obj)
+obj = $(3dengfx_obj) \
+         $(gfx_obj) \
+         $(n3dmath2_obj) \
+         $(dsys_obj) \
+         $(common_obj) \
+         $(fxwt_obj) \
+         $(sim_obj) \
+         $(lib3ds_obj)
+
+lib3dengfx.a: $(obj)
+       $(AR) rcs $@ $(obj)
+
+-include $(obj:.o=.d)
+
+.PHONY: clean
+clean:
+       $(RM) $(obj) lib3dengfx.a
+
+.PHONY: cleandep
+cleandep:
+       $(RM) $(obj:.o=.d)
diff --git a/src/3dengfx/libs/lib3ds/atmosphere.c b/src/3dengfx/libs/lib3ds/atmosphere.c
new file mode 100644 (file)
index 0000000..e079b9e
--- /dev/null
@@ -0,0 +1,307 @@
+/*
+ * The 3D Studio File Format Library
+ * Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
+ * All rights reserved.
+ *
+ * This program is  free  software;  you can redistribute it and/or modify it
+ * under the terms of the  GNU Lesser General Public License  as published by 
+ * the  Free Software Foundation;  either version 2.1 of the License,  or (at 
+ * your option) any later version.
+ *
+ * This  program  is  distributed in  the  hope that it will  be useful,  but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public  
+ * License for more details.
+ *
+ * You should  have received  a copy of the GNU Lesser General Public License
+ * along with  this program;  if not, write to the  Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: atmosphere.c,v 1.9 2001/07/07 19:05:30 jeh Exp $
+ */
+#define LIB3DS_EXPORT
+#include <lib3ds/atmosphere.h>
+#include <lib3ds/chunk.h>
+#include <lib3ds/io.h>
+
+
+/*!
+ * \defgroup atmosphere Atmosphere Settings
+ *
+ * \author J.E. Hoffmann <je-h@gmx.net>
+ */
+
+
+static Lib3dsBool
+fog_read(Lib3dsFog *fog, Lib3dsIo *io)
+{
+  Lib3dsChunk c;
+  Lib3dsWord chunk;
+
+  if (!lib3ds_chunk_read_start(&c, LIB3DS_FOG, io)) {
+    return(LIB3DS_FALSE);
+  }
+  fog->near_plane = lib3ds_io_read_float(io);
+  fog->near_density=lib3ds_io_read_float(io);
+  fog->far_plane=lib3ds_io_read_float(io);
+  fog->far_density=lib3ds_io_read_float(io);
+  lib3ds_chunk_read_tell(&c, io);
+  
+  while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) {
+    switch (chunk) {
+      case LIB3DS_LIN_COLOR_F:
+        {
+          int i;
+          for (i=0; i<3; ++i) {
+            fog->col[i]=lib3ds_io_read_float(io);
+          }
+        }
+        break;
+      case LIB3DS_COLOR_F:
+        break;
+      case LIB3DS_FOG_BGND:
+        {
+          fog->fog_background=LIB3DS_TRUE;
+        }
+        break;
+      default:
+        lib3ds_chunk_unknown(chunk);
+    }
+  }
+  
+  lib3ds_chunk_read_end(&c, io);
+  return(LIB3DS_TRUE);
+}
+
+
+static Lib3dsBool
+layer_fog_read(Lib3dsLayerFog *fog, Lib3dsIo *io)
+{
+  Lib3dsChunk c;
+  Lib3dsWord chunk;
+  Lib3dsBool have_lin=LIB3DS_FALSE;
+
+  if (!lib3ds_chunk_read_start(&c, LIB3DS_LAYER_FOG, io)) {
+    return(LIB3DS_FALSE);
+  }
+  fog->near_y=lib3ds_io_read_float(io);
+  fog->far_y=lib3ds_io_read_float(io);
+  fog->density=lib3ds_io_read_float(io);
+  fog->flags=lib3ds_io_read_dword(io);
+  lib3ds_chunk_read_tell(&c, io);
+  
+  while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) {
+    switch (chunk) {
+      case LIB3DS_LIN_COLOR_F:
+        lib3ds_io_read_rgb(io, fog->col);
+        have_lin=LIB3DS_TRUE;
+        break;
+      case LIB3DS_COLOR_F:
+        lib3ds_io_read_rgb(io, fog->col);
+        break;
+      default:
+        lib3ds_chunk_unknown(chunk);
+    }
+  }
+  
+  lib3ds_chunk_read_end(&c, io);
+  return(LIB3DS_TRUE);
+}
+
+
+static Lib3dsBool
+distance_cue_read(Lib3dsDistanceCue *cue, Lib3dsIo *io)
+{
+  Lib3dsChunk c;
+  Lib3dsWord chunk;
+
+  if (!lib3ds_chunk_read_start(&c, LIB3DS_DISTANCE_CUE, io)) {
+    return(LIB3DS_FALSE);
+  }
+  cue->near_plane=lib3ds_io_read_float(io);
+  cue->near_dimming=lib3ds_io_read_float(io);
+  cue->far_plane=lib3ds_io_read_float(io);
+  cue->far_dimming=lib3ds_io_read_float(io);
+  lib3ds_chunk_read_tell(&c, io);
+  
+  while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) {
+    switch (chunk) {
+      case LIB3DS_DCUE_BGND:
+        {
+          cue->cue_background=LIB3DS_TRUE;
+        }
+        break;
+      default:
+        lib3ds_chunk_unknown(chunk);
+    }
+  }
+  
+  lib3ds_chunk_read_end(&c, io);
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+ * \ingroup atmosphere
+ */
+Lib3dsBool
+lib3ds_atmosphere_read(Lib3dsAtmosphere *atmosphere, Lib3dsIo *io)
+{
+  Lib3dsChunk c;
+
+  if (!lib3ds_chunk_read(&c, io)) {
+    return(LIB3DS_FALSE);
+  }
+  
+  switch (c.chunk) {
+      case LIB3DS_FOG:
+        {
+          lib3ds_chunk_read_reset(&c, io);
+          if (!fog_read(&atmosphere->fog, io)) {
+            return(LIB3DS_FALSE);
+          }
+        }
+        break;
+      case LIB3DS_LAYER_FOG:
+        {
+          lib3ds_chunk_read_reset(&c, io);
+          if (!layer_fog_read(&atmosphere->layer_fog, io)) {
+            return(LIB3DS_FALSE);
+          }
+        }
+        break;
+      case LIB3DS_DISTANCE_CUE:
+        {
+          lib3ds_chunk_read_reset(&c, io);
+          if (!distance_cue_read(&atmosphere->dist_cue, io)) {
+            return(LIB3DS_FALSE);
+          }
+        }
+        break;
+      case LIB3DS_USE_FOG:
+        {
+          atmosphere->fog.use=LIB3DS_TRUE;
+        }
+        break;
+      case LIB3DS_USE_LAYER_FOG:
+        {
+          atmosphere->fog.use=LIB3DS_TRUE;
+        }
+        break;
+      case LIB3DS_USE_DISTANCE_CUE:
+        {
+          atmosphere->dist_cue.use=LIB3DS_TRUE;
+        }
+        break;
+  }
+
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+ * \ingroup atmosphere
+ */
+Lib3dsBool
+lib3ds_atmosphere_write(Lib3dsAtmosphere *atmosphere, Lib3dsIo *io)
+{
+  if (atmosphere->fog.use) { /*---- LIB3DS_FOG ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_FOG;
+    if (!lib3ds_chunk_write_start(&c,io)) {
+      return(LIB3DS_FALSE);
+    }
+    lib3ds_io_write_float(io, atmosphere->fog.near_plane);
+    lib3ds_io_write_float(io, atmosphere->fog.near_density);
+    lib3ds_io_write_float(io, atmosphere->fog.far_plane);
+    lib3ds_io_write_float(io, atmosphere->fog.far_density);
+    {
+      Lib3dsChunk c;
+      c.chunk=LIB3DS_COLOR_F;
+      c.size=18;
+      lib3ds_chunk_write(&c,io);
+      lib3ds_io_write_rgb(io, atmosphere->fog.col);
+    }
+    if (atmosphere->fog.fog_background) {
+      Lib3dsChunk c;
+      c.chunk=LIB3DS_FOG_BGND;
+      c.size=6;
+      lib3ds_chunk_write(&c,io);
+    }
+    if (!lib3ds_chunk_write_end(&c,io)) {
+      return(LIB3DS_FALSE);
+    }
+  }
+
+  if (atmosphere->layer_fog.use) { /*---- LIB3DS_LAYER_FOG ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_LAYER_FOG;
+    c.size=40;
+    lib3ds_chunk_write(&c,io);
+    lib3ds_io_write_float(io, atmosphere->layer_fog.near_y);
+    lib3ds_io_write_float(io, atmosphere->layer_fog.far_y);
+    lib3ds_io_write_float(io, atmosphere->layer_fog.near_y);
+    lib3ds_io_write_dword(io, atmosphere->layer_fog.flags);
+    {
+      Lib3dsChunk c;
+      c.chunk=LIB3DS_COLOR_F;
+      c.size=18;
+      lib3ds_chunk_write(&c,io);
+      lib3ds_io_write_rgb(io, atmosphere->fog.col);
+    }
+  }
+
+  if (atmosphere->dist_cue.use) { /*---- LIB3DS_DISTANCE_CUE ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_DISTANCE_CUE;
+    if (!lib3ds_chunk_write_start(&c,io)) {
+      return(LIB3DS_FALSE);
+    }
+    lib3ds_io_write_float(io, atmosphere->dist_cue.near_plane);
+    lib3ds_io_write_float(io, atmosphere->dist_cue.near_dimming);
+    lib3ds_io_write_float(io, atmosphere->dist_cue.far_plane);
+    lib3ds_io_write_float(io, atmosphere->dist_cue.far_dimming);
+    if (atmosphere->dist_cue.cue_background) {
+      Lib3dsChunk c;
+      c.chunk=LIB3DS_DCUE_BGND;
+      c.size=6;
+      lib3ds_chunk_write(&c,io);
+    }
+    if (!lib3ds_chunk_write_end(&c,io)) {
+      return(LIB3DS_FALSE);
+    }
+  }
+
+  if (atmosphere->fog.use) { /*---- LIB3DS_USE_FOG ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_USE_FOG;
+    c.size=6;
+    lib3ds_chunk_write(&c,io);
+  }
+
+  if (atmosphere->layer_fog.use) { /*---- LIB3DS_USE_LAYER_FOG ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_USE_LAYER_FOG;
+    c.size=6;
+    lib3ds_chunk_write(&c,io);
+  }
+
+  if (atmosphere->dist_cue.use) { /*---- LIB3DS_USE_DISTANCE_CUE ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_USE_V_GRADIENT;
+    c.size=6;
+    lib3ds_chunk_write(&c,io);
+  }
+  
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+
+\typedef Lib3dsAtmosphere
+  \ingroup atmosphere
+  \sa _Lib3dsAtmosphere
+
+*/
+
diff --git a/src/3dengfx/libs/lib3ds/atmosphere.h b/src/3dengfx/libs/lib3ds/atmosphere.h
new file mode 100644 (file)
index 0000000..fc4a82c
--- /dev/null
@@ -0,0 +1,100 @@
+/* -*- c -*- */
+#ifndef INCLUDED_LIB3DS_ATMOSPHERE_H
+#define INCLUDED_LIB3DS_ATMOSPHERE_H
+/*
+ * The 3D Studio File Format Library
+ * Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
+ * All rights reserved.
+ *
+ * This program is  free  software;  you can redistribute it and/or modify it
+ * under the terms of the  GNU Lesser General Public License  as published by 
+ * the  Free Software Foundation;  either version 2.1 of the License,  or (at 
+ * your option) any later version.
+ *
+ * This  program  is  distributed in  the  hope that it will  be useful,  but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public  
+ * License for more details.
+ *
+ * You should  have received  a copy of the GNU Lesser General Public License
+ * along with  this program;  if not, write to the  Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: atmosphere.h,v 1.6 2004/12/31 16:17:15 reed Exp $
+ */
+
+#ifndef INCLUDED_LIB3DS_TYPES_H
+#include <lib3ds/types.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*!
+ * Fog atmosphere settings
+ * \ingroup atmosphere
+ */
+typedef struct _Lib3dsFog {
+    Lib3dsBool use;
+    Lib3dsRgb col;
+    Lib3dsBool fog_background;
+    Lib3dsFloat near_plane;
+    Lib3dsFloat near_density;
+    Lib3dsFloat far_plane;
+    Lib3dsFloat far_density;
+} Lib3dsFog;
+
+/*!
+ * Layer fog atmosphere flags
+ * \ingroup atmosphere
+ */
+typedef enum _Lib3dsLayerFogFlags {
+  LIB3DS_BOTTOM_FALL_OFF =0x00000001,
+  LIB3DS_TOP_FALL_OFF    =0x00000002,
+  LIB3DS_FOG_BACKGROUND  =0x00100000
+} Lib3dsLayerFogFlags;
+
+/*!
+ * Layer fog atmosphere settings
+ * \ingroup atmosphere
+ */
+typedef struct _Lib3dsLayerFog {
+    Lib3dsBool use;
+    Lib3dsDword flags;
+    Lib3dsRgb col;
+    Lib3dsFloat near_y;
+    Lib3dsFloat far_y;
+    Lib3dsFloat density;
+} Lib3dsLayerFog;
+
+/*!
+ * Distance cue atmosphere settings
+ * \ingroup atmosphere
+ */
+typedef struct _Lib3dsDistanceCue {
+    Lib3dsBool use;
+    Lib3dsBool cue_background;
+    Lib3dsFloat near_plane;
+    Lib3dsFloat near_dimming;
+    Lib3dsFloat far_plane;
+    Lib3dsFloat far_dimming;
+} Lib3dsDistanceCue;
+
+/*!
+ * Atmosphere settings
+ * \ingroup atmosphere
+ */
+struct _Lib3dsAtmosphere {
+    Lib3dsFog fog;
+    Lib3dsLayerFog layer_fog;
+    Lib3dsDistanceCue dist_cue;
+};
+
+extern LIB3DSAPI Lib3dsBool lib3ds_atmosphere_read(Lib3dsAtmosphere *atmosphere, Lib3dsIo *io);
+extern LIB3DSAPI Lib3dsBool lib3ds_atmosphere_write(Lib3dsAtmosphere *atmosphere, Lib3dsIo *io);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/3dengfx/libs/lib3ds/background.c b/src/3dengfx/libs/lib3ds/background.c
new file mode 100644 (file)
index 0000000..4b24223
--- /dev/null
@@ -0,0 +1,266 @@
+/*
+ * The 3D Studio File Format Library
+ * Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
+ * All rights reserved.
+ *
+ * This program is  free  software;  you can redistribute it and/or modify it
+ * under the terms of the  GNU Lesser General Public License  as published by 
+ * the  Free Software Foundation;  either version 2.1 of the License,  or (at 
+ * your option) any later version.
+ *
+ * This  program  is  distributed in  the  hope that it will  be useful,  but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public  
+ * License for more details.
+ *
+ * You should  have received  a copy of the GNU Lesser General Public License
+ * along with  this program;  if not, write to the  Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: background.c,v 1.8 2001/07/07 19:05:30 jeh Exp $
+ */
+#define LIB3DS_EXPORT
+#include <lib3ds/background.h>
+#include <lib3ds/chunk.h>
+#include <lib3ds/io.h>
+#include <string.h>
+#include <math.h>
+
+
+/*!
+ * \defgroup background Background Settings
+ *
+ * \author J.E. Hoffmann <je-h@gmx.net>
+ */
+
+
+static Lib3dsBool
+solid_bgnd_read(Lib3dsBackground *background, Lib3dsIo *io)
+{
+  Lib3dsChunk c;
+  Lib3dsWord chunk;
+  Lib3dsBool have_lin=LIB3DS_FALSE;
+          
+  if (!lib3ds_chunk_read_start(&c, LIB3DS_SOLID_BGND, io)) {
+    return(LIB3DS_FALSE);
+  }
+
+  while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) {
+    switch (chunk) {
+      case LIB3DS_LIN_COLOR_F:
+        lib3ds_io_read_rgb(io, background->solid.col);
+        have_lin=LIB3DS_TRUE;
+        break;
+      case LIB3DS_COLOR_F:
+        lib3ds_io_read_rgb(io, background->solid.col);
+        break;
+      default:
+        lib3ds_chunk_unknown(chunk);
+    }
+  }
+  
+  lib3ds_chunk_read_end(&c, io);
+  return(LIB3DS_TRUE);
+}
+
+
+static Lib3dsBool
+v_gradient_read(Lib3dsBackground *background, Lib3dsIo *io)
+{
+  Lib3dsChunk c;
+  Lib3dsWord chunk;
+  int index[2];
+  Lib3dsRgb col[2][3];
+  int have_lin=0;
+  
+
+  if (!lib3ds_chunk_read_start(&c, LIB3DS_V_GRADIENT, io)) {
+    return(LIB3DS_FALSE);
+  }
+  background->gradient.percent=lib3ds_io_read_float(io);
+  lib3ds_chunk_read_tell(&c, io);
+
+  index[0]=index[1]=0;
+  while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) {
+    switch (chunk) {
+      case LIB3DS_COLOR_F:
+        lib3ds_io_read_rgb(io, col[0][index[0]]);
+        index[0]++;
+        break;
+      case LIB3DS_LIN_COLOR_F:
+        lib3ds_io_read_rgb(io, col[1][index[1]]);
+        index[1]++;
+        have_lin=1;
+        break;
+      default:
+        lib3ds_chunk_unknown(chunk);
+    }
+  }
+  {
+    int i;
+    for (i=0; i<3; ++i) {
+      background->gradient.top[i]=col[have_lin][0][i];
+      background->gradient.middle[i]=col[have_lin][1][i];
+      background->gradient.bottom[i]=col[have_lin][2][i];
+    }
+  }
+  lib3ds_chunk_read_end(&c, io);
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+ * \ingroup background
+ */
+Lib3dsBool
+lib3ds_background_read(Lib3dsBackground *background, Lib3dsIo *io)
+{
+  Lib3dsChunk c;
+
+  if (!lib3ds_chunk_read(&c, io)) {
+    return(LIB3DS_FALSE);
+  }
+  
+  switch (c.chunk) {
+    case LIB3DS_BIT_MAP:
+      {
+        if (!lib3ds_io_read_string(io, background->bitmap.name, 64)) {
+            return(LIB3DS_FALSE);
+        }
+      }
+      break;
+    case LIB3DS_SOLID_BGND:
+      {
+        lib3ds_chunk_read_reset(&c, io);
+        if (!solid_bgnd_read(background, io)) {
+          return(LIB3DS_FALSE);
+        }
+      }
+      break;
+    case LIB3DS_V_GRADIENT:
+      {
+        lib3ds_chunk_read_reset(&c, io);
+        if (!v_gradient_read(background, io)) {
+          return(LIB3DS_FALSE);
+        }
+      }
+      break;
+    case LIB3DS_USE_BIT_MAP:
+      {
+        background->bitmap.use=LIB3DS_TRUE;
+      }
+      break;
+    case LIB3DS_USE_SOLID_BGND:
+      {
+        background->solid.use=LIB3DS_TRUE;
+      }
+      break;
+    case LIB3DS_USE_V_GRADIENT:
+      {
+        background->gradient.use=LIB3DS_TRUE;
+      }
+      break;
+  }
+  
+  return(LIB3DS_TRUE);
+}
+
+
+static Lib3dsBool
+colorf_write(Lib3dsRgba rgb, Lib3dsIo *io)
+{
+  Lib3dsChunk c;
+
+  c.chunk=LIB3DS_COLOR_F;
+  c.size=18;
+  lib3ds_chunk_write(&c,io);
+  lib3ds_io_write_rgb(io, rgb);
+
+  c.chunk=LIB3DS_LIN_COLOR_F;
+  c.size=18;
+  lib3ds_chunk_write(&c,io);
+  lib3ds_io_write_rgb(io, rgb);
+  return(LIB3DS_TRUE);
+}
+
+
+static Lib3dsBool
+colorf_defined(Lib3dsRgba rgb)
+{
+  int i;
+  for (i=0; i<3; ++i) {
+    if (fabs(rgb[i])>LIB3DS_EPSILON) {
+      break;
+    }
+  }
+  return(i<3);
+}
+
+
+/*!
+ * \ingroup background
+ */
+Lib3dsBool
+lib3ds_background_write(Lib3dsBackground *background, Lib3dsIo *io)
+{
+  if (strlen(background->bitmap.name)) { /*---- LIB3DS_BIT_MAP ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_BIT_MAP;
+    c.size=6+1+strlen(background->bitmap.name);
+    lib3ds_chunk_write(&c,io);
+    lib3ds_io_write_string(io, background->bitmap.name);
+  }
+
+  if (colorf_defined(background->solid.col)) { /*---- LIB3DS_SOLID_BGND ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_SOLID_BGND;
+    c.size=42;
+    lib3ds_chunk_write(&c,io);
+    colorf_write(background->solid.col, io);
+  }
+
+  if (colorf_defined(background->gradient.top) ||
+    colorf_defined(background->gradient.middle) ||
+    colorf_defined(background->gradient.bottom)) { /*---- LIB3DS_V_GRADIENT ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_V_GRADIENT;
+    c.size=118;
+    lib3ds_chunk_write(&c,io);
+    lib3ds_io_write_float(io, background->gradient.percent);
+    colorf_write(background->gradient.top,io);
+    colorf_write(background->gradient.middle,io);
+    colorf_write(background->gradient.bottom,io);
+  }
+
+  if (background->bitmap.use) { /*---- LIB3DS_USE_BIT_MAP ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_USE_BIT_MAP;
+    c.size=6;
+    lib3ds_chunk_write(&c,io);
+  }
+
+  if (background->solid.use) { /*---- LIB3DS_USE_SOLID_BGND ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_USE_SOLID_BGND;
+    c.size=6;
+    lib3ds_chunk_write(&c,io);
+  }
+
+  if (background->gradient.use) { /*---- LIB3DS_USE_V_GRADIENT ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_USE_V_GRADIENT;
+    c.size=6;
+    lib3ds_chunk_write(&c,io);
+  }
+  
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+
+\typedef Lib3dsBackground
+  \ingroup background
+  \sa _Lib3dsBackground
+
+*/
diff --git a/src/3dengfx/libs/lib3ds/background.h b/src/3dengfx/libs/lib3ds/background.h
new file mode 100644 (file)
index 0000000..3ecfa3f
--- /dev/null
@@ -0,0 +1,85 @@
+/* -*- c -*- */
+#ifndef INCLUDED_LIB3DS_BACKGROUND_H
+#define INCLUDED_LIB3DS_BACKGROUND_H
+/*
+ * The 3D Studio File Format Library
+ * Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
+ * All rights reserved.
+ *
+ * This program is  free  software;  you can redistribute it and/or modify it
+ * under the terms of the  GNU Lesser General Public License  as published by 
+ * the  Free Software Foundation;  either version 2.1 of the License,  or (at 
+ * your option) any later version.
+ *
+ * This  program  is  distributed in  the  hope that it will  be useful,  but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public  
+ * License for more details.
+ *
+ * You should  have received  a copy of the GNU Lesser General Public License
+ * along with  this program;  if not, write to the  Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: background.h,v 1.6 2004/12/31 16:17:15 reed Exp $
+ */
+
+#ifndef INCLUDED_LIB3DS_TYPES_H
+#include <lib3ds/types.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*!
+ * Bitmap background settings
+ * \ingroup background
+ */
+typedef struct _Lib3dsBitmap {
+    Lib3dsBool use;
+    char name[64];
+} Lib3dsBitmap;
+
+/*!
+ * Solid color background settings
+ * \ingroup background
+ */
+typedef struct _Lib3dsSolid {
+    Lib3dsBool use;
+    Lib3dsRgb col;
+} Lib3dsSolid;
+
+/*!
+ * Gradient background settings
+ * \ingroup background
+ */
+typedef struct _Lib3dsGradient {
+    Lib3dsBool use;
+    Lib3dsFloat percent;
+    Lib3dsRgb top;
+    Lib3dsRgb middle;
+    Lib3dsRgb bottom;
+} Lib3dsGradient;
+
+/*!
+ * Background settings
+ * \ingroup background
+ */
+struct _Lib3dsBackground {
+    Lib3dsBitmap bitmap;
+    Lib3dsSolid solid;
+    Lib3dsGradient gradient;
+};
+
+extern LIB3DSAPI Lib3dsBool lib3ds_background_read(Lib3dsBackground *background, Lib3dsIo *io);
+extern LIB3DSAPI Lib3dsBool lib3ds_background_write(Lib3dsBackground *background, Lib3dsIo *io);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+
+
+
+
diff --git a/src/3dengfx/libs/lib3ds/camera.c b/src/3dengfx/libs/lib3ds/camera.c
new file mode 100644 (file)
index 0000000..3da02dd
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ * The 3D Studio File Format Library
+ * Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
+ * All rights reserved.
+ *
+ * This program is  free  software;  you can redistribute it and/or modify it
+ * under the terms of the  GNU Lesser General Public License  as published by 
+ * the  Free Software Foundation;  either version 2.1 of the License,  or (at 
+ * your option) any later version.
+ *
+ * This  program  is  distributed in  the  hope that it will  be useful,  but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public  
+ * License for more details.
+ *
+ * You should  have received  a copy of the GNU Lesser General Public License
+ * along with  this program;  if not, write to the  Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: camera.c,v 1.12 2004/11/16 07:41:44 efalk Exp $
+ */
+#define LIB3DS_EXPORT
+#include <lib3ds/camera.h>
+#include <lib3ds/chunk.h>
+#include <lib3ds/io.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+#ifdef WITH_DMALLOC
+#include <dmalloc.h>
+#endif
+
+
+/*!
+ * \defgroup camera Cameras
+ *
+ * \author J.E. Hoffmann <je-h@gmx.net>
+ */
+
+
+/*!
+ * Return a new Lib3dsCamera object.
+ *
+ * Object is initialized with the given name and fov=45.  All other
+ * values are 0.
+ *
+ * \param name Name of this camera.  Must not be NULL.  Must be < 64 characters.
+ *
+ * \return Lib3dsCamera object or NULL on failure.
+ *
+ * \ingroup camera
+ */
+Lib3dsCamera*
+lib3ds_camera_new(const char *name)
+{
+  Lib3dsCamera *camera;
+
+  ASSERT(name);
+  ASSERT(strlen(name)<64);
+  
+  camera=(Lib3dsCamera*)calloc(sizeof(Lib3dsCamera), 1);
+  if (!camera) {
+    return(0);
+  }
+  strcpy(camera->name, name);
+  camera->fov=45.0f;
+  return(camera);
+}
+
+
+/*!
+ * Free a Lib3dsCamera object and all of its resources.
+ *
+ * \param camera Lib3dsCamera object to be freed.
+ *
+ * \ingroup camera 
+ */
+void
+lib3ds_camera_free(Lib3dsCamera *camera)
+{
+  memset(camera, 0, sizeof(Lib3dsCamera));
+  free(camera);
+}
+
+
+/*!
+ * Dump information about a Lib3dsCamera object to stdout.
+ *
+ * \param camera Object to be dumped.
+ *
+ * \see lib3ds_file_dump_cameras
+ *
+ * \ingroup camera
+ */
+void
+lib3ds_camera_dump(Lib3dsCamera *camera)
+{
+  ASSERT(camera);
+  printf("  name:       %s\n", camera->name);
+  printf("  position:   (%f, %f, %f)\n", 
+    camera->position[0], camera->position[1], camera->position[2]);
+  printf("  target      (%f, %f, %f)\n", 
+    camera->target[0], camera->target[1], camera->target[2]);
+  printf("  roll:       %f\n", camera->roll);
+  printf("  fov:        %f\n", camera->fov);
+  printf("  see_cone:   %s\n", camera->see_cone ? "yes" : "no");
+  printf("  near_range: %f\n", camera->near_range);
+  printf("  far_range:  %f\n", camera->far_range);
+  printf("\n");
+}
+
+
+/*!
+ * Read a camera definition from a file.
+ *
+ * This function is called by lib3ds_file_read(), and you probably
+ * don't want to call it directly.
+ *
+ * \param camera A Lib3dsCamera to be filled in.
+ * \param io A Lib3dsIo object previously set up by the caller.
+ *
+ * \return LIB3DS_TRUE on success, LIB3DS_FALSE on failure.
+ *
+ * \see lib3ds_file_read
+ *
+ * \ingroup camera
+ */
+Lib3dsBool
+lib3ds_camera_read(Lib3dsCamera *camera, Lib3dsIo *io)
+{
+  Lib3dsChunk c;
+  Lib3dsWord chunk;
+
+  if (!lib3ds_chunk_read_start(&c, LIB3DS_N_CAMERA, io)) {
+    return(LIB3DS_FALSE);
+  }
+  {
+    int i;
+    for (i=0; i<3; ++i) {
+      camera->position[i]=lib3ds_io_read_float(io);
+    }
+    for (i=0; i<3; ++i) {
+      camera->target[i]=lib3ds_io_read_float(io);
+    }
+  }
+  camera->roll=lib3ds_io_read_float(io);
+  {
+    float s;
+    s=lib3ds_io_read_float(io);
+    if (fabs(s)<LIB3DS_EPSILON) {
+      camera->fov=45.0;
+    }
+    else {
+      camera->fov=2400.0f/s;
+    }
+  }
+  lib3ds_chunk_read_tell(&c, io);
+  
+  while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) {
+    switch (chunk) {
+      case LIB3DS_CAM_SEE_CONE:
+        {
+          camera->see_cone=LIB3DS_TRUE;
+        }
+        break;
+      case LIB3DS_CAM_RANGES:
+        {
+          camera->near_range=lib3ds_io_read_float(io);
+          camera->far_range=lib3ds_io_read_float(io);
+        }
+        break;
+      default:
+        lib3ds_chunk_unknown(chunk);
+    }
+  }
+  
+  lib3ds_chunk_read_end(&c, io);
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+ * Write a camera definition to a file.
+ *
+ * This function is called by lib3ds_file_write(), and you probably
+ * don't want to call it directly.
+ *
+ * \param camera A Lib3dsCamera to be written.
+ * \param io A Lib3dsIo object previously set up by the caller.
+ *
+ * \return LIB3DS_TRUE on success, LIB3DS_FALSE on failure.
+ *
+ * \see lib3ds_file_write
+ *
+ * \ingroup camera
+ */
+Lib3dsBool
+lib3ds_camera_write(Lib3dsCamera *camera, Lib3dsIo *io)
+{
+  Lib3dsChunk c;
+
+  c.chunk=LIB3DS_N_CAMERA;
+  if (!lib3ds_chunk_write_start(&c,io)) {
+    return(LIB3DS_FALSE);
+  }
+
+  lib3ds_io_write_vector(io, camera->position);
+  lib3ds_io_write_vector(io, camera->target);
+  lib3ds_io_write_float(io, camera->roll);
+  if (fabs(camera->fov)<LIB3DS_EPSILON) {
+    lib3ds_io_write_float(io, 2400.0f/45.0f);
+  }
+  else {
+    lib3ds_io_write_float(io, 2400.0f/camera->fov);
+  }
+
+  if (camera->see_cone) {
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_CAM_SEE_CONE;
+    c.size=6;
+    lib3ds_chunk_write(&c, io);
+  }
+  {
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_CAM_RANGES;
+    c.size=14;
+    lib3ds_chunk_write(&c, io);
+    lib3ds_io_write_float(io, camera->near_range);
+    lib3ds_io_write_float(io, camera->far_range);
+  }
+
+  if (!lib3ds_chunk_write_end(&c,io)) {
+    return(LIB3DS_FALSE);
+  }
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+
+\typedef Lib3dsCamera
+  \ingroup camera
+  \sa _Lib3dsCamera
+
+*/
diff --git a/src/3dengfx/libs/lib3ds/camera.h b/src/3dengfx/libs/lib3ds/camera.h
new file mode 100644 (file)
index 0000000..089c2bc
--- /dev/null
@@ -0,0 +1,60 @@
+/* -*- c -*- */
+#ifndef INCLUDED_LIB3DS_CAMERA_H
+#define INCLUDED_LIB3DS_CAMERA_H
+/*
+ * The 3D Studio File Format Library
+ * Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
+ * All rights reserved.
+ *
+ * This program is  free  software;  you can redistribute it and/or modify it
+ * under the terms of the  GNU Lesser General Public License  as published by 
+ * the  Free Software Foundation;  either version 2.1 of the License,  or (at 
+ * your option) any later version.
+ *
+ * This  program  is  distributed in  the  hope that it will  be useful,  but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public  
+ * License for more details.
+ *
+ * You should  have received  a copy of the GNU Lesser General Public License
+ * along with  this program;  if not, write to the  Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: camera.h,v 1.8 2004/12/31 16:17:15 reed Exp $
+ */
+
+#ifndef INCLUDED_LIB3DS_TYPES_H
+#include <lib3ds/types.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*!
+ * Camera object
+ * \ingroup camera
+ */
+struct _Lib3dsCamera {
+    Lib3dsCamera *next;
+    char name[64];
+    Lib3dsVector position;
+    Lib3dsVector target;
+    Lib3dsFloat roll;
+    Lib3dsFloat fov;
+    Lib3dsBool see_cone;
+    Lib3dsFloat near_range;
+    Lib3dsFloat far_range;
+}; 
+
+extern LIB3DSAPI Lib3dsCamera* lib3ds_camera_new(const char *name);
+extern LIB3DSAPI void lib3ds_camera_free(Lib3dsCamera *mesh);
+extern LIB3DSAPI void lib3ds_camera_dump(Lib3dsCamera *camera);
+extern LIB3DSAPI Lib3dsBool lib3ds_camera_read(Lib3dsCamera *camera, Lib3dsIo *io);
+extern LIB3DSAPI Lib3dsBool lib3ds_camera_write(Lib3dsCamera *camera, Lib3dsIo *io);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/src/3dengfx/libs/lib3ds/chunk.c b/src/3dengfx/libs/lib3ds/chunk.c
new file mode 100644 (file)
index 0000000..75d51d0
--- /dev/null
@@ -0,0 +1,307 @@
+/*
+ * The 3D Studio File Format Library
+ * Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
+ * All rights reserved.
+ *
+ * This program is  free  software;  you can redistribute it and/or modify it
+ * under the terms of the  GNU Lesser General Public License  as published by 
+ * the  Free Software Foundation;  either version 2.1 of the License,  or (at 
+ * your option) any later version.
+ *
+ * This  program  is  distributed in  the  hope that it will  be useful,  but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public  
+ * License for more details.
+ *
+ * You should  have received  a copy of the GNU Lesser General Public License
+ * along with  this program;  if not, write to the  Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: chunk.c,v 1.14 2001/07/07 19:05:30 jeh Exp $
+ */
+#define LIB3DS_EXPORT
+#include <lib3ds/chunk.h>
+#include <lib3ds/io.h>
+#include <lib3ds/chunktable.h>
+#include <string.h>
+#include <stdarg.h>
+
+
+/*#define LIB3DS_CHUNK_DEBUG*/
+/*#define LIB3DS_CHUNK_WARNING*/
+
+
+/*!
+ * \defgroup chunk Chunk Handling
+ *
+ * \author J.E. Hoffmann <je-h@gmx.net>
+ */
+
+
+static Lib3dsBool enable_dump=LIB3DS_FALSE;
+static Lib3dsBool enable_unknown=LIB3DS_FALSE;
+static char lib3ds_chunk_level[128]="";
+
+
+static void
+lib3ds_chunk_debug_enter(Lib3dsChunk *c)
+{
+  strcat(lib3ds_chunk_level, "  ");
+}
+
+
+static void
+lib3ds_chunk_debug_leave(Lib3dsChunk *c)
+{
+  lib3ds_chunk_level[strlen(lib3ds_chunk_level)-2]=0;
+}
+
+
+static void
+lib3ds_chunk_debug_dump(Lib3dsChunk *c)
+{
+  if (enable_dump) {
+    printf("%s%s (0x%X) size=%lu\n",
+      lib3ds_chunk_level,
+      lib3ds_chunk_name(c->chunk),
+      c->chunk,
+      c->size
+    );
+  }
+}
+
+
+/*!
+ * \ingroup chunk
+ */
+void
+lib3ds_chunk_enable_dump(Lib3dsBool enable, Lib3dsBool unknown)
+{
+  enable_dump=enable;
+  enable_unknown=unknown;
+}
+
+
+/*!
+ * \ingroup chunk
+ *
+ * Reads a 3d-Studio chunk header from a little endian file stream.
+ *
+ * \param c  The chunk to store the data.
+ * \param f  The file stream.
+ *
+ * \return   True on success, False otherwise.
+ */
+Lib3dsBool
+lib3ds_chunk_read(Lib3dsChunk *c, Lib3dsIo *io)
+{
+  ASSERT(c);
+  ASSERT(io);
+  c->cur=lib3ds_io_tell(io);
+  c->chunk=lib3ds_io_read_word(io);
+  c->size=lib3ds_io_read_dword(io);
+  c->end=c->cur+c->size;
+  c->cur+=6;
+  if (lib3ds_io_error(io) || (c->size<6)) {
+    return(LIB3DS_FALSE);
+  }
+  return(LIB3DS_TRUE);
+  
+}
+
+
+/*!
+ * \ingroup chunk
+ */
+Lib3dsBool
+lib3ds_chunk_read_start(Lib3dsChunk *c, Lib3dsWord chunk, Lib3dsIo *io)
+{
+  ASSERT(c);
+  ASSERT(io);
+  if (!lib3ds_chunk_read(c, io)) {
+    return(LIB3DS_FALSE);
+  }
+  lib3ds_chunk_debug_enter(c);
+  return((chunk==0) || (c->chunk==chunk));
+}
+
+
+/*!
+ * \ingroup chunk
+ */
+void
+lib3ds_chunk_read_tell(Lib3dsChunk *c, Lib3dsIo *io)
+{
+  c->cur=lib3ds_io_tell(io);
+}
+
+
+/*!
+ * \ingroup chunk
+ */
+Lib3dsWord
+lib3ds_chunk_read_next(Lib3dsChunk *c, Lib3dsIo *io)
+{
+  Lib3dsChunk d;
+
+  if (c->cur>=c->end) {
+    ASSERT(c->cur==c->end);
+    return(0);
+  }
+
+  lib3ds_io_seek(io, (long)c->cur, LIB3DS_SEEK_SET);
+  d.chunk=lib3ds_io_read_word(io);
+  d.size=lib3ds_io_read_dword(io);
+  lib3ds_chunk_debug_dump(&d);
+  c->cur+=d.size;
+  return(d.chunk);
+}
+
+
+/*!
+ * \ingroup chunk
+ */
+void
+lib3ds_chunk_read_reset(Lib3dsChunk *c, Lib3dsIo *io)
+{
+  lib3ds_io_seek(io, -6, LIB3DS_SEEK_CUR);
+}
+
+
+/*!
+ * \ingroup chunk
+ */
+void
+lib3ds_chunk_read_end(Lib3dsChunk *c, Lib3dsIo *io)
+{
+  lib3ds_chunk_debug_leave(c);
+  lib3ds_io_seek(io, c->end, LIB3DS_SEEK_SET);
+}
+
+
+/*!
+ * \ingroup chunk
+ *
+ * Writes a 3d-Studio chunk header into a little endian file stream.
+ *
+ * \param c  The chunk to be written.
+ * \param f  The file stream.
+ *
+ * \return   True on success, False otherwise.
+ */
+Lib3dsBool
+lib3ds_chunk_write(Lib3dsChunk *c, Lib3dsIo *io)
+{
+  ASSERT(c);
+  if (!lib3ds_io_write_word(io, c->chunk)) {
+    LIB3DS_ERROR_LOG;
+    return(LIB3DS_FALSE);
+  }
+  if (!lib3ds_io_write_dword(io, c->size)) {
+    LIB3DS_ERROR_LOG;
+    return(LIB3DS_FALSE);
+  }
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+ * \ingroup chunk
+ */
+Lib3dsBool
+lib3ds_chunk_write_start(Lib3dsChunk *c, Lib3dsIo *io)
+{
+  ASSERT(c);
+  c->size=0;
+  c->cur=lib3ds_io_tell(io);
+  if (!lib3ds_io_write_word(io, c->chunk)) {
+    return(LIB3DS_FALSE);
+  }
+  if (!lib3ds_io_write_dword(io, c->size)) {
+    return(LIB3DS_FALSE);
+  }
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+ * \ingroup chunk
+ */
+Lib3dsBool
+lib3ds_chunk_write_end(Lib3dsChunk *c, Lib3dsIo *io)
+{
+  ASSERT(c);
+  c->size=lib3ds_io_tell(io) - c->cur;
+  lib3ds_io_seek(io, c->cur+2, LIB3DS_SEEK_SET);
+  if (!lib3ds_io_write_dword(io, c->size)) {
+    LIB3DS_ERROR_LOG;
+    return(LIB3DS_FALSE);
+  }
+
+  c->cur+=c->size;
+  lib3ds_io_seek(io, c->cur, LIB3DS_SEEK_SET);
+  if (lib3ds_io_error(io)) {
+    LIB3DS_ERROR_LOG;
+    return(LIB3DS_FALSE);
+  }
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+ * \ingroup chunk
+ */
+const char*
+lib3ds_chunk_name(Lib3dsWord chunk)
+{
+  Lib3dsChunkTable *p;
+
+  for (p=lib3ds_chunk_table; p->name!=0; ++p) {
+    if (p->chunk==chunk) {
+      return(p->name);
+    }
+  }
+  return("***UNKNOWN***");
+}
+
+
+/*!
+ * \ingroup chunk
+ */
+void
+lib3ds_chunk_unknown(Lib3dsWord chunk)
+{
+  if (enable_unknown) {
+    printf("%s***WARNING*** Unknown Chunk: %s (0x%X)\n",
+      lib3ds_chunk_level,
+      lib3ds_chunk_name(chunk),
+      chunk
+    );
+  }
+}
+
+
+/*!
+ * \ingroup chunk
+ */
+void 
+lib3ds_chunk_dump_info(const char *format, ...)
+{
+  if (enable_dump) {
+    char s[1024];
+    va_list marker;
+
+    va_start(marker, format);
+    vsprintf(s, format, marker);
+    va_end(marker);
+
+    printf("%s%s\n", lib3ds_chunk_level, s);
+  }
+}
+
+
+
+
+
+
+
diff --git a/src/3dengfx/libs/lib3ds/chunk.h b/src/3dengfx/libs/lib3ds/chunk.h
new file mode 100644 (file)
index 0000000..d6719ae
--- /dev/null
@@ -0,0 +1,289 @@
+/* -*- c -*- */
+#ifndef INCLUDED_LIB3DS_CHUNK_H
+#define INCLUDED_LIB3DS_CHUNK_H
+/*
+ * The 3D Studio File Format Library
+ * Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
+ * All rights reserved.
+ *
+ * This program is  free  software;  you can redistribute it and/or modify it
+ * under the terms of the  GNU Lesser General Public License  as published by 
+ * the  Free Software Foundation;  either version 2.1 of the License,  or (at 
+ * your option) any later version.
+ *
+ * This  program  is  distributed in  the  hope that it will  be useful,  but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public  
+ * License for more details.
+ *
+ * You should  have received  a copy of the GNU Lesser General Public License
+ * along with  this program;  if not, write to the  Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: chunk.h,v 1.13 2004/12/31 16:17:15 reed Exp $
+ */
+
+#ifndef INCLUDED_LIB3DS_TYPES_H
+#include <lib3ds/types.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum _Lib3dsChunks {
+  LIB3DS_NULL_CHUNK             =0x0000,
+  LIB3DS_M3DMAGIC               =0x4D4D,    /*3DS file*/
+  LIB3DS_SMAGIC                 =0x2D2D,    
+  LIB3DS_LMAGIC                 =0x2D3D,    
+  LIB3DS_MLIBMAGIC              =0x3DAA,    /*MLI file*/
+  LIB3DS_MATMAGIC               =0x3DFF,    
+  LIB3DS_CMAGIC                 =0xC23D,    /*PRJ file*/
+  LIB3DS_M3D_VERSION            =0x0002,
+  LIB3DS_M3D_KFVERSION          =0x0005,
+
+  LIB3DS_COLOR_F                =0x0010,
+  LIB3DS_COLOR_24               =0x0011,
+  LIB3DS_LIN_COLOR_24           =0x0012,
+  LIB3DS_LIN_COLOR_F            =0x0013,
+  LIB3DS_INT_PERCENTAGE         =0x0030,
+  LIB3DS_FLOAT_PERCENTAGE       =0x0031,
+
+  LIB3DS_MDATA                  =0x3D3D,
+  LIB3DS_MESH_VERSION           =0x3D3E,
+  LIB3DS_MASTER_SCALE           =0x0100,
+  LIB3DS_LO_SHADOW_BIAS         =0x1400,
+  LIB3DS_HI_SHADOW_BIAS         =0x1410,
+  LIB3DS_SHADOW_MAP_SIZE        =0x1420,
+  LIB3DS_SHADOW_SAMPLES         =0x1430,
+  LIB3DS_SHADOW_RANGE           =0x1440,
+  LIB3DS_SHADOW_FILTER          =0x1450,
+  LIB3DS_RAY_BIAS               =0x1460,
+  LIB3DS_O_CONSTS               =0x1500,
+  LIB3DS_AMBIENT_LIGHT          =0x2100,
+  LIB3DS_BIT_MAP                =0x1100,
+  LIB3DS_SOLID_BGND             =0x1200,
+  LIB3DS_V_GRADIENT             =0x1300,
+  LIB3DS_USE_BIT_MAP            =0x1101,
+  LIB3DS_USE_SOLID_BGND         =0x1201,
+  LIB3DS_USE_V_GRADIENT         =0x1301,
+  LIB3DS_FOG                    =0x2200,
+  LIB3DS_FOG_BGND               =0x2210,
+  LIB3DS_LAYER_FOG              =0x2302,
+  LIB3DS_DISTANCE_CUE           =0x2300,
+  LIB3DS_DCUE_BGND              =0x2310,
+  LIB3DS_USE_FOG                =0x2201,
+  LIB3DS_USE_LAYER_FOG          =0x2303,
+  LIB3DS_USE_DISTANCE_CUE       =0x2301,
+
+  LIB3DS_MAT_ENTRY              =0xAFFF,
+  LIB3DS_MAT_NAME               =0xA000,
+  LIB3DS_MAT_AMBIENT            =0xA010,
+  LIB3DS_MAT_DIFFUSE            =0xA020,
+  LIB3DS_MAT_SPECULAR           =0xA030,
+  LIB3DS_MAT_SHININESS          =0xA040,
+  LIB3DS_MAT_SHIN2PCT           =0xA041,
+  LIB3DS_MAT_TRANSPARENCY       =0xA050,
+  LIB3DS_MAT_XPFALL             =0xA052,
+  LIB3DS_MAT_USE_XPFALL         =0xA240,
+  LIB3DS_MAT_REFBLUR            =0xA053,
+  LIB3DS_MAT_SHADING            =0xA100,
+  LIB3DS_MAT_USE_REFBLUR        =0xA250,
+  LIB3DS_MAT_SELF_ILLUM         =0xA080,
+  LIB3DS_MAT_TWO_SIDE           =0xA081,
+  LIB3DS_MAT_DECAL              =0xA082,
+  LIB3DS_MAT_ADDITIVE           =0xA083,
+  LIB3DS_MAT_SELF_ILPCT         =0xA084,
+  LIB3DS_MAT_WIRE               =0xA085,
+  LIB3DS_MAT_FACEMAP            =0xA088,
+  LIB3DS_MAT_PHONGSOFT          =0xA08C,
+  LIB3DS_MAT_WIREABS            =0xA08E,
+  LIB3DS_MAT_WIRE_SIZE          =0xA087,
+  LIB3DS_MAT_TEXMAP             =0xA200,
+  LIB3DS_MAT_SXP_TEXT_DATA      =0xA320,
+  LIB3DS_MAT_TEXMASK            =0xA33E,
+  LIB3DS_MAT_SXP_TEXTMASK_DATA  =0xA32A,
+  LIB3DS_MAT_TEX2MAP            =0xA33A,
+  LIB3DS_MAT_SXP_TEXT2_DATA     =0xA321,
+  LIB3DS_MAT_TEX2MASK           =0xA340,
+  LIB3DS_MAT_SXP_TEXT2MASK_DATA =0xA32C,
+  LIB3DS_MAT_OPACMAP            =0xA210,
+  LIB3DS_MAT_SXP_OPAC_DATA      =0xA322,
+  LIB3DS_MAT_OPACMASK           =0xA342,
+  LIB3DS_MAT_SXP_OPACMASK_DATA  =0xA32E,
+  LIB3DS_MAT_BUMPMAP            =0xA230,
+  LIB3DS_MAT_SXP_BUMP_DATA      =0xA324,
+  LIB3DS_MAT_BUMPMASK           =0xA344,
+  LIB3DS_MAT_SXP_BUMPMASK_DATA  =0xA330,
+  LIB3DS_MAT_SPECMAP            =0xA204,
+  LIB3DS_MAT_SXP_SPEC_DATA      =0xA325,
+  LIB3DS_MAT_SPECMASK           =0xA348,
+  LIB3DS_MAT_SXP_SPECMASK_DATA  =0xA332,
+  LIB3DS_MAT_SHINMAP            =0xA33C,
+  LIB3DS_MAT_SXP_SHIN_DATA      =0xA326,
+  LIB3DS_MAT_SHINMASK           =0xA346,
+  LIB3DS_MAT_SXP_SHINMASK_DATA  =0xA334,
+  LIB3DS_MAT_SELFIMAP           =0xA33D,
+  LIB3DS_MAT_SXP_SELFI_DATA     =0xA328,
+  LIB3DS_MAT_SELFIMASK          =0xA34A,
+  LIB3DS_MAT_SXP_SELFIMASK_DATA =0xA336,
+  LIB3DS_MAT_REFLMAP            =0xA220,
+  LIB3DS_MAT_REFLMASK           =0xA34C,
+  LIB3DS_MAT_SXP_REFLMASK_DATA  =0xA338,
+  LIB3DS_MAT_ACUBIC             =0xA310,
+  LIB3DS_MAT_MAPNAME            =0xA300,
+  LIB3DS_MAT_MAP_TILING         =0xA351,
+  LIB3DS_MAT_MAP_TEXBLUR        =0xA353,
+  LIB3DS_MAT_MAP_USCALE         =0xA354,
+  LIB3DS_MAT_MAP_VSCALE         =0xA356,
+  LIB3DS_MAT_MAP_UOFFSET        =0xA358,
+  LIB3DS_MAT_MAP_VOFFSET        =0xA35A,
+  LIB3DS_MAT_MAP_ANG            =0xA35C,
+  LIB3DS_MAT_MAP_COL1           =0xA360,
+  LIB3DS_MAT_MAP_COL2           =0xA362,
+  LIB3DS_MAT_MAP_RCOL           =0xA364,
+  LIB3DS_MAT_MAP_GCOL           =0xA366,
+  LIB3DS_MAT_MAP_BCOL           =0xA368,
+
+  LIB3DS_NAMED_OBJECT           =0x4000,
+  LIB3DS_N_DIRECT_LIGHT         =0x4600,
+  LIB3DS_DL_OFF                 =0x4620,
+  LIB3DS_DL_OUTER_RANGE         =0x465A,
+  LIB3DS_DL_INNER_RANGE         =0x4659,
+  LIB3DS_DL_MULTIPLIER          =0x465B,
+  LIB3DS_DL_EXCLUDE             =0x4654,
+  LIB3DS_DL_ATTENUATE           =0x4625,
+  LIB3DS_DL_SPOTLIGHT           =0x4610,
+  LIB3DS_DL_SPOT_ROLL           =0x4656,
+  LIB3DS_DL_SHADOWED            =0x4630,
+  LIB3DS_DL_LOCAL_SHADOW2       =0x4641,
+  LIB3DS_DL_SEE_CONE            =0x4650,
+  LIB3DS_DL_SPOT_RECTANGULAR    =0x4651,
+  LIB3DS_DL_SPOT_ASPECT         =0x4657,
+  LIB3DS_DL_SPOT_PROJECTOR      =0x4653,
+  LIB3DS_DL_SPOT_OVERSHOOT      =0x4652,
+  LIB3DS_DL_RAY_BIAS            =0x4658,
+  LIB3DS_DL_RAYSHAD             =0x4627,
+  LIB3DS_N_CAMERA               =0x4700,
+  LIB3DS_CAM_SEE_CONE           =0x4710,
+  LIB3DS_CAM_RANGES             =0x4720,
+  LIB3DS_OBJ_HIDDEN             =0x4010,
+  LIB3DS_OBJ_VIS_LOFTER         =0x4011,
+  LIB3DS_OBJ_DOESNT_CAST        =0x4012,
+  LIB3DS_OBJ_DONT_RECVSHADOW    =0x4017,
+  LIB3DS_OBJ_MATTE              =0x4013,
+  LIB3DS_OBJ_FAST               =0x4014,
+  LIB3DS_OBJ_PROCEDURAL         =0x4015,
+  LIB3DS_OBJ_FROZEN             =0x4016,
+  LIB3DS_N_TRI_OBJECT           =0x4100,
+  LIB3DS_POINT_ARRAY            =0x4110,
+  LIB3DS_POINT_FLAG_ARRAY       =0x4111,
+  LIB3DS_FACE_ARRAY             =0x4120,
+  LIB3DS_MSH_MAT_GROUP          =0x4130,
+  LIB3DS_SMOOTH_GROUP           =0x4150,
+  LIB3DS_MSH_BOXMAP             =0x4190,
+  LIB3DS_TEX_VERTS              =0x4140,
+  LIB3DS_MESH_MATRIX            =0x4160,
+  LIB3DS_MESH_COLOR             =0x4165,
+  LIB3DS_MESH_TEXTURE_INFO      =0x4170,
+
+  LIB3DS_KFDATA                 =0xB000,
+  LIB3DS_KFHDR                  =0xB00A,
+  LIB3DS_KFSEG                  =0xB008,
+  LIB3DS_KFCURTIME              =0xB009,
+  LIB3DS_AMBIENT_NODE_TAG       =0xB001,
+  LIB3DS_OBJECT_NODE_TAG        =0xB002,
+  LIB3DS_CAMERA_NODE_TAG        =0xB003,
+  LIB3DS_TARGET_NODE_TAG        =0xB004,
+  LIB3DS_LIGHT_NODE_TAG         =0xB005,
+  LIB3DS_L_TARGET_NODE_TAG      =0xB006,
+  LIB3DS_SPOTLIGHT_NODE_TAG     =0xB007,
+  LIB3DS_NODE_ID                =0xB030,
+  LIB3DS_NODE_HDR               =0xB010,
+  LIB3DS_PIVOT                  =0xB013,
+  LIB3DS_INSTANCE_NAME          =0xB011,
+  LIB3DS_MORPH_SMOOTH           =0xB015,
+  LIB3DS_BOUNDBOX               =0xB014,
+  LIB3DS_POS_TRACK_TAG          =0xB020,
+  LIB3DS_COL_TRACK_TAG          =0xB025,
+  LIB3DS_ROT_TRACK_TAG          =0xB021,
+  LIB3DS_SCL_TRACK_TAG          =0xB022,
+  LIB3DS_MORPH_TRACK_TAG        =0xB026,
+  LIB3DS_FOV_TRACK_TAG          =0xB023,
+  LIB3DS_ROLL_TRACK_TAG         =0xB024,
+  LIB3DS_HOT_TRACK_TAG          =0xB027,
+  LIB3DS_FALL_TRACK_TAG         =0xB028,
+  LIB3DS_HIDE_TRACK_TAG         =0xB029,
+
+  LIB3DS_POLY_2D                = 0x5000,
+  LIB3DS_SHAPE_OK               = 0x5010,
+  LIB3DS_SHAPE_NOT_OK           = 0x5011,
+  LIB3DS_SHAPE_HOOK             = 0x5020,
+  LIB3DS_PATH_3D                = 0x6000,
+  LIB3DS_PATH_MATRIX            = 0x6005,
+  LIB3DS_SHAPE_2D               = 0x6010,
+  LIB3DS_M_SCALE                = 0x6020,
+  LIB3DS_M_TWIST                = 0x6030,
+  LIB3DS_M_TEETER               = 0x6040,
+  LIB3DS_M_FIT                  = 0x6050,
+  LIB3DS_M_BEVEL                = 0x6060,
+  LIB3DS_XZ_CURVE               = 0x6070,
+  LIB3DS_YZ_CURVE               = 0x6080,
+  LIB3DS_INTERPCT               = 0x6090,
+  LIB3DS_DEFORM_LIMIT           = 0x60A0,
+
+  LIB3DS_USE_CONTOUR            = 0x6100,
+  LIB3DS_USE_TWEEN              = 0x6110,
+  LIB3DS_USE_SCALE              = 0x6120,
+  LIB3DS_USE_TWIST              = 0x6130,
+  LIB3DS_USE_TEETER             = 0x6140,
+  LIB3DS_USE_FIT                = 0x6150,
+  LIB3DS_USE_BEVEL              = 0x6160,
+
+  LIB3DS_DEFAULT_VIEW           = 0x3000,
+  LIB3DS_VIEW_TOP               = 0x3010,
+  LIB3DS_VIEW_BOTTOM            = 0x3020,
+  LIB3DS_VIEW_LEFT              = 0x3030,
+  LIB3DS_VIEW_RIGHT             = 0x3040,
+  LIB3DS_VIEW_FRONT             = 0x3050,
+  LIB3DS_VIEW_BACK              = 0x3060,
+  LIB3DS_VIEW_USER              = 0x3070,
+  LIB3DS_VIEW_CAMERA            = 0x3080,
+  LIB3DS_VIEW_WINDOW            = 0x3090,
+
+  LIB3DS_VIEWPORT_LAYOUT_OLD    = 0x7000,
+  LIB3DS_VIEWPORT_DATA_OLD      = 0x7010,
+  LIB3DS_VIEWPORT_LAYOUT        = 0x7001,
+  LIB3DS_VIEWPORT_DATA          = 0x7011,
+  LIB3DS_VIEWPORT_DATA_3        = 0x7012,
+  LIB3DS_VIEWPORT_SIZE          = 0x7020,
+  LIB3DS_NETWORK_VIEW           = 0x7030
+} Lib3dsChunks;
+
+typedef struct _Lib3dsChunk {
+    Lib3dsWord chunk;
+    Lib3dsDword size;
+    Lib3dsDword end;
+    Lib3dsDword cur;
+} Lib3dsChunk; 
+
+extern LIB3DSAPI void lib3ds_chunk_enable_dump(Lib3dsBool enable, Lib3dsBool unknown);
+extern LIB3DSAPI Lib3dsBool lib3ds_chunk_read(Lib3dsChunk *c, Lib3dsIo *io);
+extern LIB3DSAPI Lib3dsBool lib3ds_chunk_read_start(Lib3dsChunk *c, Lib3dsWord chunk, Lib3dsIo *io);
+extern LIB3DSAPI void lib3ds_chunk_read_tell(Lib3dsChunk *c, Lib3dsIo *io);
+extern LIB3DSAPI Lib3dsWord lib3ds_chunk_read_next(Lib3dsChunk *c, Lib3dsIo *io);
+extern LIB3DSAPI void lib3ds_chunk_read_reset(Lib3dsChunk *c, Lib3dsIo *io);
+extern LIB3DSAPI void lib3ds_chunk_read_end(Lib3dsChunk *c, Lib3dsIo *io);
+extern LIB3DSAPI Lib3dsBool lib3ds_chunk_write(Lib3dsChunk *c, Lib3dsIo *io);
+extern LIB3DSAPI Lib3dsBool lib3ds_chunk_write_start(Lib3dsChunk *c, Lib3dsIo *io);
+extern LIB3DSAPI Lib3dsBool lib3ds_chunk_write_end(Lib3dsChunk *c, Lib3dsIo *io);
+extern LIB3DSAPI const char* lib3ds_chunk_name(Lib3dsWord chunk);
+extern LIB3DSAPI void lib3ds_chunk_unknown(Lib3dsWord chunk);
+extern LIB3DSAPI void lib3ds_chunk_dump_info(const char *format, ...);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+
diff --git a/src/3dengfx/libs/lib3ds/chunktable.h b/src/3dengfx/libs/lib3ds/chunktable.h
new file mode 100644 (file)
index 0000000..4942605
--- /dev/null
@@ -0,0 +1,264 @@
+/* -*- c -*- */
+#ifndef INCLUDED_LIB3DS_CHUNKTABLE_H
+#define INCLUDED_LIB3DS_CHUNKTABLE_H
+/*
+ * The 3D Studio File Format Library
+ * Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
+ * All rights reserved.
+ *
+ * This program is  free  software;  you can redistribute it and/or modify it
+ * under the terms of the  GNU Lesser General Public License  as published by
+ * the  Free Software Foundation;  either version 2.1 of the License,  or (at
+ * your option) any later version.
+ *
+ * This  program  is  distributed in  the  hope that it will  be useful,  but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public
+ * License for more details.
+ *
+ * You should  have received  a copy of the GNU Lesser General Public License
+ * along with  this program;  if not, write to the  Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: chunktable.h,v 1.13 2004/12/31 16:17:15 reed Exp $
+ */
+
+#ifndef INCLUDED_LIB3DS_CHUNK_H
+#include <lib3ds/chunk.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct _Lib3dsChunkTable {
+    Lib3dsDword chunk;
+    const char* name;
+} Lib3dsChunkTable;
+
+static Lib3dsChunkTable lib3ds_chunk_table[]={
+  {LIB3DS_NULL_CHUNK, "LIB3DS_NULL_CHUNK"},
+  {LIB3DS_M3DMAGIC, "LIB3DS_M3DMAGIC"},
+  {LIB3DS_SMAGIC, "LIB3DS_SMAGIC"},
+  {LIB3DS_LMAGIC, "LIB3DS_LMAGIC"},
+  {LIB3DS_MLIBMAGIC, "LIB3DS_MLIBMAGIC"},
+  {LIB3DS_MATMAGIC, "LIB3DS_MATMAGIC"},
+  {LIB3DS_CMAGIC, "LIB3DS_CMAGIC"},
+  {LIB3DS_M3D_VERSION, "LIB3DS_M3D_VERSION"},
+  {LIB3DS_M3D_KFVERSION, "LIB3DS_M3D_KFVERSION"},
+  {LIB3DS_COLOR_F, "LIB3DS_COLOR_F"},
+  {LIB3DS_COLOR_24, "LIB3DS_COLOR_24"},
+  {LIB3DS_LIN_COLOR_24, "LIB3DS_LIN_COLOR_24"},
+  {LIB3DS_LIN_COLOR_F, "LIB3DS_LIN_COLOR_F"},
+  {LIB3DS_INT_PERCENTAGE, "LIB3DS_INT_PERCENTAGE"},
+  {LIB3DS_FLOAT_PERCENTAGE, "LIB3DS_FLOAT_PERCENTAGE"},
+  {LIB3DS_MDATA, "LIB3DS_MDATA"},
+  {LIB3DS_MESH_VERSION, "LIB3DS_MESH_VERSION"},
+  {LIB3DS_MASTER_SCALE, "LIB3DS_MASTER_SCALE"},
+  {LIB3DS_LO_SHADOW_BIAS, "LIB3DS_LO_SHADOW_BIAS"},
+  {LIB3DS_HI_SHADOW_BIAS, "LIB3DS_HI_SHADOW_BIAS"},
+  {LIB3DS_SHADOW_MAP_SIZE, "LIB3DS_SHADOW_MAP_SIZE"},
+  {LIB3DS_SHADOW_SAMPLES, "LIB3DS_SHADOW_SAMPLES"},
+  {LIB3DS_SHADOW_RANGE, "LIB3DS_SHADOW_RANGE"},
+  {LIB3DS_SHADOW_FILTER, "LIB3DS_SHADOW_FILTER"},
+  {LIB3DS_RAY_BIAS, "LIB3DS_RAY_BIAS"},
+  {LIB3DS_O_CONSTS, "LIB3DS_O_CONSTS"},
+  {LIB3DS_AMBIENT_LIGHT, "LIB3DS_AMBIENT_LIGHT"},
+  {LIB3DS_BIT_MAP, "LIB3DS_BIT_MAP"},
+  {LIB3DS_SOLID_BGND, "LIB3DS_SOLID_BGND"},
+  {LIB3DS_V_GRADIENT, "LIB3DS_V_GRADIENT"},
+  {LIB3DS_USE_BIT_MAP, "LIB3DS_USE_BIT_MAP"},
+  {LIB3DS_USE_SOLID_BGND, "LIB3DS_USE_SOLID_BGND"},
+  {LIB3DS_USE_V_GRADIENT, "LIB3DS_USE_V_GRADIENT"},
+  {LIB3DS_FOG, "LIB3DS_FOG"},
+  {LIB3DS_FOG_BGND, "LIB3DS_FOG_BGND"},
+  {LIB3DS_LAYER_FOG, "LIB3DS_LAYER_FOG"},
+  {LIB3DS_DISTANCE_CUE, "LIB3DS_DISTANCE_CUE"},
+  {LIB3DS_DCUE_BGND, "LIB3DS_DCUE_BGND"},
+  {LIB3DS_USE_FOG, "LIB3DS_USE_FOG"},
+  {LIB3DS_USE_LAYER_FOG, "LIB3DS_USE_LAYER_FOG"},
+  {LIB3DS_USE_DISTANCE_CUE, "LIB3DS_USE_DISTANCE_CUE"},
+  {LIB3DS_MAT_ENTRY, "LIB3DS_MAT_ENTRY"},
+  {LIB3DS_MAT_NAME, "LIB3DS_MAT_NAME"},
+  {LIB3DS_MAT_AMBIENT, "LIB3DS_MAT_AMBIENT"},
+  {LIB3DS_MAT_DIFFUSE, "LIB3DS_MAT_DIFFUSE"},
+  {LIB3DS_MAT_SPECULAR, "LIB3DS_MAT_SPECULAR"},
+  {LIB3DS_MAT_SHININESS, "LIB3DS_MAT_SHININESS"},
+  {LIB3DS_MAT_SHIN2PCT, "LIB3DS_MAT_SHIN2PCT"},
+  {LIB3DS_MAT_TRANSPARENCY, "LIB3DS_MAT_TRANSPARENCY"},
+  {LIB3DS_MAT_XPFALL, "LIB3DS_MAT_XPFALL"},
+  {LIB3DS_MAT_USE_XPFALL, "LIB3DS_MAT_USE_XPFALL"},
+  {LIB3DS_MAT_REFBLUR, "LIB3DS_MAT_REFBLUR"},
+  {LIB3DS_MAT_SHADING, "LIB3DS_MAT_SHADING"},
+  {LIB3DS_MAT_USE_REFBLUR, "LIB3DS_MAT_USE_REFBLUR"},
+  {LIB3DS_MAT_SELF_ILLUM, "LIB3DS_MAT_SELF_ILLUM"},
+  {LIB3DS_MAT_TWO_SIDE, "LIB3DS_MAT_TWO_SIDE"},
+  {LIB3DS_MAT_DECAL, "LIB3DS_MAT_DECAL"},
+  {LIB3DS_MAT_ADDITIVE, "LIB3DS_MAT_ADDITIVE"},
+  {LIB3DS_MAT_SELF_ILPCT, "LIB3DS_MAT_SELF_ILPCT"},
+  {LIB3DS_MAT_WIRE, "LIB3DS_MAT_WIRE"},
+  {LIB3DS_MAT_FACEMAP, "LIB3DS_MAT_FACEMAP"},
+  {LIB3DS_MAT_PHONGSOFT, "LIB3DS_MAT_PHONGSOFT"},
+  {LIB3DS_MAT_WIREABS, "LIB3DS_MAT_WIREABS"},
+  {LIB3DS_MAT_WIRE_SIZE, "LIB3DS_MAT_WIRE_SIZE"},
+  {LIB3DS_MAT_TEXMAP, "LIB3DS_MAT_TEXMAP"},
+  {LIB3DS_MAT_SXP_TEXT_DATA, "LIB3DS_MAT_SXP_TEXT_DATA"},
+  {LIB3DS_MAT_TEXMASK, "LIB3DS_MAT_TEXMASK"},
+  {LIB3DS_MAT_SXP_TEXTMASK_DATA, "LIB3DS_MAT_SXP_TEXTMASK_DATA"},
+  {LIB3DS_MAT_TEX2MAP, "LIB3DS_MAT_TEX2MAP"},
+  {LIB3DS_MAT_SXP_TEXT2_DATA, "LIB3DS_MAT_SXP_TEXT2_DATA"},
+  {LIB3DS_MAT_TEX2MASK, "LIB3DS_MAT_TEX2MASK"},
+  {LIB3DS_MAT_SXP_TEXT2MASK_DATA, "LIB3DS_MAT_SXP_TEXT2MASK_DATA"},
+  {LIB3DS_MAT_OPACMAP, "LIB3DS_MAT_OPACMAP"},
+  {LIB3DS_MAT_SXP_OPAC_DATA, "LIB3DS_MAT_SXP_OPAC_DATA"},
+  {LIB3DS_MAT_OPACMASK, "LIB3DS_MAT_OPACMASK"},
+  {LIB3DS_MAT_SXP_OPACMASK_DATA, "LIB3DS_MAT_SXP_OPACMASK_DATA"},
+  {LIB3DS_MAT_BUMPMAP, "LIB3DS_MAT_BUMPMAP"},
+  {LIB3DS_MAT_SXP_BUMP_DATA, "LIB3DS_MAT_SXP_BUMP_DATA"},
+  {LIB3DS_MAT_BUMPMASK, "LIB3DS_MAT_BUMPMASK"},
+  {LIB3DS_MAT_SXP_BUMPMASK_DATA, "LIB3DS_MAT_SXP_BUMPMASK_DATA"},
+  {LIB3DS_MAT_SPECMAP, "LIB3DS_MAT_SPECMAP"},
+  {LIB3DS_MAT_SXP_SPEC_DATA, "LIB3DS_MAT_SXP_SPEC_DATA"},
+  {LIB3DS_MAT_SPECMASK, "LIB3DS_MAT_SPECMASK"},
+  {LIB3DS_MAT_SXP_SPECMASK_DATA, "LIB3DS_MAT_SXP_SPECMASK_DATA"},
+  {LIB3DS_MAT_SHINMAP, "LIB3DS_MAT_SHINMAP"},
+  {LIB3DS_MAT_SXP_SHIN_DATA, "LIB3DS_MAT_SXP_SHIN_DATA"},
+  {LIB3DS_MAT_SHINMASK, "LIB3DS_MAT_SHINMASK"},
+  {LIB3DS_MAT_SXP_SHINMASK_DATA, "LIB3DS_MAT_SXP_SHINMASK_DATA"},
+  {LIB3DS_MAT_SELFIMAP, "LIB3DS_MAT_SELFIMAP"},
+  {LIB3DS_MAT_SXP_SELFI_DATA, "LIB3DS_MAT_SXP_SELFI_DATA"},
+  {LIB3DS_MAT_SELFIMASK, "LIB3DS_MAT_SELFIMASK"},
+  {LIB3DS_MAT_SXP_SELFIMASK_DATA, "LIB3DS_MAT_SXP_SELFIMASK_DATA"},
+  {LIB3DS_MAT_REFLMAP, "LIB3DS_MAT_REFLMAP"},
+  {LIB3DS_MAT_REFLMASK, "LIB3DS_MAT_REFLMASK"},
+  {LIB3DS_MAT_SXP_REFLMASK_DATA, "LIB3DS_MAT_SXP_REFLMASK_DATA"},
+  {LIB3DS_MAT_ACUBIC, "LIB3DS_MAT_ACUBIC"},
+  {LIB3DS_MAT_MAPNAME, "LIB3DS_MAT_MAPNAME"},
+  {LIB3DS_MAT_MAP_TILING, "LIB3DS_MAT_MAP_TILING"},
+  {LIB3DS_MAT_MAP_TEXBLUR, "LIB3DS_MAT_MAP_TEXBLUR"},
+  {LIB3DS_MAT_MAP_USCALE, "LIB3DS_MAT_MAP_USCALE"},
+  {LIB3DS_MAT_MAP_VSCALE, "LIB3DS_MAT_MAP_VSCALE"},
+  {LIB3DS_MAT_MAP_UOFFSET, "LIB3DS_MAT_MAP_UOFFSET"},
+  {LIB3DS_MAT_MAP_VOFFSET, "LIB3DS_MAT_MAP_VOFFSET"},
+  {LIB3DS_MAT_MAP_ANG, "LIB3DS_MAT_MAP_ANG"},
+  {LIB3DS_MAT_MAP_COL1, "LIB3DS_MAT_MAP_COL1"},
+  {LIB3DS_MAT_MAP_COL2, "LIB3DS_MAT_MAP_COL2"},
+  {LIB3DS_MAT_MAP_RCOL, "LIB3DS_MAT_MAP_RCOL"},
+  {LIB3DS_MAT_MAP_GCOL, "LIB3DS_MAT_MAP_GCOL"},
+  {LIB3DS_MAT_MAP_BCOL, "LIB3DS_MAT_MAP_BCOL"},
+  {LIB3DS_NAMED_OBJECT, "LIB3DS_NAMED_OBJECT"},
+  {LIB3DS_N_DIRECT_LIGHT, "LIB3DS_N_DIRECT_LIGHT"},
+  {LIB3DS_DL_OFF, "LIB3DS_DL_OFF"},
+  {LIB3DS_DL_OUTER_RANGE, "LIB3DS_DL_OUTER_RANGE"},
+  {LIB3DS_DL_INNER_RANGE, "LIB3DS_DL_INNER_RANGE"},
+  {LIB3DS_DL_MULTIPLIER, "LIB3DS_DL_MULTIPLIER"},
+  {LIB3DS_DL_EXCLUDE, "LIB3DS_DL_EXCLUDE"},
+  {LIB3DS_DL_ATTENUATE, "LIB3DS_DL_ATTENUATE"},
+  {LIB3DS_DL_SPOTLIGHT, "LIB3DS_DL_SPOTLIGHT"},
+  {LIB3DS_DL_SPOT_ROLL, "LIB3DS_DL_SPOT_ROLL"},
+  {LIB3DS_DL_SHADOWED, "LIB3DS_DL_SHADOWED"},
+  {LIB3DS_DL_LOCAL_SHADOW2, "LIB3DS_DL_LOCAL_SHADOW2"},
+  {LIB3DS_DL_SEE_CONE, "LIB3DS_DL_SEE_CONE"},
+  {LIB3DS_DL_SPOT_RECTANGULAR, "LIB3DS_DL_SPOT_RECTANGULAR"},
+  {LIB3DS_DL_SPOT_ASPECT, "LIB3DS_DL_SPOT_ASPECT"},
+  {LIB3DS_DL_SPOT_PROJECTOR, "LIB3DS_DL_SPOT_PROJECTOR"},
+  {LIB3DS_DL_SPOT_OVERSHOOT, "LIB3DS_DL_SPOT_OVERSHOOT"},
+  {LIB3DS_DL_RAY_BIAS, "LIB3DS_DL_RAY_BIAS"},
+  {LIB3DS_DL_RAYSHAD, "LIB3DS_DL_RAYSHAD"},
+  {LIB3DS_N_CAMERA, "LIB3DS_N_CAMERA"},
+  {LIB3DS_CAM_SEE_CONE, "LIB3DS_CAM_SEE_CONE"},
+  {LIB3DS_CAM_RANGES, "LIB3DS_CAM_RANGES"},
+  {LIB3DS_OBJ_HIDDEN, "LIB3DS_OBJ_HIDDEN"},
+  {LIB3DS_OBJ_VIS_LOFTER, "LIB3DS_OBJ_VIS_LOFTER"},
+  {LIB3DS_OBJ_DOESNT_CAST, "LIB3DS_OBJ_DOESNT_CAST"},
+  {LIB3DS_OBJ_DONT_RECVSHADOW, "LIB3DS_OBJ_DONT_RECVSHADOW"},
+  {LIB3DS_OBJ_MATTE, "LIB3DS_OBJ_MATTE"},
+  {LIB3DS_OBJ_FAST, "LIB3DS_OBJ_FAST"},
+  {LIB3DS_OBJ_PROCEDURAL, "LIB3DS_OBJ_PROCEDURAL"},
+  {LIB3DS_OBJ_FROZEN, "LIB3DS_OBJ_FROZEN"},
+  {LIB3DS_N_TRI_OBJECT, "LIB3DS_N_TRI_OBJECT"},
+  {LIB3DS_POINT_ARRAY, "LIB3DS_POINT_ARRAY"},
+  {LIB3DS_POINT_FLAG_ARRAY, "LIB3DS_POINT_FLAG_ARRAY"},
+  {LIB3DS_FACE_ARRAY, "LIB3DS_FACE_ARRAY"},
+  {LIB3DS_MSH_MAT_GROUP, "LIB3DS_MSH_MAT_GROUP"},
+  {LIB3DS_SMOOTH_GROUP, "LIB3DS_SMOOTH_GROUP"},
+  {LIB3DS_MSH_BOXMAP, "LIB3DS_MSH_BOXMAP"},
+  {LIB3DS_TEX_VERTS, "LIB3DS_TEX_VERTS"},
+  {LIB3DS_MESH_MATRIX, "LIB3DS_MESH_MATRIX"},
+  {LIB3DS_MESH_COLOR, "LIB3DS_MESH_COLOR"},
+  {LIB3DS_MESH_TEXTURE_INFO, "LIB3DS_MESH_TEXTURE_INFO"},
+  {LIB3DS_KFDATA, "LIB3DS_KFDATA"},
+  {LIB3DS_KFHDR, "LIB3DS_KFHDR"},
+  {LIB3DS_KFSEG, "LIB3DS_KFSEG"},
+  {LIB3DS_KFCURTIME, "LIB3DS_KFCURTIME"},
+  {LIB3DS_AMBIENT_NODE_TAG, "LIB3DS_AMBIENT_NODE_TAG"},
+  {LIB3DS_OBJECT_NODE_TAG, "LIB3DS_OBJECT_NODE_TAG"},
+  {LIB3DS_CAMERA_NODE_TAG, "LIB3DS_CAMERA_NODE_TAG"},
+  {LIB3DS_TARGET_NODE_TAG, "LIB3DS_TARGET_NODE_TAG"},
+  {LIB3DS_LIGHT_NODE_TAG, "LIB3DS_LIGHT_NODE_TAG"},
+  {LIB3DS_L_TARGET_NODE_TAG, "LIB3DS_L_TARGET_NODE_TAG"},
+  {LIB3DS_SPOTLIGHT_NODE_TAG, "LIB3DS_SPOTLIGHT_NODE_TAG"},
+  {LIB3DS_NODE_ID, "LIB3DS_NODE_ID"},
+  {LIB3DS_NODE_HDR, "LIB3DS_NODE_HDR"},
+  {LIB3DS_PIVOT, "LIB3DS_PIVOT"},
+  {LIB3DS_INSTANCE_NAME, "LIB3DS_INSTANCE_NAME"},
+  {LIB3DS_MORPH_SMOOTH, "LIB3DS_MORPH_SMOOTH"},
+  {LIB3DS_BOUNDBOX, "LIB3DS_BOUNDBOX"},
+  {LIB3DS_POS_TRACK_TAG, "LIB3DS_POS_TRACK_TAG"},
+  {LIB3DS_COL_TRACK_TAG, "LIB3DS_COL_TRACK_TAG"},
+  {LIB3DS_ROT_TRACK_TAG, "LIB3DS_ROT_TRACK_TAG"},
+  {LIB3DS_SCL_TRACK_TAG, "LIB3DS_SCL_TRACK_TAG"},
+  {LIB3DS_MORPH_TRACK_TAG, "LIB3DS_MORPH_TRACK_TAG"},
+  {LIB3DS_FOV_TRACK_TAG, "LIB3DS_FOV_TRACK_TAG"},
+  {LIB3DS_ROLL_TRACK_TAG, "LIB3DS_ROLL_TRACK_TAG"},
+  {LIB3DS_HOT_TRACK_TAG, "LIB3DS_HOT_TRACK_TAG"},
+  {LIB3DS_FALL_TRACK_TAG, "LIB3DS_FALL_TRACK_TAG"},
+  {LIB3DS_HIDE_TRACK_TAG, "LIB3DS_HIDE_TRACK_TAG"},
+  {LIB3DS_POLY_2D, "LIB3DS_POLY_2D"},
+  {LIB3DS_SHAPE_OK, "LIB3DS_SHAPE_OK"},
+  {LIB3DS_SHAPE_NOT_OK, "LIB3DS_SHAPE_NOT_OK"},
+  {LIB3DS_SHAPE_HOOK, "LIB3DS_SHAPE_HOOK"},
+  {LIB3DS_PATH_3D, "LIB3DS_PATH_3D"},
+  {LIB3DS_PATH_MATRIX, "LIB3DS_PATH_MATRIX"},
+  {LIB3DS_SHAPE_2D, "LIB3DS_SHAPE_2D"},
+  {LIB3DS_M_SCALE, "LIB3DS_M_SCALE"},
+  {LIB3DS_M_TWIST, "LIB3DS_M_TWIST"},
+  {LIB3DS_M_TEETER, "LIB3DS_M_TEETER"},
+  {LIB3DS_M_FIT, "LIB3DS_M_FIT"},
+  {LIB3DS_M_BEVEL, "LIB3DS_M_BEVEL"},
+  {LIB3DS_XZ_CURVE, "LIB3DS_XZ_CURVE"},
+  {LIB3DS_YZ_CURVE, "LIB3DS_YZ_CURVE"},
+  {LIB3DS_INTERPCT, "LIB3DS_INTERPCT"},
+  {LIB3DS_DEFORM_LIMIT, "LIB3DS_DEFORM_LIMIT"},
+  {LIB3DS_USE_CONTOUR, "LIB3DS_USE_CONTOUR"},
+  {LIB3DS_USE_TWEEN, "LIB3DS_USE_TWEEN"},
+  {LIB3DS_USE_SCALE, "LIB3DS_USE_SCALE"},
+  {LIB3DS_USE_TWIST, "LIB3DS_USE_TWIST"},
+  {LIB3DS_USE_TEETER, "LIB3DS_USE_TEETER"},
+  {LIB3DS_USE_FIT, "LIB3DS_USE_FIT"},
+  {LIB3DS_USE_BEVEL, "LIB3DS_USE_BEVEL"},
+  {LIB3DS_DEFAULT_VIEW, "LIB3DS_DEFAULT_VIEW"},
+  {LIB3DS_VIEW_TOP, "LIB3DS_VIEW_TOP"},
+  {LIB3DS_VIEW_BOTTOM, "LIB3DS_VIEW_BOTTOM"},
+  {LIB3DS_VIEW_LEFT, "LIB3DS_VIEW_LEFT"},
+  {LIB3DS_VIEW_RIGHT, "LIB3DS_VIEW_RIGHT"},
+  {LIB3DS_VIEW_FRONT, "LIB3DS_VIEW_FRONT"},
+  {LIB3DS_VIEW_BACK, "LIB3DS_VIEW_BACK"},
+  {LIB3DS_VIEW_USER, "LIB3DS_VIEW_USER"},
+  {LIB3DS_VIEW_CAMERA, "LIB3DS_VIEW_CAMERA"},
+  {LIB3DS_VIEW_WINDOW, "LIB3DS_VIEW_WINDOW"},
+  {LIB3DS_VIEWPORT_LAYOUT_OLD, "LIB3DS_VIEWPORT_LAYOUT_OLD"},
+  {LIB3DS_VIEWPORT_DATA_OLD, "LIB3DS_VIEWPORT_DATA_OLD"},
+  {LIB3DS_VIEWPORT_LAYOUT, "LIB3DS_VIEWPORT_LAYOUT"},
+  {LIB3DS_VIEWPORT_DATA, "LIB3DS_VIEWPORT_DATA"},
+  {LIB3DS_VIEWPORT_DATA_3, "LIB3DS_VIEWPORT_DATA_3"},
+  {LIB3DS_VIEWPORT_SIZE, "LIB3DS_VIEWPORT_SIZE"},
+  {LIB3DS_NETWORK_VIEW, "LIB3DS_NETWORK_VIEW"},
+  {0,0}
+};
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/src/3dengfx/libs/lib3ds/ease.c b/src/3dengfx/libs/lib3ds/ease.c
new file mode 100644 (file)
index 0000000..745bf10
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * The 3D Studio File Format Library
+ * Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
+ * All rights reserved.
+ *
+ * This program is  free  software;  you can redistribute it and/or modify it
+ * under the terms of the  GNU Lesser General Public License  as published by 
+ * the  Free Software Foundation;  either version 2.1 of the License,  or (at 
+ * your option) any later version.
+ *
+ * This  program  is  distributed in  the  hope that it will  be useful,  but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public  
+ * License for more details.
+ *
+ * You should  have received  a copy of the GNU Lesser General Public License
+ * along with  this program;  if not, write to the  Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: ease.c,v 1.4 2001/01/12 10:29:17 jeh Exp $
+ */
+#define LIB3DS_EXPORT
+#include <lib3ds/ease.h>
+
+
+/*!
+ * \defgroup ease Ease
+ *
+ * \author J.E. Hoffmann <je-h@gmx.net>
+ */
+
+
+/*!
+ * \ingroup ease
+ */
+Lib3dsFloat
+lib3ds_ease(Lib3dsFloat fp, Lib3dsFloat fc, Lib3dsFloat fn,
+  Lib3dsFloat ease_from, Lib3dsFloat ease_to)
+{
+  Lib3dsDouble s,step;
+  Lib3dsDouble tofrom;
+  Lib3dsDouble a;
+
+  s=step=(Lib3dsFloat)(fc-fp)/(fn-fp);
+  tofrom=ease_to+ease_from;
+  if (tofrom!=0.0) {
+    if (tofrom>1.0) {
+      ease_to=(Lib3dsFloat)(ease_to/tofrom);
+      ease_from=(Lib3dsFloat)(ease_from/tofrom);
+    }
+    a=1.0/(2.0-(ease_to+ease_from));
+
+    if (step<ease_from) s=a/ease_from*step*step;
+    else {
+      if ((1.0-ease_to)<=step) {
+        step=1.0-step;
+        s=1.0-a/ease_to*step*step;
+      }
+      else {
+        s=((2.0*step)-ease_from)*a;
+      }
+    }
+  }
+  return((Lib3dsFloat)s);
+}
diff --git a/src/3dengfx/libs/lib3ds/ease.h b/src/3dengfx/libs/lib3ds/ease.h
new file mode 100644 (file)
index 0000000..1ed17bd
--- /dev/null
@@ -0,0 +1,41 @@
+/* -*- c -*- */
+#ifndef INCLUDED_LIB3DS_EASE_H
+#define INCLUDED_LIB3DS_EASE_H
+/*
+ * The 3D Studio File Format Library
+ * Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
+ * All rights reserved.
+ *
+ * This program is  free  software;  you can redistribute it and/or modify it
+ * under the terms of the  GNU Lesser General Public License  as published by 
+ * the  Free Software Foundation;  either version 2.1 of the License,  or (at 
+ * your option) any later version.
+ *
+ * This  program  is  distributed in  the  hope that it will  be useful,  but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public  
+ * License for more details.
+ *
+ * You should  have received  a copy of the GNU Lesser General Public License
+ * along with  this program;  if not, write to the  Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: ease.h,v 1.5 2004/12/31 16:17:15 reed Exp $
+ */
+
+#ifndef INCLUDED_LIB3DS_TYPES_H
+#include <lib3ds/types.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern LIB3DSAPI Lib3dsFloat lib3ds_ease(Lib3dsFloat fp, Lib3dsFloat fc, 
+  Lib3dsFloat fn, Lib3dsFloat ease_from, Lib3dsFloat ease_to);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/src/3dengfx/libs/lib3ds/file.c b/src/3dengfx/libs/lib3ds/file.c
new file mode 100644 (file)
index 0000000..33df4b9
--- /dev/null
@@ -0,0 +1,1917 @@
+/*
+ * The 3D Studio File Format Library
+ * Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
+ * All rights reserved.
+ *
+ * This program is  free  software;  you can redistribute it and/or modify it
+ * under the terms of the  GNU Lesser General Public License  as published by 
+ * the  Free Software Foundation;  either version 2.1 of the License,  or (at 
+ * your option) any later version.
+ *
+ * This  program  is  distributed in  the  hope that it will  be useful,  but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public  
+ * License for more details.
+ *
+ * You should  have received  a copy of the GNU Lesser General Public License
+ * along with  this program;  if not, write to the  Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: file.c,v 1.23 2005/01/11 10:20:36 madmac Exp $
+ */
+#define LIB3DS_EXPORT
+#include <lib3ds/file.h>
+#include <lib3ds/chunk.h>
+#include <lib3ds/io.h>
+#include <lib3ds/material.h>
+#include <lib3ds/mesh.h>
+#include <lib3ds/camera.h>
+#include <lib3ds/light.h>
+#include <lib3ds/node.h>
+#include <lib3ds/vector.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#ifdef WITH_DMALLOC
+#include <dmalloc.h>
+#endif
+
+
+
+/*!
+ * \defgroup file Files
+ *
+ * \author J.E. Hoffmann <je-h@gmx.net>
+ */
+
+
+static Lib3dsBool
+fileio_error_func(void *self)
+{
+  FILE *f = (FILE*)self;
+  return(ferror(f)!=0);
+}
+
+
+static long
+fileio_seek_func(void *self, long offset, Lib3dsIoSeek origin)
+{
+  FILE *f = (FILE*)self;
+  int o;
+  switch (origin) {
+    case LIB3DS_SEEK_SET:
+      o = SEEK_SET;
+      break;
+    case LIB3DS_SEEK_CUR:
+      o = SEEK_CUR;
+      break;
+    case LIB3DS_SEEK_END:
+      o = SEEK_END;
+      break;
+    default:
+      ASSERT(0);
+      return(0);
+  }
+  return (fseek(f, offset, o));
+}
+
+
+static long
+fileio_tell_func(void *self)
+{
+  FILE *f = (FILE*)self;
+  return(ftell(f));
+}
+
+
+static int
+fileio_read_func(void *self, Lib3dsByte *buffer, int size)
+{
+  FILE *f = (FILE*)self;
+  return(fread(buffer, 1, size, f));
+}
+
+
+static int
+fileio_write_func(void *self, const Lib3dsByte *buffer, int size)
+{
+  FILE *f = (FILE*)self;
+  return(fwrite(buffer, 1, size, f));
+}
+
+
+/*!
+ * Loads a .3DS file from disk into memory.
+ *
+ * \param filename  The filename of the .3DS file
+ *
+ * \return   A pointer to the Lib3dsFile structure containing the
+ *           data of the .3DS file. 
+ *           If the .3DS file can not be loaded NULL is returned.
+ *
+ * \note     To free the returned structure use lib3ds_free.
+ *
+ * \see lib3ds_file_save
+ * \see lib3ds_file_new
+ * \see lib3ds_file_free
+ *
+ * \ingroup file
+ */
+Lib3dsFile*
+lib3ds_file_load(const char *filename)
+{
+  FILE *f;
+  Lib3dsFile *file;
+  Lib3dsIo *io;
+
+
+  f = fopen(filename, "rb");
+  if (!f) {
+    return(0);
+  }
+  file = lib3ds_file_new();
+  if (!file) {
+    fclose(f);
+    return(0);
+  }
+  io = lib3ds_io_new(
+    f, 
+    fileio_error_func,
+    fileio_seek_func,
+    fileio_tell_func,
+    fileio_read_func,
+    fileio_write_func
+  );
+  if (!io) {
+    lib3ds_file_free(file);
+    fclose(f);
+    return(0);
+  }
+
+  if (!lib3ds_file_read(file, io)) {
+    free(file);
+    fclose(f);
+    return(0);
+  }
+
+  lib3ds_io_free(io);
+  fclose(f);
+  return(file);
+}
+
+
+/*!
+ * Saves a .3DS file from memory to disk.
+ *
+ * \param file      A pointer to a Lib3dsFile structure containing the
+ *                  the data that should be stored.
+ * \param filename  The filename of the .3DS file to store the data in.
+ *
+ * \return          TRUE on success, FALSE otherwise.
+ *
+ * \see lib3ds_file_load
+ *
+ * \ingroup file
+ */
+Lib3dsBool
+lib3ds_file_save(Lib3dsFile *file, const char *filename)
+{
+  FILE *f;
+  Lib3dsIo *io;
+  Lib3dsBool result;
+
+  f = fopen(filename, "wb");
+  if (!f) {
+    return(LIB3DS_FALSE);
+  }
+  io = lib3ds_io_new(
+    f, 
+    fileio_error_func,
+    fileio_seek_func,
+    fileio_tell_func,
+    fileio_read_func,
+    fileio_write_func
+  );
+  if (!io) {
+    fclose(f);
+    return LIB3DS_FALSE;
+  }
+  
+  result = lib3ds_file_write(file, io);
+
+  fclose(f);
+
+  lib3ds_io_free(io);
+  return(result);
+}
+
+
+/*!
+ * Creates and returns a new, empty Lib3dsFile object.
+ *
+ * \return     A pointer to the Lib3dsFile structure.
+ *             If the structure cannot be allocated, NULL is returned.
+ *
+ * \ingroup file
+ */
+Lib3dsFile*
+lib3ds_file_new()
+{
+  Lib3dsFile *file;
+
+  file=(Lib3dsFile*)calloc(sizeof(Lib3dsFile),1);
+  if (!file) {
+    return(0);
+  }
+  file->mesh_version=3;
+  file->master_scale=1.0f;
+  file->keyf_revision=5;
+  strcpy(file->name, "LIB3DS");
+
+  file->frames=100;
+  file->segment_from=0;
+  file->segment_to=100;
+  file->current_frame=0;
+
+  return(file);
+}
+
+
+/*!
+ * Free a Lib3dsFile object and all of its resources.
+ *
+ * \param file The Lib3dsFile object to be freed.
+ *
+ * \ingroup file
+ */
+void
+lib3ds_file_free(Lib3dsFile* file)
+{
+  ASSERT(file);
+  lib3ds_viewport_set_views(&file->viewport,0);
+  {
+    Lib3dsMaterial *p,*q;
+    
+    for (p=file->materials; p; p=q) {
+      q=p->next;
+      lib3ds_material_free(p);
+    }
+    file->materials=0;
+  }
+  {
+    Lib3dsCamera *p,*q;
+    
+    for (p=file->cameras; p; p=q) {
+      q=p->next;
+      lib3ds_camera_free(p);
+    }
+    file->cameras=0;
+  }
+  {
+    Lib3dsLight *p,*q;
+    
+    for (p=file->lights; p; p=q) {
+      q=p->next;
+      lib3ds_light_free(p);
+    }
+    file->lights=0;
+  }
+  {
+    Lib3dsMesh *p,*q;
+    
+    for (p=file->meshes; p; p=q) {
+      q=p->next;
+      lib3ds_mesh_free(p);
+    }
+    file->meshes=0;
+  }
+  {
+    Lib3dsNode *p,*q;
+  
+    for (p=file->nodes; p; p=q) {
+      q=p->next;
+      lib3ds_node_free(p);
+    }
+  }
+  free(file);
+}
+
+
+/*!
+ * Evaluate all of the nodes in this Lib3dsFile object.
+ *
+ * \param file The Lib3dsFile object to be evaluated.
+ * \param t time value, between 0. and file->frames
+ *
+ * \see lib3ds_node_eval
+ *
+ * \ingroup file
+ */
+void
+lib3ds_file_eval(Lib3dsFile *file, Lib3dsFloat t)
+{
+  Lib3dsNode *p;
+
+  for (p=file->nodes; p!=0; p=p->next) {
+    lib3ds_node_eval(p, t);
+  }
+}
+
+
+static Lib3dsBool
+named_object_read(Lib3dsFile *file, Lib3dsIo *io)
+{
+  Lib3dsChunk c;
+  char name[64];
+  Lib3dsWord chunk;
+
+  if (!lib3ds_chunk_read_start(&c, LIB3DS_NAMED_OBJECT, io)) {
+    return(LIB3DS_FALSE);
+  }
+  if (!lib3ds_io_read_string(io, name, 64)) {
+    return(LIB3DS_FALSE);
+  }
+  lib3ds_chunk_dump_info("  NAME=%s", name);
+  lib3ds_chunk_read_tell(&c, io);
+
+  while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) {
+    switch (chunk) {
+      case LIB3DS_N_TRI_OBJECT:
+        {
+          Lib3dsMesh *mesh;
+
+          mesh=lib3ds_mesh_new(name);
+          if (!mesh) {
+            return(LIB3DS_FALSE);
+          }
+          lib3ds_chunk_read_reset(&c, io);
+          if (!lib3ds_mesh_read(mesh, io)) {
+            return(LIB3DS_FALSE);
+          }
+          lib3ds_file_insert_mesh(file, mesh);
+        }
+        break;
+      case LIB3DS_N_CAMERA:
+        {
+          Lib3dsCamera *camera;
+
+          camera=lib3ds_camera_new(name);
+          if (!camera) {
+            return(LIB3DS_FALSE);
+          }
+          lib3ds_chunk_read_reset(&c, io);
+          if (!lib3ds_camera_read(camera, io)) {
+            return(LIB3DS_FALSE);
+          }
+          lib3ds_file_insert_camera(file, camera);
+        }
+        break;
+      case LIB3DS_N_DIRECT_LIGHT:
+        {
+          Lib3dsLight *light;
+
+          light=lib3ds_light_new(name);
+          if (!light) {
+            return(LIB3DS_FALSE);
+          }
+          lib3ds_chunk_read_reset(&c, io);
+          if (!lib3ds_light_read(light, io)) {
+            return(LIB3DS_FALSE);
+          }
+          lib3ds_file_insert_light(file, light);
+        }
+        break;
+      default:
+        lib3ds_chunk_unknown(chunk);
+    }
+  }
+  
+  lib3ds_chunk_read_end(&c, io);
+  return(LIB3DS_TRUE);
+}
+
+
+static Lib3dsBool
+ambient_read(Lib3dsFile *file, Lib3dsIo *io)
+{
+  Lib3dsChunk c;
+  Lib3dsWord chunk;
+  Lib3dsBool have_lin=LIB3DS_FALSE;
+
+  if (!lib3ds_chunk_read_start(&c, LIB3DS_AMBIENT_LIGHT, io)) {
+    return(LIB3DS_FALSE);
+  }
+
+  while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) {
+    switch (chunk) {
+      case LIB3DS_LIN_COLOR_F:
+        {
+          int i;
+          for (i=0; i<3; ++i) {
+            file->ambient[i]=lib3ds_io_read_float(io);
+          }
+        }
+        have_lin=LIB3DS_TRUE;
+        break;
+      case LIB3DS_COLOR_F:
+        {
+          /* gamma corrected color chunk
+             replaced in 3ds R3 by LIN_COLOR_24 */
+          if (!have_lin) {
+            int i;
+            for (i=0; i<3; ++i) {
+              file->ambient[i]=lib3ds_io_read_float(io);
+            }
+          }
+        }
+        break;
+      default:
+        lib3ds_chunk_unknown(chunk);
+    }
+  }
+  
+  lib3ds_chunk_read_end(&c, io);
+  return(LIB3DS_TRUE);
+}
+
+
+static Lib3dsBool
+mdata_read(Lib3dsFile *file, Lib3dsIo *io)
+{
+  Lib3dsChunk c;
+  Lib3dsWord chunk;
+
+  if (!lib3ds_chunk_read_start(&c, LIB3DS_MDATA, io)) {
+    return(LIB3DS_FALSE);
+  }
+  
+  while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) {
+    switch (chunk) {
+      case LIB3DS_MESH_VERSION:
+        {
+          file->mesh_version=lib3ds_io_read_intd(io);
+        }
+        break;
+      case LIB3DS_MASTER_SCALE:
+        {
+          file->master_scale=lib3ds_io_read_float(io);
+        }
+        break;
+      case LIB3DS_SHADOW_MAP_SIZE:
+      case LIB3DS_LO_SHADOW_BIAS:
+      case LIB3DS_HI_SHADOW_BIAS:
+      case LIB3DS_SHADOW_SAMPLES:
+      case LIB3DS_SHADOW_RANGE:
+      case LIB3DS_SHADOW_FILTER:
+      case LIB3DS_RAY_BIAS:
+        {
+          lib3ds_chunk_read_reset(&c, io);
+          if (!lib3ds_shadow_read(&file->shadow, io)) {
+            return(LIB3DS_FALSE);
+          }
+        }
+        break;
+      case LIB3DS_VIEWPORT_LAYOUT:
+      case LIB3DS_DEFAULT_VIEW:
+        {
+          lib3ds_chunk_read_reset(&c, io);
+          if (!lib3ds_viewport_read(&file->viewport, io)) {
+            return(LIB3DS_FALSE);
+          }
+        }
+        break;
+      case LIB3DS_O_CONSTS:
+        {
+          int i;
+          for (i=0; i<3; ++i) {
+            file->construction_plane[i]=lib3ds_io_read_float(io);
+          }
+        }
+        break;
+      case LIB3DS_AMBIENT_LIGHT:
+        {
+          lib3ds_chunk_read_reset(&c, io);
+          if (!ambient_read(file, io)) {
+            return(LIB3DS_FALSE);
+          }
+        }
+        break;
+      case LIB3DS_BIT_MAP:
+      case LIB3DS_SOLID_BGND:
+      case LIB3DS_V_GRADIENT:
+      case LIB3DS_USE_BIT_MAP:
+      case LIB3DS_USE_SOLID_BGND:
+      case LIB3DS_USE_V_GRADIENT:
+        {
+          lib3ds_chunk_read_reset(&c, io);
+          if (!lib3ds_background_read(&file->background, io)) {
+            return(LIB3DS_FALSE);
+          }
+        }
+        break;
+      case LIB3DS_FOG:
+      case LIB3DS_LAYER_FOG:
+      case LIB3DS_DISTANCE_CUE:
+      case LIB3DS_USE_FOG:
+      case LIB3DS_USE_LAYER_FOG:
+      case LIB3DS_USE_DISTANCE_CUE:
+        {
+          lib3ds_chunk_read_reset(&c, io);
+          if (!lib3ds_atmosphere_read(&file->atmosphere, io)) {
+            return(LIB3DS_FALSE);
+          }
+        }
+        break;
+      case LIB3DS_MAT_ENTRY:
+        {
+          Lib3dsMaterial *material;
+
+          material=lib3ds_material_new();
+          if (!material) {
+            return(LIB3DS_FALSE);
+          }
+          lib3ds_chunk_read_reset(&c, io);
+          if (!lib3ds_material_read(material, io)) {
+            return(LIB3DS_FALSE);
+          }
+          lib3ds_file_insert_material(file, material);
+        }
+        break;
+      case LIB3DS_NAMED_OBJECT:
+        {
+          lib3ds_chunk_read_reset(&c, io);
+          if (!named_object_read(file, io)) {
+            return(LIB3DS_FALSE);
+          }
+        }
+        break;
+      default:
+        lib3ds_chunk_unknown(chunk);
+    }
+  }
+
+  lib3ds_chunk_read_end(&c, io);
+  return(LIB3DS_TRUE);
+}
+
+
+static Lib3dsBool
+kfdata_read(Lib3dsFile *file, Lib3dsIo *io)
+{
+  Lib3dsChunk c;
+  Lib3dsWord chunk;
+
+  if (!lib3ds_chunk_read_start(&c, LIB3DS_KFDATA, io)) {
+    return(LIB3DS_FALSE);
+  }
+  
+  while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) {
+    switch (chunk) {
+      case LIB3DS_KFHDR:
+        {
+          file->keyf_revision=lib3ds_io_read_word(io);
+          if (!lib3ds_io_read_string(io, file->name, 12+1)) {
+            return(LIB3DS_FALSE);
+          }
+          file->frames=lib3ds_io_read_intd(io);
+        }
+        break;
+      case LIB3DS_KFSEG:
+        {
+          file->segment_from=lib3ds_io_read_intd(io);
+          file->segment_to=lib3ds_io_read_intd(io);
+        }
+        break;
+      case LIB3DS_KFCURTIME:
+        {
+          file->current_frame=lib3ds_io_read_intd(io);
+        }
+        break;
+      case LIB3DS_VIEWPORT_LAYOUT:
+      case LIB3DS_DEFAULT_VIEW:
+        {
+          lib3ds_chunk_read_reset(&c, io);
+          if (!lib3ds_viewport_read(&file->viewport_keyf, io)) {
+            return(LIB3DS_FALSE);
+          }
+        }
+        break;
+      case LIB3DS_AMBIENT_NODE_TAG:
+        {
+          Lib3dsNode *node;
+
+          node=lib3ds_node_new_ambient();
+          if (!node) {
+            return(LIB3DS_FALSE);
+          }
+          lib3ds_chunk_read_reset(&c, io);
+          if (!lib3ds_node_read(node, file, io)) {
+            return(LIB3DS_FALSE);
+          }
+          lib3ds_file_insert_node(file, node);
+        }
+        break;
+      case LIB3DS_OBJECT_NODE_TAG:
+        {
+          Lib3dsNode *node;
+
+          node=lib3ds_node_new_object();
+          if (!node) {
+            return(LIB3DS_FALSE);
+          }
+          lib3ds_chunk_read_reset(&c, io);
+          if (!lib3ds_node_read(node, file, io)) {
+            return(LIB3DS_FALSE);
+          }
+          lib3ds_file_insert_node(file, node);
+        }
+        break;
+      case LIB3DS_CAMERA_NODE_TAG:
+        {
+          Lib3dsNode *node;
+
+          node=lib3ds_node_new_camera();
+          if (!node) {
+            return(LIB3DS_FALSE);
+          }
+          lib3ds_chunk_read_reset(&c, io);
+          if (!lib3ds_node_read(node, file, io)) {
+            return(LIB3DS_FALSE);
+          }
+          lib3ds_file_insert_node(file, node);
+        }
+        break;
+      case LIB3DS_TARGET_NODE_TAG:
+        {
+          Lib3dsNode *node;
+
+          node=lib3ds_node_new_target();
+          if (!node) {
+            return(LIB3DS_FALSE);
+          }
+          lib3ds_chunk_read_reset(&c, io);
+          if (!lib3ds_node_read(node, file, io)) {
+            return(LIB3DS_FALSE);
+          }
+          lib3ds_file_insert_node(file, node);
+        }
+        break;
+      case LIB3DS_LIGHT_NODE_TAG:
+      case LIB3DS_SPOTLIGHT_NODE_TAG:
+        {
+          Lib3dsNode *node;
+
+          node=lib3ds_node_new_light();
+          if (!node) {
+            return(LIB3DS_FALSE);
+          }
+          lib3ds_chunk_read_reset(&c, io);
+          if (!lib3ds_node_read(node, file, io)) {
+            return(LIB3DS_FALSE);
+          }
+          lib3ds_file_insert_node(file, node);
+        }
+        break;
+      case LIB3DS_L_TARGET_NODE_TAG:
+        {
+          Lib3dsNode *node;
+
+          node=lib3ds_node_new_spot();
+          if (!node) {
+            return(LIB3DS_FALSE);
+          }
+          lib3ds_chunk_read_reset(&c, io);
+          if (!lib3ds_node_read(node, file, io)) {
+            return(LIB3DS_FALSE);
+          }
+          lib3ds_file_insert_node(file, node);
+        }
+        break;
+      default:
+        lib3ds_chunk_unknown(chunk);
+    }
+  }
+
+  lib3ds_chunk_read_end(&c, io);
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+ * Read 3ds file data into a Lib3dsFile object.
+ *
+ * \param file The Lib3dsFile object to be filled.
+ * \param io A Lib3dsIo object previously set up by the caller.
+ *
+ * \return LIB3DS_TRUE on success, LIB3DS_FALSE on failure.
+ *
+ * \ingroup file
+ */
+Lib3dsBool
+lib3ds_file_read(Lib3dsFile *file, Lib3dsIo *io)
+{
+  Lib3dsChunk c;
+  Lib3dsWord chunk;
+
+  if (!lib3ds_chunk_read_start(&c, 0, io)) {
+    return(LIB3DS_FALSE);
+  }
+  switch (c.chunk) {
+    case LIB3DS_MDATA:
+      {
+        lib3ds_chunk_read_reset(&c, io);
+        if (!mdata_read(file, io)) {
+          return(LIB3DS_FALSE);
+        }
+      }
+      break;
+    case LIB3DS_M3DMAGIC:
+    case LIB3DS_MLIBMAGIC:
+    case LIB3DS_CMAGIC:
+      {
+        while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) {
+          switch (chunk) {
+            case LIB3DS_M3D_VERSION:
+              {
+                file->mesh_version=lib3ds_io_read_dword(io);
+              }
+              break;
+            case LIB3DS_MDATA:
+              {
+                lib3ds_chunk_read_reset(&c, io);
+                if (!mdata_read(file, io)) {
+                  return(LIB3DS_FALSE);
+                }
+              }
+              break;
+            case LIB3DS_KFDATA:
+              {
+                lib3ds_chunk_read_reset(&c, io);
+                if (!kfdata_read(file, io)) {
+                  return(LIB3DS_FALSE);
+                }
+              }
+              break;
+            default:
+              lib3ds_chunk_unknown(chunk);
+          }
+        }
+      }
+      break;
+    default:
+      lib3ds_chunk_unknown(c.chunk);
+      return(LIB3DS_FALSE);
+  }
+
+  lib3ds_chunk_read_end(&c, io);
+  return(LIB3DS_TRUE);
+}
+
+
+static Lib3dsBool
+colorf_write(Lib3dsRgba rgb, Lib3dsIo *io)
+{
+  Lib3dsChunk c;
+
+  c.chunk=LIB3DS_COLOR_F;
+  c.size=18;
+  lib3ds_chunk_write(&c,io);
+  lib3ds_io_write_rgb(io, rgb);
+
+  c.chunk=LIB3DS_LIN_COLOR_F;
+  c.size=18;
+  lib3ds_chunk_write(&c,io);
+  lib3ds_io_write_rgb(io, rgb);
+  return(LIB3DS_TRUE);
+}
+
+
+static Lib3dsBool
+mdata_write(Lib3dsFile *file, Lib3dsIo *io)
+{
+  Lib3dsChunk c;
+
+  c.chunk=LIB3DS_MDATA;
+  if (!lib3ds_chunk_write_start(&c,io)) {
+    return(LIB3DS_FALSE);
+  }
+
+  { /*---- LIB3DS_MESH_VERSION ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_MESH_VERSION;
+    c.size=10;
+    lib3ds_chunk_write(&c,io);
+    lib3ds_io_write_intd(io, file->mesh_version);
+  }
+  { /*---- LIB3DS_MASTER_SCALE ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_MASTER_SCALE;
+    c.size=10;
+    lib3ds_chunk_write(&c,io);
+    lib3ds_io_write_float(io, file->master_scale);
+  }
+  { /*---- LIB3DS_O_CONSTS ----*/
+    int i;
+    for (i=0; i<3; ++i) {
+      if (fabs(file->construction_plane[i])>LIB3DS_EPSILON) {
+        break;
+      }
+    }
+    if (i<3) {
+      Lib3dsChunk c;
+      c.chunk=LIB3DS_O_CONSTS;
+      c.size=18;
+      lib3ds_chunk_write(&c,io);
+      lib3ds_io_write_vector(io, file->construction_plane);
+    }
+  }
+  
+  { /*---- LIB3DS_AMBIENT_LIGHT ----*/
+    int i;
+    for (i=0; i<3; ++i) {
+      if (fabs(file->ambient[i])>LIB3DS_EPSILON) {
+        break;
+      }
+    }
+    if (i<3) {
+      Lib3dsChunk c;
+      c.chunk=LIB3DS_AMBIENT_LIGHT;
+      c.size=42;
+      lib3ds_chunk_write(&c,io);
+      colorf_write(file->ambient,io);
+    }
+  }
+  lib3ds_background_write(&file->background, io);
+  lib3ds_atmosphere_write(&file->atmosphere, io);
+  lib3ds_shadow_write(&file->shadow, io);
+  lib3ds_viewport_write(&file->viewport, io);
+  {
+    Lib3dsMaterial *p;
+    for (p=file->materials; p!=0; p=p->next) {
+      if (!lib3ds_material_write(p,io)) {
+        return(LIB3DS_FALSE);
+      }
+    }
+  }
+  {
+    Lib3dsCamera *p;
+    Lib3dsChunk c;
+    
+    for (p=file->cameras; p!=0; p=p->next) {
+      c.chunk=LIB3DS_NAMED_OBJECT;
+      if (!lib3ds_chunk_write_start(&c,io)) {
+        return(LIB3DS_FALSE);
+      }
+      lib3ds_io_write_string(io, p->name);
+      lib3ds_camera_write(p,io);
+      if (!lib3ds_chunk_write_end(&c,io)) {
+        return(LIB3DS_FALSE);
+      }
+    }
+  }
+  {
+    Lib3dsLight *p;
+    Lib3dsChunk c;
+    
+    for (p=file->lights; p!=0; p=p->next) {
+      c.chunk=LIB3DS_NAMED_OBJECT;
+      if (!lib3ds_chunk_write_start(&c,io)) {
+        return(LIB3DS_FALSE);
+      }
+      lib3ds_io_write_string(io,p->name);
+      lib3ds_light_write(p,io);
+      if (!lib3ds_chunk_write_end(&c,io)) {
+        return(LIB3DS_FALSE);
+      }
+    }
+  }
+  {
+    Lib3dsMesh *p;
+    Lib3dsChunk c;
+    
+    for (p=file->meshes; p!=0; p=p->next) {
+      c.chunk=LIB3DS_NAMED_OBJECT;
+      if (!lib3ds_chunk_write_start(&c,io)) {
+        return(LIB3DS_FALSE);
+      }
+      lib3ds_io_write_string(io, p->name);
+      lib3ds_mesh_write(p,io);
+      if (!lib3ds_chunk_write_end(&c,io)) {
+        return(LIB3DS_FALSE);
+      }
+    }
+  }
+
+  if (!lib3ds_chunk_write_end(&c,io)) {
+    return(LIB3DS_FALSE);
+  }
+  return(LIB3DS_TRUE);
+}
+
+
+
+static Lib3dsBool
+nodes_write(Lib3dsNode *node, Lib3dsFile *file, Lib3dsIo *io)
+{
+  {
+    Lib3dsNode *p;
+    for (p=node->childs; p!=0; p=p->next) {
+      if (!lib3ds_node_write(p, file, io)) {
+        return(LIB3DS_FALSE);
+      }
+      nodes_write(p, file, io);
+    }
+  }
+  return(LIB3DS_TRUE);
+}
+
+
+static Lib3dsBool
+kfdata_write(Lib3dsFile *file, Lib3dsIo *io)
+{
+  Lib3dsChunk c;
+
+  if (!file->nodes) {
+    return(LIB3DS_TRUE);
+  }
+  
+  c.chunk=LIB3DS_KFDATA;
+  if (!lib3ds_chunk_write_start(&c,io)) {
+    return(LIB3DS_FALSE);
+  }
+  
+  { /*---- LIB3DS_KFHDR ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_KFHDR;
+    c.size=6 + 2 + strlen(file->name)+1 +4;
+    lib3ds_chunk_write(&c,io);
+    lib3ds_io_write_intw(io, file->keyf_revision);
+    lib3ds_io_write_string(io, file->name);
+    lib3ds_io_write_intd(io, file->frames);
+  }
+  { /*---- LIB3DS_KFSEG ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_KFSEG;
+    c.size=14;
+    lib3ds_chunk_write(&c,io);
+    lib3ds_io_write_intd(io, file->segment_from);
+    lib3ds_io_write_intd(io, file->segment_to);
+  }
+  { /*---- LIB3DS_KFCURTIME ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_KFCURTIME;
+    c.size=10;
+    lib3ds_chunk_write(&c,io);
+    lib3ds_io_write_intd(io, file->current_frame);
+  }
+  lib3ds_viewport_write(&file->viewport_keyf, io);
+  
+  {
+    Lib3dsNode *p;
+    for (p=file->nodes; p!=0; p=p->next) {
+      if (!lib3ds_node_write(p, file, io)) {
+        return(LIB3DS_FALSE);
+      }
+      if (!nodes_write(p, file, io)) {
+        return(LIB3DS_FALSE);
+      }
+    }
+  }
+  
+  if (!lib3ds_chunk_write_end(&c,io)) {
+    return(LIB3DS_FALSE);
+  }
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+ * Write 3ds file data from a Lib3dsFile object to a file.
+ *
+ * \param file The Lib3dsFile object to be written.
+ * \param io A Lib3dsIo object previously set up by the caller.
+ *
+ * \return LIB3DS_TRUE on success, LIB3DS_FALSE on failure.
+ *
+ * \ingroup file
+ */
+Lib3dsBool
+lib3ds_file_write(Lib3dsFile *file, Lib3dsIo *io)
+{
+  Lib3dsChunk c;
+
+  c.chunk=LIB3DS_M3DMAGIC;
+  if (!lib3ds_chunk_write_start(&c,io)) {
+    LIB3DS_ERROR_LOG;
+    return(LIB3DS_FALSE);
+  }
+
+  { /*---- LIB3DS_M3D_VERSION ----*/
+    Lib3dsChunk c;
+
+    c.chunk=LIB3DS_M3D_VERSION;
+    c.size=10;
+    lib3ds_chunk_write(&c,io);
+    lib3ds_io_write_dword(io, file->mesh_version);
+  }
+
+  if (!mdata_write(file, io)) {
+    return(LIB3DS_FALSE);
+  }
+  if (!kfdata_write(file, io)) {
+    return(LIB3DS_FALSE);
+  }
+
+  if (!lib3ds_chunk_write_end(&c,io)) {
+    return(LIB3DS_FALSE);
+  }
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+ * Insert a new Lib3dsMaterial object into the materials list of
+ * a Lib3dsFile object.
+ *
+ * The new Lib3dsMaterial object is inserted into the materials list
+ * in alphabetic order by name.
+ *
+ * \param file The Lib3dsFile object to be modified.
+ * \param material The Lib3dsMaterial object to be inserted into file->materials
+ *
+ * \ingroup file
+ */
+void
+lib3ds_file_insert_material(Lib3dsFile *file, Lib3dsMaterial *material)
+{
+  Lib3dsMaterial *p,*q;
+  
+  ASSERT(file);
+  ASSERT(material);
+  ASSERT(!material->next);
+
+  q=0;
+  for (p=file->materials; p!=0; p=p->next) {
+    if (strcmp(material->name, p->name)<0) {
+      break;
+    }
+    q=p;
+  }
+  if (!q) {
+    material->next=file->materials;
+    file->materials=material;
+  }
+  else {
+    material->next=q->next;
+    q->next=material;
+  }
+}
+
+
+/*!
+ * Remove a Lib3dsMaterial object from the materials list of
+ * a Lib3dsFile object.
+ *
+ * If the Lib3dsMaterial is not found in the materials list, nothing is
+ * done (except that an error log message may be generated.)
+ *
+ * \param file The Lib3dsFile object to be modified.
+ * \param material The Lib3dsMaterial object to be removed from file->materials
+ *
+ * \ingroup file
+ */
+void
+lib3ds_file_remove_material(Lib3dsFile *file, Lib3dsMaterial *material)
+{
+  Lib3dsMaterial *p,*q;
+
+  ASSERT(file);
+  ASSERT(material);
+  ASSERT(file->materials);
+  for (p=0,q=file->materials; q; p=q,q=q->next) {
+    if (q==material) {
+      break;
+    }
+  }
+  if (!q) {
+    ASSERT(LIB3DS_FALSE);
+    return;
+  }
+  if (!p) {
+    file->materials=material->next;
+  }
+  else {
+    p->next=q->next;
+  }
+  material->next=0;
+}
+
+
+/*!
+ * Return a Lib3dsMaterial object by name.
+ *
+ * \param file Lib3dsFile object to be searched.
+ * \param name Name of the Lib3dsMaterial object to be searched for.
+ *
+ * \return A pointer to the named Lib3dsMaterial, or NULL if not found.
+ *
+ * \ingroup file
+ */
+Lib3dsMaterial*
+lib3ds_file_material_by_name(Lib3dsFile *file, const char *name)
+{
+  Lib3dsMaterial *p;
+
+  ASSERT(file);
+  for (p=file->materials; p!=0; p=p->next) {
+    if (strcmp(p->name,name)==0) {
+      return(p);
+    }
+  }
+  return(0);
+}
+
+
+/*!
+ * Dump all Lib3dsMaterial objects found in a Lib3dsFile object.
+ *
+ * \param file Lib3dsFile object to be dumped.
+ *
+ * \see lib3ds_material_dump
+ *
+ * \ingroup file
+ */
+void
+lib3ds_file_dump_materials(Lib3dsFile *file)
+{
+  Lib3dsMaterial *p;
+
+  ASSERT(file);
+  for (p=file->materials; p!=0; p=p->next) {
+    lib3ds_material_dump(p);
+  }
+}
+
+
+/*!
+ * Insert a new Lib3dsMesh object into the meshes list of
+ * a Lib3dsFile object.
+ *
+ * The new Lib3dsMesh object is inserted into the meshes list
+ * in alphabetic order by name.
+ *
+ * \param file The Lib3dsFile object to be modified.
+ * \param material The Lib3dsMesh object to be inserted into file->meshes
+ *
+ * \ingroup file
+ */
+void
+lib3ds_file_insert_mesh(Lib3dsFile *file, Lib3dsMesh *mesh)
+{
+  Lib3dsMesh *p,*q;
+  
+  ASSERT(file);
+  ASSERT(mesh);
+  ASSERT(!mesh->next);
+
+  q=0;
+  for (p=file->meshes; p!=0; p=p->next) {
+    if (strcmp(mesh->name, p->name)<0) {
+      break;
+    }
+    q=p;
+  }
+  if (!q) {
+    mesh->next=file->meshes;
+    file->meshes=mesh;
+  }
+  else {
+    mesh->next=q->next;
+    q->next=mesh;
+  }
+}
+
+
+/*!
+ * Remove a Lib3dsMesh object from the meshes list of
+ * a Lib3dsFile object.
+ *
+ * If the Lib3dsMesh is not found in the meshes list, nothing is done
+ * (except that an error log message may be generated.)
+ *
+ * \param file The Lib3dsFile object to be modified.
+ * \param material The Lib3dsMesh object to be removed from file->meshes
+ *
+ * \ingroup file
+ */
+void
+lib3ds_file_remove_mesh(Lib3dsFile *file, Lib3dsMesh *mesh)
+{
+  Lib3dsMesh *p,*q;
+
+  ASSERT(file);
+  ASSERT(mesh);
+  ASSERT(file->meshes);
+  for (p=0,q=file->meshes; q; p=q,q=q->next) {
+    if (q==mesh) {
+      break;
+    }
+  }
+  if (!q) {
+    ASSERT(LIB3DS_FALSE);
+    return;
+  }
+  if (!p) {
+    file->meshes=mesh->next;
+  }
+  else {
+    p->next=q->next;
+  }
+  mesh->next=0;
+}
+
+
+/*!
+ * Return a Lib3dsMesh object from a Lib3dsFile by name.
+ *
+ * \param file Lib3dsFile object to be searched.
+ * \param name Name of the Lib3dsMesh object to be searched for.
+ *
+ * \return A pointer to the named Lib3dsMesh, or NULL if not found.
+ *
+ * \ingroup file
+ */
+Lib3dsMesh*
+lib3ds_file_mesh_by_name(Lib3dsFile *file, const char *name)
+{
+  Lib3dsMesh *p;
+
+  ASSERT(file);
+  for (p=file->meshes; p!=0; p=p->next) {
+    if (strcmp(p->name,name)==0) {
+      return(p);
+    }
+  }
+  return(0);
+}
+
+
+/*!
+ * Dump all Lib3dsMesh objects found in a Lib3dsFile object.
+ *
+ * \param file Lib3dsFile object to be dumped.
+ *
+ * \see lib3ds_mesh_dump
+ *
+ * \ingroup file
+ */
+void
+lib3ds_file_dump_meshes(Lib3dsFile *file)
+{
+  Lib3dsMesh *p;
+
+  ASSERT(file);
+  for (p=file->meshes; p!=0; p=p->next) {
+    lib3ds_mesh_dump(p);
+  }
+}
+
+
+static void
+dump_instances(Lib3dsNode *node, const char* parent)
+{
+  Lib3dsNode *p;
+  char name[255];
+
+  ASSERT(node);
+  ASSERT(parent);
+  strcpy(name, parent);
+  strcat(name, ".");
+  strcat(name, node->name);
+  if (node->type==LIB3DS_OBJECT_NODE) {
+    printf("  %s : %s\n", name, node->data.object.instance);
+  }
+  for (p=node->childs; p!=0; p=p->next) {
+    dump_instances(p, parent);
+  }
+}
+
+
+/*!
+ * Dump all Lib3dsNode object names found in a Lib3dsFile object.
+ *
+ * For each node of type OBJECT_NODE, its name and data.object.instance
+ * fields are printed to stdout.  Consider using lib3ds_file_dump_nodes()
+ * instead, as that function dumps more information.
+ *
+ * Nodes are dumped recursively.
+ *
+ * \param file Lib3dsFile object to be dumped.
+ *
+ * \see lib3ds_file_dump_nodes
+ *
+ * \ingroup file
+ */
+void
+lib3ds_file_dump_instances(Lib3dsFile *file)
+{
+  Lib3dsNode *p;
+
+  ASSERT(file);
+  for (p=file->nodes; p!=0; p=p->next) {
+    dump_instances(p,"");
+  }
+}
+
+
+/*!
+ * Insert a new Lib3dsCamera object into the cameras list of
+ * a Lib3dsFile object.
+ *
+ * The new Lib3dsCamera object is inserted into the cameras list
+ * in alphabetic order by name.
+ *
+ * \param file The Lib3dsFile object to be modified.
+ * \param material The Lib3dsCamera object to be inserted into file->cameras
+ *
+ * \ingroup file
+ */
+void
+lib3ds_file_insert_camera(Lib3dsFile *file, Lib3dsCamera *camera)
+{
+  Lib3dsCamera *p,*q;
+  
+  ASSERT(file);
+  ASSERT(camera);
+  ASSERT(!camera->next);
+
+  q=0;
+  for (p=file->cameras; p!=0; p=p->next) {
+    if (strcmp(camera->name, p->name)<0) {
+      break;
+    }
+    q=p;
+  }
+  if (!q) {
+    camera->next=file->cameras;
+    file->cameras=camera;
+  }
+  else {
+    camera->next=q->next;
+    q->next=camera;
+  }
+}
+
+
+/*!
+ * Remove a Lib3dsCamera object from the cameras list of
+ * a Lib3dsFile object.
+ *
+ * If the Lib3dsCamera is not found in the cameras list, nothing is done
+ * (except that an error log message may be generated.)
+ *
+ * \param file The Lib3dsFile object to be modified.
+ * \param material The Lib3dsCamera object to be removed from file->cameras
+ *
+ * \ingroup file
+ */
+void
+lib3ds_file_remove_camera(Lib3dsFile *file, Lib3dsCamera *camera)
+{
+  Lib3dsCamera *p,*q;
+
+  ASSERT(file);
+  ASSERT(camera);
+  ASSERT(file->cameras);
+  for (p=0,q=file->cameras; q; p=q,q=q->next) {
+    if (q==camera) {
+      break;
+    }
+  }
+  if (!q) {
+    ASSERT(LIB3DS_FALSE);
+    return;
+  }
+  if (!p) {
+    file->cameras=camera->next;
+  }
+  else {
+    p->next=q->next;
+  }
+  camera->next=0;
+}
+
+
+/*!
+ * Return a Lib3dsCamera object from a Lib3dsFile by name.
+ *
+ * \param file Lib3dsFile object to be searched.
+ * \param name Name of the Lib3dsCamera object to be searched for.
+ *
+ * \return A pointer to the named Lib3dsCamera, or NULL if not found.
+ *
+ * \ingroup file
+ */
+Lib3dsCamera*
+lib3ds_file_camera_by_name(Lib3dsFile *file, const char *name)
+{
+  Lib3dsCamera *p;
+
+  ASSERT(file);
+  for (p=file->cameras; p!=0; p=p->next) {
+    if (strcmp(p->name,name)==0) {
+      return(p);
+    }
+  }
+  return(0);
+}
+
+
+/*!
+ * Dump all Lib3dsCamera objects found in a Lib3dsFile object.
+ *
+ * \param file Lib3dsFile object to be dumped.
+ *
+ * \see lib3ds_camera_dump
+ *
+ * \ingroup file
+ */
+void
+lib3ds_file_dump_cameras(Lib3dsFile *file)
+{
+  Lib3dsCamera *p;
+
+  ASSERT(file);
+  for (p=file->cameras; p!=0; p=p->next) {
+    lib3ds_camera_dump(p);
+  }
+}
+
+
+/*!
+ * Insert a new Lib3dsLight object into the lights list of
+ * a Lib3dsFile object.
+ *
+ * The new Lib3dsLight object is inserted into the lights list
+ * in alphabetic order by name.
+ *
+ * \param file The Lib3dsFile object to be modified.
+ * \param material The Lib3dsLight object to be inserted into file->lights
+ *
+ * \ingroup file
+ */
+void
+lib3ds_file_insert_light(Lib3dsFile *file, Lib3dsLight *light)
+{
+  Lib3dsLight *p,*q;
+  
+  ASSERT(file);
+  ASSERT(light);
+  ASSERT(!light->next);
+
+  q=0;
+  for (p=file->lights; p!=0; p=p->next) {
+    if (strcmp(light->name, p->name)<0) {
+      break;
+    }
+    q=p;
+  }
+  if (!q) {
+    light->next=file->lights;
+    file->lights=light;
+  }
+  else {
+    light->next=q->next;
+    q->next=light;
+  }
+}
+
+
+/*!
+ * Remove a Lib3dsLight object from the lights list of
+ * a Lib3dsFile object.
+ *
+ * If the Lib3dsLight is not found in the lights list, nothing is done
+ * (except that an error log message may be generated.)
+ *
+ * \param file The Lib3dsFile object to be modified.
+ * \param material The Lib3dsLight object to be removed from file->lights
+ *
+ * \ingroup file
+ */
+void
+lib3ds_file_remove_light(Lib3dsFile *file, Lib3dsLight *light)
+{
+  Lib3dsLight *p,*q;
+
+  ASSERT(file);
+  ASSERT(light);
+  ASSERT(file->lights);
+  for (p=0,q=file->lights; q; p=q,q=q->next) {
+    if (q==light) {
+      break;
+    }
+  }
+  if (!q) {
+    ASSERT(LIB3DS_FALSE);
+    return;
+  }
+  if (!p) {
+    file->lights=light->next;
+  }
+  else {
+    p->next=q->next;
+  }
+  light->next=0;
+}
+
+
+/*!
+ * Return a Lib3dsLight object from a Lib3dsFile by name.
+ *
+ * \param file Lib3dsFile object to be searched.
+ * \param name Name of the Lib3dsLight object to be searched for.
+ *
+ * \return A pointer to the named Lib3dsLight, or NULL if not found.
+ *
+ * \ingroup file
+ */
+Lib3dsLight*
+lib3ds_file_light_by_name(Lib3dsFile *file, const char *name)
+{
+  Lib3dsLight *p;
+
+  ASSERT(file);
+  for (p=file->lights; p!=0; p=p->next) {
+    if (strcmp(p->name,name)==0) {
+      return(p);
+    }
+  }
+  return(0);
+}
+
+
+/*!
+ * Dump all Lib3dsLight objects found in a Lib3dsFile object.
+ *
+ * \param file Lib3dsFile object to be dumped.
+ *
+ * \see lib3ds_light_dump
+ *
+ * \ingroup file
+ */
+void
+lib3ds_file_dump_lights(Lib3dsFile *file)
+{
+  Lib3dsLight *p;
+
+  ASSERT(file);
+  for (p=file->lights; p!=0; p=p->next) {
+    lib3ds_light_dump(p);
+  }
+}
+
+
+/*!
+ * Compute the bounding box for Lib3dsFile objects.
+ *
+ * This function computes the bounding box for all meshes
+ * in the Lib3dsFile object.  Cameras and lights are not included.
+ *
+ * \param file The Lib3dsFile object to be examined.
+ * \param min Returned minimum x,y,z values.
+ * \param max Returned maximum x,y,z values.
+ *
+ * \ingroup file
+ */
+void
+lib3ds_object_bounding_box(Lib3dsFile *file, Lib3dsVector min, Lib3dsVector max)
+{
+  {
+    Lib3dsVector lmin, lmax;
+    Lib3dsMesh *p=file->meshes;
+
+    if (p) {
+      lib3ds_mesh_bounding_box(p, min, max);
+      p = p->next;  
+    }
+    while (p) {
+      lib3ds_mesh_bounding_box(p, lmin, lmax);
+      lib3ds_vector_min(min, lmin);
+      lib3ds_vector_max(max, lmax);
+      p=p->next;
+    }
+  }
+}  
+
+
+/*!
+ * Compute the bounding box for a Lib3dsFile.
+ *
+ * This function computes the bounding box for all meshes, cameras,
+ * and lights in the Lib3dsFile object.
+ *
+ * \param file The Lib3dsFile object to be examined.
+ * \param min Returned minimum x,y,z values.
+ * \param max Returned maximum x,y,z values.
+ *
+ * \ingroup file
+ */
+void
+lib3ds_file_bounding_box(Lib3dsFile *file, Lib3dsVector min, Lib3dsVector max)
+{
+  Lib3dsBool init=LIB3DS_FALSE;
+
+  {
+    Lib3dsVector lmin, lmax;
+    Lib3dsMesh *p=file->meshes;
+
+    if (!init && p) {
+      init = LIB3DS_TRUE;
+      lib3ds_mesh_bounding_box(p, min, max);
+      p = p->next;  
+    }
+    while (p) {
+      lib3ds_mesh_bounding_box(p, lmin, lmax);
+      lib3ds_vector_min(min, lmin);
+      lib3ds_vector_max(max, lmax);
+      p=p->next;
+    }
+  }
+  {
+    Lib3dsCamera *p=file->cameras;
+    if (!init && p) {
+      init = LIB3DS_TRUE;
+      lib3ds_vector_copy(min, p->position);
+      lib3ds_vector_copy(max, p->position);
+    }
+
+    while (p) {
+      lib3ds_vector_min(min, p->position);
+      lib3ds_vector_max(max, p->position);
+      lib3ds_vector_min(min, p->target);
+      lib3ds_vector_max(max, p->target);
+      p=p->next;
+    }
+  }
+  {
+    Lib3dsLight *p=file->lights;
+    if (!init && p) {
+      init = LIB3DS_TRUE;
+      lib3ds_vector_copy(min, p->position);
+      lib3ds_vector_copy(max, p->position);
+    }
+
+    while (p) {
+      lib3ds_vector_min(min, p->position);
+      lib3ds_vector_max(max, p->position);
+      if (p->spot_light) {
+        lib3ds_vector_min(min, p->spot);
+        lib3ds_vector_max(max, p->spot);
+      }
+      p=p->next;
+    }
+  }
+}  
+
+
+/*!
+ * Return a node object by name and type.
+ *
+ * This function performs a recursive search for the specified node.
+ * Both name and type must match.
+ *
+ * \param file The Lib3dsFile to be searched.
+ * \param name The target node name.
+ * \param type The target node type
+ *
+ * \return A pointer to the first matching node, or NULL if not found.
+ *
+ * \see lib3ds_node_by_name
+ *
+ * \ingroup file
+ */
+Lib3dsNode*
+lib3ds_file_node_by_name(Lib3dsFile *file, const char* name, Lib3dsNodeTypes type)
+{
+  Lib3dsNode *p,*q;
+
+  ASSERT(file);
+  for (p=file->nodes; p!=0; p=p->next) {
+    if ((p->type==type) && (strcmp(p->name, name)==0)) {
+      return(p);
+    }
+    q=lib3ds_node_by_name(p, name, type);
+    if (q) {
+      return(q);
+    }
+  }
+  return(0);
+}
+
+
+/*!
+ * Return a node object by id.
+ *
+ * This function performs a recursive search for the specified node.
+ *
+ * \param file The Lib3dsFile to be searched.
+ * \param node_id The target node id.
+ *
+ * \return A pointer to the first matching node, or NULL if not found.
+ *
+ * \see lib3ds_node_by_id
+ *
+ * \ingroup file
+ */
+Lib3dsNode*
+lib3ds_file_node_by_id(Lib3dsFile *file, Lib3dsWord node_id)
+{
+  Lib3dsNode *p,*q;
+
+  ASSERT(file);
+  for (p=file->nodes; p!=0; p=p->next) {
+    if (p->node_id==node_id) {
+      return(p);
+    }
+    q=lib3ds_node_by_id(p, node_id);
+    if (q) {
+      return(q);
+    }
+  }
+  return(0);
+}
+
+
+/*!
+ * Insert a new node into a Lib3dsFile object.
+ *
+ * If the node's parent_id structure is not LIB3DS_NO_PARENT and the
+ * specified parent is found inside the Lib3dsFile object, then the
+ * node is inserted as a child of that parent.  If the parent_id
+ * structure is LIB3DS_NO_PARENT or the specified parent is not found,
+ * then the node is inserted at the top level.
+ *
+ * Node is inserted in alphabetic order by name.
+ *
+ * Finally, if any other top-level nodes in file specify this node as
+ * their parent, they are relocated as a child of this node.
+ *
+ * \param file The Lib3dsFile object to be modified.
+ * \param node The node to be inserted into file
+ *
+ * \ingroup file
+ */
+void
+lib3ds_file_insert_node(Lib3dsFile *file, Lib3dsNode *node)
+{
+  Lib3dsNode *parent,*p,*n;
+  
+  ASSERT(node);
+  ASSERT(!node->next);
+  ASSERT(!node->parent);
+
+  parent=0;
+  if (node->parent_id!=LIB3DS_NO_PARENT) {
+    parent=lib3ds_file_node_by_id(file, node->parent_id);
+  }
+  node->parent=parent;
+  
+  if (!parent) {
+    for (p=0,n=file->nodes; n!=0; p=n,n=n->next) {
+      if (strcmp(n->name, node->name)>0) {
+        break;
+      }
+    }
+    if (!p) {
+      node->next=file->nodes;
+      file->nodes=node;
+    }
+    else {
+      node->next=p->next;
+      p->next=node;
+    }
+  }
+  else {
+    for (p=0,n=parent->childs; n!=0; p=n,n=n->next) {
+      if (strcmp(n->name, node->name)>0) {
+        break;
+      }
+    }
+    if (!p) {
+      node->next=parent->childs;
+      parent->childs=node;
+    }
+    else {
+      node->next=p->next;
+      p->next=node;
+    }
+  }
+
+  if (node->node_id!=LIB3DS_NO_PARENT) {
+    for (n=file->nodes; n!=0; n=p) {
+      p=n->next;
+      if (n->parent_id==node->node_id) {
+        lib3ds_file_remove_node(file, n);
+        lib3ds_file_insert_node(file, n);
+      }
+    }
+  }
+}
+
+
+/*!
+ * Remove a node from the a Lib3dsFile object.
+ *
+ * \param file The Lib3dsFile object to be modified.
+ * \param node The Lib3dsNode object to be removed from file
+ *
+ * \return LIB3DS_TRUE on success, LIB3DS_FALSE if node is not found in file
+ *
+ * \ingroup file
+ */
+Lib3dsBool
+lib3ds_file_remove_node(Lib3dsFile *file, Lib3dsNode *node)
+{
+  Lib3dsNode *p,*n;
+
+  if (node->parent) {
+    for (p=0,n=node->parent->childs; n; p=n,n=n->next) {
+      if (n==node) {
+        break;
+      }
+    }
+    if (!n) {
+      return(LIB3DS_FALSE);
+    }
+    
+    if (!p) {
+      node->parent->childs=n->next;
+    }
+    else {
+      p->next=n->next;
+    }
+  }
+  else {
+    for (p=0,n=file->nodes; n; p=n,n=n->next) {
+      if (n==node) {
+        break;
+      }
+    }
+    if (!n) {
+      return(LIB3DS_FALSE);
+    }
+    
+    if (!p) {
+      file->nodes=n->next;
+    }
+    else {
+      p->next=n->next;
+    }
+  }
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+ * Dump all node objects found in a Lib3dsFile object.
+ *
+ * Nodes are dumped recursively.
+ *
+ * \param file Lib3dsFile object to be dumped.
+ *
+ * \see lib3ds_node_dump
+ *
+ * \ingroup file
+ */
+void
+lib3ds_file_dump_nodes(Lib3dsFile *file)
+{
+  Lib3dsNode *p;
+
+  ASSERT(file);
+  for (p=file->nodes; p!=0; p=p->next) {
+    lib3ds_node_dump(p,1);
+  }
+}
+
+
+/*!
+
+\typedef Lib3dsFile
+  \ingroup file
+  \sa _Lib3dsFile
+
+*/
+
+
+
+/* Programming trick to force users to compile their source code against the
+ * correct headers.  The symbol lib3ds_version1_3 will be defined iff the users
+ * compile with the current version of <lib3ds/types.h>
+ */
+
+/*
+extern int lib3ds_version1_3;
+static const int *lib3ds_version = &lib3ds_version1_3;
+*/
diff --git a/src/3dengfx/libs/lib3ds/file.h b/src/3dengfx/libs/lib3ds/file.h
new file mode 100644 (file)
index 0000000..41ac690
--- /dev/null
@@ -0,0 +1,114 @@
+/* -*- c -*- */
+#ifndef INCLUDED_LIB3DS_FILE_H
+#define INCLUDED_LIB3DS_FILE_H
+/*
+ * The 3D Studio File Format Library
+ * Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
+ * All rights reserved.
+ *
+ * This program is  free  software;  you can redistribute it and/or modify it
+ * under the terms of the  GNU Lesser General Public License  as published by 
+ * the  Free Software Foundation;  either version 2.1 of the License,  or (at 
+ * your option) any later version.
+ *
+ * This  program  is  distributed in  the  hope that it will  be useful,  but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public  
+ * License for more details.
+ *
+ * You should  have received  a copy of the GNU Lesser General Public License
+ * along with  this program;  if not, write to the  Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: file.h,v 1.19 2005/06/13 11:29:10 madmac Exp $
+ */
+/* The symbol LIB3DS_VERSION contains the current version number                
+   which can be used to check the version at compile time.                      
+   The major, minor and micro version number is encoded as follows:             
+   Version x.y.z becomes the decimal number xyyzz. */                             
+#define LIB3DS_VERSION  10300                                                   
+
+#ifndef INCLUDED_LIB3DS_BACKGROUND_H
+#include <lib3ds/background.h>
+#endif
+#ifndef INCLUDED_LIB3DS_ATMOSPHERE_H
+#include <lib3ds/atmosphere.h>
+#endif
+#ifndef INCLUDED_LIB3DS_SHADOW_H
+#include <lib3ds/shadow.h>
+#endif
+#ifndef INCLUDED_LIB3DS_VIEWPORT_H
+#include <lib3ds/viewport.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*!
+ * 3ds file structure
+ * \ingroup file
+ */
+struct _Lib3dsFile {
+    Lib3dsDword mesh_version;
+    Lib3dsWord keyf_revision;
+    char name[12+1];
+    Lib3dsFloat master_scale;
+    Lib3dsVector construction_plane;
+    Lib3dsRgb ambient;
+    Lib3dsShadow shadow;
+    Lib3dsBackground background;
+    Lib3dsAtmosphere atmosphere;
+    Lib3dsViewport viewport;
+    Lib3dsViewport viewport_keyf;
+    Lib3dsIntd frames;
+    Lib3dsIntd segment_from;
+    Lib3dsIntd segment_to;
+    Lib3dsIntd current_frame;
+    Lib3dsMaterial *materials;
+    Lib3dsMesh *meshes;
+    Lib3dsCamera *cameras;
+    Lib3dsLight *lights;
+    Lib3dsNode *nodes;
+}; 
+
+extern LIB3DSAPI Lib3dsFile* lib3ds_file_load(const char *filename);
+extern LIB3DSAPI Lib3dsBool lib3ds_file_save(Lib3dsFile *file, const char *filename);
+extern LIB3DSAPI Lib3dsFile* lib3ds_file_new();
+extern LIB3DSAPI void lib3ds_file_free(Lib3dsFile *file);
+extern LIB3DSAPI void lib3ds_file_eval(Lib3dsFile *file, Lib3dsFloat t);
+extern LIB3DSAPI Lib3dsBool lib3ds_file_read(Lib3dsFile *file, Lib3dsIo *io);
+extern LIB3DSAPI Lib3dsBool lib3ds_file_write(Lib3dsFile *file, Lib3dsIo *io);
+extern LIB3DSAPI void lib3ds_file_insert_material(Lib3dsFile *file, Lib3dsMaterial *material);
+extern LIB3DSAPI void lib3ds_file_remove_material(Lib3dsFile *file, Lib3dsMaterial *material);
+extern LIB3DSAPI Lib3dsMaterial* lib3ds_file_material_by_name(Lib3dsFile *file, const char *name);
+extern LIB3DSAPI void lib3ds_file_dump_materials(Lib3dsFile *file);
+extern LIB3DSAPI void lib3ds_file_insert_mesh(Lib3dsFile *file, Lib3dsMesh *mesh);
+extern LIB3DSAPI void lib3ds_file_remove_mesh(Lib3dsFile *file, Lib3dsMesh *mesh);
+extern LIB3DSAPI Lib3dsMesh* lib3ds_file_mesh_by_name(Lib3dsFile *file, const char *name);
+extern LIB3DSAPI void lib3ds_file_dump_meshes(Lib3dsFile *file);
+extern LIB3DSAPI void lib3ds_file_dump_instances(Lib3dsFile *file);
+extern LIB3DSAPI void lib3ds_file_insert_camera(Lib3dsFile *file, Lib3dsCamera *camera);
+extern LIB3DSAPI void lib3ds_file_remove_camera(Lib3dsFile *file, Lib3dsCamera *camera);
+extern LIB3DSAPI Lib3dsCamera* lib3ds_file_camera_by_name(Lib3dsFile *file, const char *name);
+extern LIB3DSAPI void lib3ds_file_dump_cameras(Lib3dsFile *file);
+extern LIB3DSAPI void lib3ds_file_insert_light(Lib3dsFile *file, Lib3dsLight *light);
+extern LIB3DSAPI void lib3ds_file_remove_light(Lib3dsFile *file, Lib3dsLight *light);
+extern LIB3DSAPI Lib3dsLight* lib3ds_file_light_by_name(Lib3dsFile *file, const char *name);
+extern LIB3DSAPI void lib3ds_file_dump_lights(Lib3dsFile *file);
+extern LIB3DSAPI Lib3dsNode* lib3ds_file_node_by_name(Lib3dsFile *file, const char* name,
+  Lib3dsNodeTypes type);
+extern LIB3DSAPI Lib3dsNode* lib3ds_file_node_by_id(Lib3dsFile *file, Lib3dsWord node_id);
+extern LIB3DSAPI void lib3ds_file_insert_node(Lib3dsFile *file, Lib3dsNode *node);
+extern LIB3DSAPI Lib3dsBool lib3ds_file_remove_node(Lib3dsFile *file, Lib3dsNode *node);
+extern LIB3DSAPI void lib3ds_file_dump_nodes(Lib3dsFile *file);
+extern LIB3DSAPI void lib3ds_object_bounding_box(Lib3dsFile *file,
+                               Lib3dsVector min, Lib3dsVector max);
+extern LIB3DSAPI void lib3ds_file_bounding_box(Lib3dsFile *file,
+                               Lib3dsVector min, Lib3dsVector max);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/src/3dengfx/libs/lib3ds/float.c b/src/3dengfx/libs/lib3ds/float.c
new file mode 100644 (file)
index 0000000..4dd9eff
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * The 3D Studio File Format Library
+ * Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
+ * All rights reserved.
+ *
+ * This program is  free  software;  you can redistribute it and/or modify it
+ * under the terms of the  GNU Lesser General Public License  as published by 
+ * the  Free Software Foundation;  either version 2.1 of the License,  or (at 
+ * your option) any later version.
+ *
+ * This  program  is  distributed in  the  hope that it will  be useful,  but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public  
+ * License for more details.
+ *
+ * You should  have received  a copy of the GNU Lesser General Public License
+ * along with  this program;  if not, write to the  Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: float.c,v 1.4 2001/01/12 10:29:17 jeh Exp $
+ */
+#define LIB3DS_EXPORT
+#include <lib3ds/float.h>
+
+
+/*!
+ * \defgroup float Floating Point Mathematics
+ *
+ * \author J.E. Hoffmann <je-h@gmx.net>
+ */
+
+
+/*!
+ * \ingroup float
+ */
+Lib3dsFloat
+lib3ds_float_cubic(Lib3dsFloat a, Lib3dsFloat p, Lib3dsFloat q, Lib3dsFloat b, Lib3dsFloat t)
+{
+  Lib3dsDouble x,y,z,w;   
+
+  x=2*t*t*t - 3*t*t + 1;
+  y=-2*t*t*t + 3*t*t;
+  z=t*t*t - 2*t*t + t;
+  w=t*t*t - t*t;
+  return((Lib3dsFloat)(x*a + y*b + z*p + w*q));
+}
+
diff --git a/src/3dengfx/libs/lib3ds/float.h b/src/3dengfx/libs/lib3ds/float.h
new file mode 100644 (file)
index 0000000..9bb1366
--- /dev/null
@@ -0,0 +1,41 @@
+/* -*- c -*- */
+#ifndef INCLUDED_LIB3DS_FLOAT_H
+#define INCLUDED_LIB3DS_FLOAT_H
+/*
+ * The 3D Studio File Format Library
+ * Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
+ * All rights reserved.
+ *
+ * This program is  free  software;  you can redistribute it and/or modify it
+ * under the terms of the  GNU Lesser General Public License  as published by 
+ * the  Free Software Foundation;  either version 2.1 of the License,  or (at 
+ * your option) any later version.
+ *
+ * This  program  is  distributed in  the  hope that it will  be useful,  but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public  
+ * License for more details.
+ *
+ * You should  have received  a copy of the GNU Lesser General Public License
+ * along with  this program;  if not, write to the  Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: float.h,v 1.5 2004/12/31 16:17:15 reed Exp $
+ */
+
+#ifndef INCLUDED_LIB3DS_TYPES_H
+#include <lib3ds/types.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern LIB3DSAPI Lib3dsFloat lib3ds_float_cubic(Lib3dsFloat a, Lib3dsFloat p,
+  Lib3dsFloat q, Lib3dsFloat b, Lib3dsFloat t);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/src/3dengfx/libs/lib3ds/io.c b/src/3dengfx/libs/lib3ds/io.c
new file mode 100644 (file)
index 0000000..7fc604e
--- /dev/null
@@ -0,0 +1,524 @@
+/*
+ * The 3D Studio File Format Library
+ * Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
+ * All rights reserved.
+ *
+ * This program is  free  software;  you can redistribute it and/or modify it
+ * under the terms of the  GNU Lesser General Public License  as published by 
+ * the  Free Software Foundation;  either version 2.1 of the License,  or (at 
+ * your option) any later version.
+ *
+ * This  program  is  distributed in  the  hope that it will  be useful,  but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public  
+ * License for more details.
+ *
+ * You should  have received  a copy of the GNU Lesser General Public License
+ * along with  this program;  if not, write to the  Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: io.c,v 1.3 2001/07/11 13:47:35 jeh Exp $
+ */
+#define LIB3DS_EXPORT
+#include <lib3ds/io.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+/*!
+ * \defgroup io Binary Input/Ouput Abstraction Layer
+ *
+ * \author J.E. Hoffmann <je-h@gmx.net>
+ */
+
+
+struct _Lib3dsIo {
+  void *self;
+  Lib3dsIoErrorFunc error_func;
+  Lib3dsIoSeekFunc seek_func;
+  Lib3dsIoTellFunc tell_func;
+  Lib3dsIoReadFunc read_func;
+  Lib3dsIoWriteFunc write_func;
+};
+
+
+Lib3dsIo* 
+lib3ds_io_new(void *self, Lib3dsIoErrorFunc error_func, Lib3dsIoSeekFunc seek_func,
+  Lib3dsIoTellFunc tell_func, Lib3dsIoReadFunc read_func, Lib3dsIoWriteFunc write_func)
+{
+  Lib3dsIo *io = calloc(sizeof(Lib3dsIo),1);
+  ASSERT(io);
+  if (!io) {
+    return 0;
+  }
+
+  io->self = self;
+  io->error_func = error_func;
+  io->seek_func = seek_func;
+  io->tell_func = tell_func;
+  io->read_func = read_func;
+  io->write_func = write_func;
+
+  return io;
+}
+
+
+void 
+lib3ds_io_free(Lib3dsIo *io)
+{
+  ASSERT(io);
+  if (!io) {
+    return;
+  }
+  free(io);
+}
+
+
+Lib3dsBool
+lib3ds_io_error(Lib3dsIo *io)
+{
+  ASSERT(io);
+  if (!io || !io->error_func) {
+    return 0;
+  }
+  return (*io->error_func)(io->self);
+}
+
+
+long 
+lib3ds_io_seek(Lib3dsIo *io, long offset, Lib3dsIoSeek origin)
+{
+  ASSERT(io);
+  if (!io || !io->seek_func) {
+    return 0;
+  }
+  return (*io->seek_func)(io->self, offset, origin);
+}
+
+
+long 
+lib3ds_io_tell(Lib3dsIo *io)
+{
+  ASSERT(io);
+  if (!io || !io->tell_func) {
+    return 0;
+  }
+  return (*io->tell_func)(io->self);
+}
+
+
+int 
+lib3ds_io_read(Lib3dsIo *io, Lib3dsByte *buffer, int size)
+{
+  ASSERT(io);
+  if (!io || !io->read_func) {
+    return 0;
+  }
+  return (*io->read_func)(io->self, buffer, size);
+}
+
+
+int 
+lib3ds_io_write(Lib3dsIo *io, const Lib3dsByte *buffer, int size)
+{
+  ASSERT(io);
+  if (!io || !io->write_func) {
+    return 0;
+  }
+  return (*io->write_func)(io->self, buffer, size);
+}
+
+
+/*!
+ * \ingroup io
+ *
+ * Read a byte from a file stream.  
+ */
+Lib3dsByte
+lib3ds_io_read_byte(Lib3dsIo *io)
+{
+  Lib3dsByte b;
+
+  ASSERT(io);
+  lib3ds_io_read(io, &b, 1);
+  return(b);
+}
+
+
+/**
+ * Read a word from a file stream in little endian format.   
+ */
+Lib3dsWord
+lib3ds_io_read_word(Lib3dsIo *io)
+{
+  Lib3dsByte b[2];
+  Lib3dsWord w;
+
+  ASSERT(io);
+  lib3ds_io_read(io, b, 2);
+  w=((Lib3dsWord)b[1] << 8) |
+    ((Lib3dsWord)b[0]);
+  return(w);
+}
+
+
+/*!
+ * \ingroup io
+ *
+ * Read a dword from file a stream in little endian format.   
+ */
+Lib3dsDword
+lib3ds_io_read_dword(Lib3dsIo *io)
+{
+  Lib3dsByte b[4];
+  Lib3dsDword d;        
+                         
+  ASSERT(io);
+  lib3ds_io_read(io, b, 4);
+  d=((Lib3dsDword)b[3] << 24) |
+    ((Lib3dsDword)b[2] << 16) |
+    ((Lib3dsDword)b[1] << 8) |
+    ((Lib3dsDword)b[0]);
+  return(d);
+}
+
+
+/*!
+ * \ingroup io
+ *
+ * Read a signed byte from a file stream.   
+ */
+Lib3dsIntb
+lib3ds_io_read_intb(Lib3dsIo *io)
+{
+  Lib3dsIntb b;
+
+  ASSERT(io);
+  lib3ds_io_read(io, (Lib3dsByte*)&b, 1);
+  return(b);
+}
+
+
+/*!
+ * \ingroup io
+ *
+ * Read a signed word from a file stream in little endian format.   
+ */
+Lib3dsIntw
+lib3ds_io_read_intw(Lib3dsIo *io)
+{
+  Lib3dsByte b[2];
+  Lib3dsWord w;
+
+  ASSERT(io);
+  lib3ds_io_read(io, b, 2);
+  w=((Lib3dsWord)b[1] << 8) |
+    ((Lib3dsWord)b[0]);
+  return((Lib3dsIntw)w);
+}
+
+
+/*!
+ * \ingroup io
+ *
+ * Read a signed dword a from file stream in little endian format.   
+ */
+Lib3dsIntd
+lib3ds_io_read_intd(Lib3dsIo *io)
+{
+  Lib3dsByte b[4];
+  Lib3dsDword d;        
+                         
+  ASSERT(io);
+  lib3ds_io_read(io, b, 4);
+  d=((Lib3dsDword)b[3] << 24) |
+    ((Lib3dsDword)b[2] << 16) |
+    ((Lib3dsDword)b[1] << 8) |
+    ((Lib3dsDword)b[0]);
+  return((Lib3dsIntd)d);
+}
+
+
+/*!
+ * \ingroup io
+ *
+ * Read a float from a file stream in little endian format.   
+ */
+Lib3dsFloat
+lib3ds_io_read_float(Lib3dsIo *io)
+{
+  Lib3dsByte b[4];
+  Lib3dsDword d;
+
+  ASSERT(io);
+  lib3ds_io_read(io, b, 4);
+  d=((Lib3dsDword)b[3] << 24) |
+    ((Lib3dsDword)b[2] << 16) |
+    ((Lib3dsDword)b[1] << 8) |
+    ((Lib3dsDword)b[0]);
+  return(*((Lib3dsFloat*)&d));
+}
+
+
+/*!
+ * \ingroup io
+ * \ingroup vector
+ *
+ * Read a vector from a file stream in little endian format.   
+ *
+ * \param io IO input handle. 
+ * \param v  The vector to store the data. 
+ */
+Lib3dsBool
+lib3ds_io_read_vector(Lib3dsIo *io, Lib3dsVector v)
+{
+  ASSERT(io);
+  
+  v[0]=lib3ds_io_read_float(io);
+  v[1]=lib3ds_io_read_float(io);
+  v[2]=lib3ds_io_read_float(io);
+
+  return(!lib3ds_io_error(io));
+}
+
+
+/*!
+ * \ingroup io
+ */
+Lib3dsBool
+lib3ds_io_read_rgb(Lib3dsIo *io, Lib3dsRgb rgb)
+{
+  ASSERT(io);
+
+  rgb[0]=lib3ds_io_read_float(io);
+  rgb[1]=lib3ds_io_read_float(io);
+  rgb[2]=lib3ds_io_read_float(io);
+
+  return(!lib3ds_io_error(io));
+}
+
+
+/*!
+ * \ingroup io
+ *
+ * Read a zero-terminated string from a file stream.
+ *
+ * \param io      IO input handle. 
+ * \param s       The buffer to store the read string.
+ * \param buflen  Buffer length.
+ *
+ * \return        True on success, False otherwise.
+ */
+Lib3dsBool
+lib3ds_io_read_string(Lib3dsIo *io, char *s, int buflen)
+{
+  char c;
+  int k=0;
+
+  ASSERT(io);
+  for (;;) {
+    if (lib3ds_io_read(io, (Lib3dsByte*)&c, 1)!=1) {
+      return LIB3DS_FALSE;
+    }
+    *s++ = c;
+    if (!c) {
+      break;
+    }
+    ++k;
+    if (k>=buflen) {
+      return(LIB3DS_FALSE);
+    }
+  }
+
+  return(!lib3ds_io_error(io));
+}
+
+
+/*!
+ * \ingroup io
+ *
+ * Writes a byte into a file stream.
+ */
+Lib3dsBool
+lib3ds_io_write_byte(Lib3dsIo *io, Lib3dsByte b)
+{
+  ASSERT(io);
+  if (lib3ds_io_write(io, &b, 1)!=1) {
+    return(LIB3DS_FALSE);
+  }
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+ * \ingroup io
+ *
+ * Writes a word into a little endian file stream.
+ */
+Lib3dsBool
+lib3ds_io_write_word(Lib3dsIo *io, Lib3dsWord w)
+{
+  Lib3dsByte b[2];
+
+  ASSERT(io);
+  b[1]=((Lib3dsWord)w & 0xFF00) >> 8;
+  b[0]=((Lib3dsWord)w & 0x00FF);
+  if (lib3ds_io_write(io, b, 2)!=2) {
+    return(LIB3DS_FALSE);
+  }
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+ * \ingroup io
+ *
+ * Writes a dword into a little endian file stream.
+ */
+Lib3dsBool
+lib3ds_io_write_dword(Lib3dsIo *io, Lib3dsDword d)
+{
+  Lib3dsByte b[4];
+
+  ASSERT(io);
+  b[3]=(Lib3dsByte)(((Lib3dsDword)d & 0xFF000000) >> 24);
+  b[2]=(Lib3dsByte)(((Lib3dsDword)d & 0x00FF0000) >> 16);
+  b[1]=(Lib3dsByte)(((Lib3dsDword)d & 0x0000FF00) >> 8);
+  b[0]=(Lib3dsByte)(((Lib3dsDword)d & 0x000000FF));
+  if (lib3ds_io_write(io, b, 4)!=4) {
+    return(LIB3DS_FALSE);
+  }
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+ * \ingroup io
+ *
+ * Writes a signed byte in a file stream.
+ */
+Lib3dsBool
+lib3ds_io_write_intb(Lib3dsIo *io, Lib3dsIntb b)
+{
+  ASSERT(io);
+  if (lib3ds_io_write(io, (Lib3dsByte*)&b, 1)!=1) {
+    return(LIB3DS_FALSE);
+  }
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+ * \ingroup io
+ *
+ * Writes a signed word into a little endian file stream.
+ */
+Lib3dsBool
+lib3ds_io_write_intw(Lib3dsIo *io, Lib3dsIntw w)
+{
+  Lib3dsByte b[2];
+
+  ASSERT(io);
+  b[1]=((Lib3dsWord)w & 0xFF00) >> 8;
+  b[0]=((Lib3dsWord)w & 0x00FF);
+  if (lib3ds_io_write(io, b, 2)!=2) {
+    return(LIB3DS_FALSE);
+  }
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+ * \ingroup io
+ *
+ * Writes a signed dword into a little endian file stream.
+ */
+Lib3dsBool
+lib3ds_io_write_intd(Lib3dsIo *io, Lib3dsIntd d)
+{
+  Lib3dsByte b[4];
+
+  ASSERT(io);
+  b[3]=(Lib3dsByte)(((Lib3dsDword)d & 0xFF000000) >> 24);
+  b[2]=(Lib3dsByte)(((Lib3dsDword)d & 0x00FF0000) >> 16);
+  b[1]=(Lib3dsByte)(((Lib3dsDword)d & 0x0000FF00) >> 8);
+  b[0]=(Lib3dsByte)(((Lib3dsDword)d & 0x000000FF));
+  if (lib3ds_io_write(io, b, 4)!=4) {
+    return(LIB3DS_FALSE);
+  }
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+ * \ingroup io
+ *
+ * Writes a float into a little endian file stream.
+ */
+Lib3dsBool
+lib3ds_io_write_float(Lib3dsIo *io, Lib3dsFloat l)
+{
+  Lib3dsByte b[4];
+  Lib3dsDword d;
+
+  ASSERT(io);
+  d=*((Lib3dsDword*)&l);
+  b[3]=(Lib3dsByte)(((Lib3dsDword)d & 0xFF000000) >> 24);
+  b[2]=(Lib3dsByte)(((Lib3dsDword)d & 0x00FF0000) >> 16);
+  b[1]=(Lib3dsByte)(((Lib3dsDword)d & 0x0000FF00) >> 8);
+  b[0]=(Lib3dsByte)(((Lib3dsDword)d & 0x000000FF));
+  if (lib3ds_io_write(io, b, 4)!=4) {
+    return(LIB3DS_FALSE);
+  }
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+ * \ingroup io
+ * \ingroup vector
+ *
+ * Writes a vector into a file stream in little endian format.   
+ */
+Lib3dsBool
+lib3ds_io_write_vector(Lib3dsIo *io, Lib3dsVector v)
+{
+  int i;
+  for (i=0; i<3; ++i) {
+    if (!lib3ds_io_write_float(io, v[i])) {
+      return(LIB3DS_FALSE);
+    }
+  }
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+ * \ingroup io
+ */
+Lib3dsBool
+lib3ds_io_write_rgb(Lib3dsIo *io, Lib3dsRgb rgb)
+{
+  int i;
+  for (i=0; i<3; ++i) {
+    if (!lib3ds_io_write_float(io, rgb[i])) {
+      return(LIB3DS_FALSE);
+    }
+  }
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+ * \ingroup io
+ *
+ * Writes a zero-terminated string into a file stream.
+ */
+Lib3dsBool
+lib3ds_io_write_string(Lib3dsIo *io, const char *s)
+{
+  ASSERT(s);
+  ASSERT(io);
+  lib3ds_io_write(io, (const Lib3dsByte*)s, strlen(s)+1);
+  return(!lib3ds_io_error(io));
+}
diff --git a/src/3dengfx/libs/lib3ds/io.h b/src/3dengfx/libs/lib3ds/io.h
new file mode 100644 (file)
index 0000000..453bc25
--- /dev/null
@@ -0,0 +1,82 @@
+/* -*- c -*- */
+#ifndef INCLUDED_LIB3DS_IO_H
+#define INCLUDED_LIB3DS_IO_H
+/*
+ * The 3D Studio File Format Library
+ * Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
+ * All rights reserved.
+ *
+ * This program is  free  software;  you can redistribute it and/or modify it
+ * under the terms of the  GNU Lesser General Public License  as published by 
+ * the  Free Software Foundation;  either version 2.1 of the License,  or (at 
+ * your option) any later version.
+ *
+ * This  program  is  distributed in  the  hope that it will  be useful,  but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public  
+ * License for more details.
+ *
+ * You should  have received  a copy of the GNU Lesser General Public License
+ * along with  this program;  if not, write to the  Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: io.h,v 1.3 2004/12/31 16:17:15 reed Exp $
+ */
+
+#ifndef INCLUDED_LIB3DS_TYPES_H
+#include <lib3ds/types.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum _Lib3dsIoSeek {
+  LIB3DS_SEEK_SET  =0,
+  LIB3DS_SEEK_CUR  =1,
+  LIB3DS_SEEK_END  =2
+} Lib3dsIoSeek;
+  
+typedef Lib3dsBool (*Lib3dsIoErrorFunc)(void *self);
+typedef long (*Lib3dsIoSeekFunc)(void *self, long offset, Lib3dsIoSeek origin);
+typedef long (*Lib3dsIoTellFunc)(void *self);
+typedef int (*Lib3dsIoReadFunc)(void *self, Lib3dsByte *buffer, int size);
+typedef int (*Lib3dsIoWriteFunc)(void *self, const Lib3dsByte *buffer, int size);
+
+extern LIB3DSAPI Lib3dsIo* lib3ds_io_new(void *self, Lib3dsIoErrorFunc error_func,
+  Lib3dsIoSeekFunc seek_func, Lib3dsIoTellFunc tell_func,
+  Lib3dsIoReadFunc read_func, Lib3dsIoWriteFunc write_func);
+extern LIB3DSAPI void lib3ds_io_free(Lib3dsIo *io);
+extern LIB3DSAPI Lib3dsBool lib3ds_io_error(Lib3dsIo *io);
+extern LIB3DSAPI long lib3ds_io_seek(Lib3dsIo *io, long offset, Lib3dsIoSeek origin);
+extern LIB3DSAPI long lib3ds_io_tell(Lib3dsIo *io);
+extern LIB3DSAPI int lib3ds_io_read(Lib3dsIo *io, Lib3dsByte *buffer, int size);
+extern LIB3DSAPI int lib3ds_io_write(Lib3dsIo *io, const Lib3dsByte *buffer, int size);
+
+extern LIB3DSAPI Lib3dsByte lib3ds_io_read_byte(Lib3dsIo *io);
+extern LIB3DSAPI Lib3dsWord lib3ds_io_read_word(Lib3dsIo *io);
+extern LIB3DSAPI Lib3dsDword lib3ds_io_read_dword(Lib3dsIo *io);
+extern LIB3DSAPI Lib3dsIntb lib3ds_io_read_intb(Lib3dsIo *io);
+extern LIB3DSAPI Lib3dsIntw lib3ds_io_read_intw(Lib3dsIo *io);
+extern LIB3DSAPI Lib3dsIntd lib3ds_io_read_intd(Lib3dsIo *io);
+extern LIB3DSAPI Lib3dsFloat lib3ds_io_read_float(Lib3dsIo *io);
+extern LIB3DSAPI Lib3dsBool lib3ds_io_read_vector(Lib3dsIo *io, Lib3dsVector v);
+extern LIB3DSAPI Lib3dsBool lib3ds_io_read_rgb(Lib3dsIo *io, Lib3dsRgb rgb);
+extern LIB3DSAPI Lib3dsBool lib3ds_io_read_string(Lib3dsIo *io, char *s, int buflen);
+
+extern LIB3DSAPI Lib3dsBool lib3ds_io_write_byte(Lib3dsIo *io, Lib3dsByte b);
+extern LIB3DSAPI Lib3dsBool lib3ds_io_write_word(Lib3dsIo *io, Lib3dsWord w);
+extern LIB3DSAPI Lib3dsBool lib3ds_io_write_dword(Lib3dsIo *io, Lib3dsDword d);
+extern LIB3DSAPI Lib3dsBool lib3ds_io_write_intb(Lib3dsIo *io, Lib3dsIntb b);
+extern LIB3DSAPI Lib3dsBool lib3ds_io_write_intw(Lib3dsIo *io, Lib3dsIntw w);
+extern LIB3DSAPI Lib3dsBool lib3ds_io_write_intd(Lib3dsIo *io, Lib3dsIntd d);
+extern LIB3DSAPI Lib3dsBool lib3ds_io_write_float(Lib3dsIo *io, Lib3dsFloat l);
+extern LIB3DSAPI Lib3dsBool lib3ds_io_write_vector(Lib3dsIo *io, Lib3dsVector v);
+extern LIB3DSAPI Lib3dsBool lib3ds_io_write_rgb(Lib3dsIo *io, Lib3dsRgb rgb);
+extern LIB3DSAPI Lib3dsBool lib3ds_io_write_string(Lib3dsIo *io, const char *s);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/src/3dengfx/libs/lib3ds/light.c b/src/3dengfx/libs/lib3ds/light.c
new file mode 100644 (file)
index 0000000..4f35766
--- /dev/null
@@ -0,0 +1,428 @@
+/*
+ * The 3D Studio File Format Library
+ * Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
+ * All rights reserved.
+ *
+ * This program is  free  software;  you can redistribute it and/or modify it
+ * under the terms of the  GNU Lesser General Public License  as published by 
+ * the  Free Software Foundation;  either version 2.1 of the License,  or (at 
+ * your option) any later version.
+ *
+ * This  program  is  distributed in  the  hope that it will  be useful,  but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public  
+ * License for more details.
+ *
+ * You should  have received  a copy of the GNU Lesser General Public License
+ * along with  this program;  if not, write to the  Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: light.c,v 1.10 2001/07/11 13:47:35 jeh Exp $
+ */
+#define LIB3DS_EXPORT
+#include <lib3ds/light.h>
+#include <lib3ds/chunk.h>
+#include <lib3ds/io.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+#ifdef WITH_DMALLOC
+#include <dmalloc.h>
+#endif
+
+
+/*!
+ * \defgroup light Lights
+ *
+ * \author J.E. Hoffmann <je-h@gmx.net>
+ */
+/*!
+
+\typedef Lib3dsLight
+  \ingroup light
+  \sa _Lib3dsLight
+
+*/
+
+
+
+/*!
+ * \ingroup light
+ */
+Lib3dsLight*
+lib3ds_light_new(const char *name)
+{
+  Lib3dsLight *light;
+
+  ASSERT(name);
+  ASSERT(strlen(name)<64);
+  
+  light=(Lib3dsLight*)calloc(sizeof(Lib3dsLight), 1);
+  if (!light) {
+    return(0);
+  }
+  strcpy(light->name, name);
+  return(light);
+}
+
+
+/*!
+ * \ingroup light
+ */
+void
+lib3ds_light_free(Lib3dsLight *light)
+{
+  memset(light, 0, sizeof(Lib3dsLight));
+  free(light);
+}
+
+
+/*!
+ * \ingroup light
+ */
+void
+lib3ds_light_dump(Lib3dsLight *light)
+{
+  ASSERT(light);
+  printf("  name:             %s\n", light->name);
+  printf("  spot_light:       %s\n", light->spot_light ? "yes" : "no");
+  printf("  see_cone:         %s\n", light->see_cone ? "yes" : "no");
+  printf("  color:            (%f, %f, %f)\n", 
+    light->color[0], light->color[1], light->color[2]);
+  printf("  position          (%f, %f, %f)\n", 
+    light->position[0], light->position[1], light->position[2]);
+  printf("  spot              (%f, %f, %f)\n", 
+    light->spot[0], light->spot[1], light->spot[2]);
+  printf("  roll:             %f\n", light->roll);
+  printf("  off:              %s\n", light->off ? "yes" : "no");
+  printf("  outer_range:      %f\n", light->outer_range);
+  printf("  inner_range:      %f\n", light->inner_range);
+  printf("  multiplier:       %f\n", light->multiplier);
+  printf("  attenuation:      %f\n", light->attenuation);
+  printf("  rectangular_spot: %s\n", light->rectangular_spot ? "yes" : "no");
+  printf("  shadowed:         %s\n", light->shadowed ? "yes" : "no");
+  printf("  shadow_bias:      %f\n", light->shadow_bias);
+  printf("  shadow_filter:    %f\n", light->shadow_filter);
+  printf("  shadow_size:      %d\n", light->shadow_size);
+  printf("  spot_aspect:      %f\n", light->spot_aspect);
+  printf("  use_projector:    %s\n", light->use_projector ? "yes" : "no");
+  printf("  projector:        %s\n", light->projector);
+  printf("  spot_overshoot:   %d\n", (int)light->spot_overshoot);
+  printf("  ray_shadows:      %s\n", light->ray_shadows ? "yes" : "no");
+  printf("  ray_bias:         %f\n", light->ray_bias);
+  printf("  hot_spot:         %f\n", light->hot_spot);
+  printf("  fall_off:         %f\n", light->fall_off);
+  printf("\n");
+}
+
+
+/*!
+ * \ingroup light
+ */
+static Lib3dsBool
+spotlight_read(Lib3dsLight *light, Lib3dsIo *io)
+{
+  Lib3dsChunk c;
+  Lib3dsWord chunk;
+  int i;
+
+  if (!lib3ds_chunk_read_start(&c, LIB3DS_DL_SPOTLIGHT, io)) {
+    return(LIB3DS_FALSE);
+  }
+  light->spot_light=LIB3DS_TRUE;
+  for (i=0; i<3; ++i) {
+    light->spot[i]=lib3ds_io_read_float(io);
+  }
+  light->hot_spot = lib3ds_io_read_float(io);
+  light->fall_off = lib3ds_io_read_float(io);
+  lib3ds_chunk_read_tell(&c, io);
+  
+  while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) {
+    switch (chunk) {
+      case LIB3DS_DL_SPOT_ROLL:
+        {
+          light->roll=lib3ds_io_read_float(io);
+        }
+        break;
+      case LIB3DS_DL_SHADOWED:
+        {
+          light->shadowed=LIB3DS_TRUE;
+        }
+        break;
+      case LIB3DS_DL_LOCAL_SHADOW2:
+        {
+          light->shadow_bias=lib3ds_io_read_float(io);
+          light->shadow_filter=lib3ds_io_read_float(io);
+          light->shadow_size=lib3ds_io_read_intw(io);
+        }
+        break;
+      case LIB3DS_DL_SEE_CONE:
+        {
+          light->see_cone=LIB3DS_TRUE;
+        }
+        break;
+      case LIB3DS_DL_SPOT_RECTANGULAR:
+        {
+          light->rectangular_spot=LIB3DS_TRUE;
+        }
+        break;
+      case LIB3DS_DL_SPOT_ASPECT:
+        {
+          light->spot_aspect=lib3ds_io_read_float(io);
+        }
+        break;
+      case LIB3DS_DL_SPOT_PROJECTOR:
+        {
+          light->use_projector=LIB3DS_TRUE;
+          if (!lib3ds_io_read_string(io, light->projector, 64)) {
+            return(LIB3DS_FALSE);
+          }
+        }
+      case LIB3DS_DL_SPOT_OVERSHOOT:
+        {
+          light->spot_overshoot=LIB3DS_TRUE;
+        }
+        break;
+      case LIB3DS_DL_RAY_BIAS:
+        {
+          light->ray_bias=lib3ds_io_read_float(io);
+        }
+        break;
+      case LIB3DS_DL_RAYSHAD:
+        {
+          light->ray_shadows=LIB3DS_TRUE;
+        }
+        break;
+      default:
+        lib3ds_chunk_unknown(chunk);
+    }
+  }
+  
+  lib3ds_chunk_read_end(&c, io);
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+ * \ingroup light
+ */
+Lib3dsBool
+lib3ds_light_read(Lib3dsLight *light, Lib3dsIo *io)
+{
+  Lib3dsChunk c;
+  Lib3dsWord chunk;
+
+  if (!lib3ds_chunk_read_start(&c, LIB3DS_N_DIRECT_LIGHT, io)) {
+    return(LIB3DS_FALSE);
+  }
+  {
+    int i;
+    for (i=0; i<3; ++i) {
+      light->position[i]=lib3ds_io_read_float(io);
+    }
+  }
+  lib3ds_chunk_read_tell(&c, io);
+  
+  while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) {
+    switch (chunk) {
+      case LIB3DS_COLOR_F:
+        {
+          int i;
+          for (i=0; i<3; ++i) {
+            light->color[i]=lib3ds_io_read_float(io);
+          }
+        }
+        break;
+      case LIB3DS_DL_OFF:
+        {
+          light->off=LIB3DS_TRUE;
+        }
+        break;
+      case LIB3DS_DL_OUTER_RANGE:
+        {
+          light->outer_range=lib3ds_io_read_float(io);
+        }
+        break;
+      case LIB3DS_DL_INNER_RANGE:
+        {
+          light->inner_range=lib3ds_io_read_float(io);
+        }
+        break;
+      case LIB3DS_DL_MULTIPLIER:
+        {
+          light->multiplier=lib3ds_io_read_float(io);
+        }
+        break;
+      case LIB3DS_DL_EXCLUDE:
+        {
+          /* FIXME: */
+          lib3ds_chunk_unknown(chunk);
+        }
+      case LIB3DS_DL_ATTENUATE:
+        {
+          light->attenuation=lib3ds_io_read_float(io);
+        }
+        break;
+      case LIB3DS_DL_SPOTLIGHT:
+        {
+          lib3ds_chunk_read_reset(&c, io);
+          if (!spotlight_read(light, io)) {
+            return(LIB3DS_FALSE);
+          }
+        }
+        break;
+      default:
+        lib3ds_chunk_unknown(chunk);
+    }
+  }
+  
+  lib3ds_chunk_read_end(&c, io);
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+ * \ingroup light
+ */
+Lib3dsBool
+lib3ds_light_write(Lib3dsLight *light, Lib3dsIo *io)
+{
+  Lib3dsChunk c;
+
+  c.chunk=LIB3DS_N_DIRECT_LIGHT;
+  if (!lib3ds_chunk_write_start(&c,io)) {
+    return(LIB3DS_FALSE);
+  }
+  lib3ds_io_write_vector(io, light->position);
+  { /*---- LIB3DS_COLOR_F ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_COLOR_F;
+    c.size=18;
+    lib3ds_chunk_write(&c, io);
+    lib3ds_io_write_rgb(io, light->color);
+  }
+  if (light->off) { /*---- LIB3DS_DL_OFF ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_DL_OFF;
+    c.size=6;
+    lib3ds_chunk_write(&c, io);
+  }
+  { /*---- LIB3DS_DL_OUTER_RANGE ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_DL_OUTER_RANGE;
+    c.size=10;
+    lib3ds_chunk_write(&c, io);
+    lib3ds_io_write_float(io, light->outer_range);
+  }
+  { /*---- LIB3DS_DL_INNER_RANGE ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_DL_INNER_RANGE;
+    c.size=10;
+    lib3ds_chunk_write(&c, io);
+    lib3ds_io_write_float(io, light->inner_range);
+  }
+  { /*---- LIB3DS_DL_MULTIPLIER ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_DL_MULTIPLIER;
+    c.size=10;
+    lib3ds_chunk_write(&c, io);
+    lib3ds_io_write_float(io, light->multiplier);
+  }
+  if (light->attenuation) { /*---- LIB3DS_DL_ATTENUATE ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_DL_ATTENUATE;
+    c.size=6;
+    lib3ds_chunk_write(&c, io);
+  }
+
+  if (light->spot_light) {
+    Lib3dsChunk c;
+
+    c.chunk=LIB3DS_DL_SPOTLIGHT;
+    if (!lib3ds_chunk_write_start(&c,io)) {
+      return(LIB3DS_FALSE);
+    }
+    lib3ds_io_write_vector(io, light->spot);
+    lib3ds_io_write_float(io, light->hot_spot);
+    lib3ds_io_write_float(io, light->fall_off);
+    
+    { /*---- LIB3DS_DL_SPOT_ROLL ----*/
+      Lib3dsChunk c;
+      c.chunk=LIB3DS_DL_SPOT_ROLL;
+      c.size=10;
+      lib3ds_chunk_write(&c, io);
+      lib3ds_io_write_float(io, light->roll);
+    }
+    if (light->shadowed) { /*---- LIB3DS_DL_SHADOWED ----*/
+      Lib3dsChunk c;
+      c.chunk=LIB3DS_DL_SHADOWED;
+      c.size=6;
+      lib3ds_chunk_write(&c, io);
+    }
+    if ((fabs(light->shadow_bias)>LIB3DS_EPSILON) ||
+      (fabs(light->shadow_filter)>LIB3DS_EPSILON) ||
+      (light->shadow_size!=0)) { /*---- LIB3DS_DL_LOCAL_SHADOW2 ----*/
+      Lib3dsChunk c;
+      c.chunk=LIB3DS_DL_LOCAL_SHADOW2;
+      c.size=16;
+      lib3ds_chunk_write(&c, io);
+      lib3ds_io_write_float(io, light->shadow_bias);
+      lib3ds_io_write_float(io, light->shadow_filter);
+      lib3ds_io_write_intw(io, light->shadow_size);
+    }
+    if (light->see_cone) { /*---- LIB3DS_DL_SEE_CONE ----*/
+      Lib3dsChunk c;
+      c.chunk=LIB3DS_DL_SEE_CONE;
+      c.size=6;
+      lib3ds_chunk_write(&c, io);
+    }
+    if (light->rectangular_spot) { /*---- LIB3DS_DL_SPOT_RECTANGULAR ----*/
+      Lib3dsChunk c;
+      c.chunk=LIB3DS_DL_SPOT_RECTANGULAR;
+      c.size=6;
+      lib3ds_chunk_write(&c, io);
+    }
+    if (fabs(light->spot_aspect)>LIB3DS_EPSILON) { /*---- LIB3DS_DL_SPOT_ASPECT ----*/
+      Lib3dsChunk c;
+      c.chunk=LIB3DS_DL_SPOT_ASPECT;
+      c.size=10;
+      lib3ds_chunk_write(&c, io);
+      lib3ds_io_write_float(io, light->spot_aspect);
+    }
+    if (light->use_projector) { /*---- LIB3DS_DL_SPOT_PROJECTOR ----*/
+      Lib3dsChunk c;
+      c.chunk=LIB3DS_DL_SPOT_PROJECTOR;
+      c.size=10;
+      lib3ds_chunk_write(&c, io);
+      lib3ds_io_write_string(io, light->projector);
+    }
+    if (light->spot_overshoot) { /*---- LIB3DS_DL_SPOT_OVERSHOOT ----*/
+      Lib3dsChunk c;
+      c.chunk=LIB3DS_DL_SPOT_OVERSHOOT;
+      c.size=6;
+      lib3ds_chunk_write(&c, io);
+    }
+    if (fabs(light->ray_bias)>LIB3DS_EPSILON) { /*---- LIB3DS_DL_RAY_BIAS ----*/
+      Lib3dsChunk c;
+      c.chunk=LIB3DS_DL_RAY_BIAS;
+      c.size=10;
+      lib3ds_chunk_write(&c, io);
+      lib3ds_io_write_float(io, light->ray_bias);
+    }
+    if (light->ray_shadows) { /*---- LIB3DS_DL_RAYSHAD ----*/
+      Lib3dsChunk c;
+      c.chunk=LIB3DS_DL_RAYSHAD;
+      c.size=6;
+      lib3ds_chunk_write(&c, io);
+    }
+    if (!lib3ds_chunk_write_end(&c,io)) {
+      return(LIB3DS_FALSE);
+    }
+  }
+  if (!lib3ds_chunk_write_end(&c,io)) {
+    return(LIB3DS_FALSE);
+  }
+  return(LIB3DS_TRUE);
+}
+
+
diff --git a/src/3dengfx/libs/lib3ds/light.h b/src/3dengfx/libs/lib3ds/light.h
new file mode 100644 (file)
index 0000000..bd507b0
--- /dev/null
@@ -0,0 +1,78 @@
+/* -*- c -*- */
+#ifndef INCLUDED_LIB3DS_LIGHT_H
+#define INCLUDED_LIB3DS_LIGHT_H
+/*
+ * The 3D Studio File Format Library
+ * Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
+ * All rights reserved.
+ *
+ * This program is  free  software;  you can redistribute it and/or modify it
+ * under the terms of the  GNU Lesser General Public License  as published by 
+ * the  Free Software Foundation;  either version 2.1 of the License,  or (at 
+ * your option) any later version.
+ *
+ * This  program  is  distributed in  the  hope that it will  be useful,  but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public  
+ * License for more details.
+ *
+ * You should  have received  a copy of the GNU Lesser General Public License
+ * along with  this program;  if not, write to the  Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: light.h,v 1.10 2004/12/31 16:17:15 reed Exp $
+ */
+
+#ifndef INCLUDED_LIB3DS_TYPES_H
+#include <lib3ds/types.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*!
+ * Light
+ * \ingroup light
+ */
+struct _Lib3dsLight {
+    Lib3dsLight *next;
+    char name[64];
+    Lib3dsBool spot_light;
+    Lib3dsBool see_cone;
+    Lib3dsRgb color;
+    Lib3dsVector position;
+    Lib3dsVector spot;
+    Lib3dsFloat roll;
+    Lib3dsBool off;
+    Lib3dsFloat outer_range;
+    Lib3dsFloat inner_range;
+    Lib3dsFloat multiplier;
+    /*const char** excludes;*/
+    Lib3dsFloat attenuation;
+    Lib3dsBool rectangular_spot;
+    Lib3dsBool shadowed;
+    Lib3dsFloat shadow_bias;
+    Lib3dsFloat shadow_filter;
+    Lib3dsIntw shadow_size;
+    Lib3dsFloat spot_aspect;
+    Lib3dsBool use_projector;
+    char projector[64];
+    Lib3dsIntd spot_overshoot;
+    Lib3dsBool ray_shadows;
+    Lib3dsFloat ray_bias;
+    Lib3dsFloat hot_spot;
+    Lib3dsFloat fall_off;
+}; 
+
+extern LIB3DSAPI Lib3dsLight* lib3ds_light_new(const char *name);
+extern LIB3DSAPI void lib3ds_light_free(Lib3dsLight *mesh);
+extern LIB3DSAPI void lib3ds_light_dump(Lib3dsLight *light);
+extern LIB3DSAPI Lib3dsBool lib3ds_light_read(Lib3dsLight *light, Lib3dsIo *io);
+extern LIB3DSAPI Lib3dsBool lib3ds_light_write(Lib3dsLight *light, Lib3dsIo *io);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/src/3dengfx/libs/lib3ds/makefile.part b/src/3dengfx/libs/lib3ds/makefile.part
new file mode 100644 (file)
index 0000000..8382324
--- /dev/null
@@ -0,0 +1,20 @@
+lib3ds_obj = \
+       libs/lib3ds/atmosphere.o \
+       libs/lib3ds/background.o \
+       libs/lib3ds/camera.o \
+       libs/lib3ds/chunk.o \
+       libs/lib3ds/ease.o \
+       libs/lib3ds/file.o \
+       libs/lib3ds/float.o \
+       libs/lib3ds/io.o \
+       libs/lib3ds/light.o \
+       libs/lib3ds/material.o \
+       libs/lib3ds/matrix.o \
+       libs/lib3ds/mesh.o \
+       libs/lib3ds/node.o \
+       libs/lib3ds/quat.o \
+       libs/lib3ds/shadow.o \
+       libs/lib3ds/tcb.o \
+       libs/lib3ds/tracks.o \
+       libs/lib3ds/vector.o \
+       libs/lib3ds/viewport.o
diff --git a/src/3dengfx/libs/lib3ds/material.c b/src/3dengfx/libs/lib3ds/material.c
new file mode 100644 (file)
index 0000000..7f93c75
--- /dev/null
@@ -0,0 +1,1084 @@
+/*
+ * The 3D Studio File Format Library
+ * Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
+ * All rights reserved.
+ *
+ * This program is  free  software;  you can redistribute it and/or modify it
+ * under the terms of the  GNU Lesser General Public License  as published by 
+ * the  Free Software Foundation;  either version 2.1 of the License,  or (at 
+ * your option) any later version.
+ *
+ * This  program  is  distributed in  the  hope that it will  be useful,  but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public  
+ * License for more details.
+ *
+ * You should  have received  a copy of the GNU Lesser General Public License
+ * along with  this program;  if not, write to the  Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: material.c,v 1.18 2004/11/20 08:31:31 efalk Exp $
+ */
+#define LIB3DS_EXPORT
+#include <lib3ds/material.h>
+#include <lib3ds/chunk.h>
+#include <lib3ds/io.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+#ifdef WITH_DMALLOC
+#include <dmalloc.h>
+#endif
+
+
+/*!
+ * \defgroup material Materials
+ *
+ * \author J.E. Hoffmann <je-h@gmx.net>
+ */
+
+
+static void
+initialize_texture_map(Lib3dsTextureMap *map)
+{
+  map->flags = 0x10;
+  map->percent = 1.0f;
+  map->scale[0] = 1.0f;
+  map->scale[1] = 1.0f;
+}
+
+
+/*!
+ * Creates and returns a new, empty Lib3dsMaterial object.
+ *
+ * Initial value of the material is a shiny grey.
+ *
+ * \return     A pointer to the Lib3dsMaterial structure.
+ *             If the structure cannot be allocated, NULL is returned.
+ *
+ * \ingroup material
+ */
+Lib3dsMaterial*
+lib3ds_material_new()
+{
+  Lib3dsMaterial *mat;
+
+  mat = (Lib3dsMaterial*)calloc(sizeof(Lib3dsMaterial), 1);
+  if (!mat) {
+    return(0);
+  }
+
+  mat->ambient[0] = mat->ambient[1] = mat->ambient[2] = 0.588235f;
+  mat->diffuse[0] = mat->diffuse[1] = mat->diffuse[2] = 0.588235f;
+  mat->specular[0] = mat->specular[1] = mat->specular[2] = 0.898039f;
+  mat->shininess = 0.1f;
+  mat->wire_size = 1.0f;
+  mat->shading = 3;
+
+  initialize_texture_map(&mat->texture1_map);
+  initialize_texture_map(&mat->texture1_mask);
+  initialize_texture_map(&mat->texture2_map);
+  initialize_texture_map(&mat->texture2_mask);
+  initialize_texture_map(&mat->opacity_map);
+  initialize_texture_map(&mat->opacity_mask);
+  initialize_texture_map(&mat->bump_map);
+  initialize_texture_map(&mat->bump_mask);
+  initialize_texture_map(&mat->specular_map);
+  initialize_texture_map(&mat->specular_mask);
+  initialize_texture_map(&mat->shininess_map);
+  initialize_texture_map(&mat->shininess_mask);
+  initialize_texture_map(&mat->self_illum_map);
+  initialize_texture_map(&mat->self_illum_mask);
+  initialize_texture_map(&mat->reflection_map);
+  initialize_texture_map(&mat->reflection_mask);
+  
+  return(mat);
+}
+
+
+/*!
+ * \ingroup material
+ */
+void
+lib3ds_material_free(Lib3dsMaterial *material)
+{
+  memset(material, 0, sizeof(Lib3dsMaterial));
+  free(material);
+}
+
+
+static Lib3dsBool
+color_read(Lib3dsRgba rgb, Lib3dsIo *io)
+{
+  Lib3dsChunk c;
+  Lib3dsWord chunk;
+  Lib3dsBool have_lin=LIB3DS_FALSE;
+
+  if (!lib3ds_chunk_read_start(&c, 0, io)) {
+    return(LIB3DS_FALSE);
+  }
+
+  while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) {
+    switch (chunk) {
+      case LIB3DS_LIN_COLOR_24:
+        {
+          int i;
+          for (i=0; i<3; ++i) {
+            rgb[i]=1.0f*lib3ds_io_read_byte(io)/255.0f;
+          }
+          rgb[3]=1.0f;
+        }
+        have_lin=LIB3DS_TRUE;
+        break;
+      case LIB3DS_COLOR_24:
+        /* gamma corrected color chunk
+           replaced in 3ds R3 by LIN_COLOR_24 */
+        if (!have_lin) {
+          int i;
+          for (i=0; i<3; ++i) {
+            rgb[i]=1.0f*lib3ds_io_read_byte(io)/255.0f;
+          }
+          rgb[3]=1.0f;
+        }
+        break;
+      default:
+        lib3ds_chunk_unknown(chunk);
+    }
+  }
+  
+  lib3ds_chunk_read_end(&c, io);
+  return(LIB3DS_TRUE);
+}
+
+
+static Lib3dsBool
+int_percentage_read(Lib3dsFloat *p, Lib3dsIo *io)
+{
+  Lib3dsChunk c;
+  Lib3dsWord chunk;
+
+  if (!lib3ds_chunk_read_start(&c, 0, io)) {
+    return(LIB3DS_FALSE);
+  }
+
+  while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) {
+    switch (chunk) {
+      case LIB3DS_INT_PERCENTAGE:
+        {
+          Lib3dsIntw i=lib3ds_io_read_intw(io);
+          *p=(Lib3dsFloat)(1.0*i/100.0);
+        }
+        break;
+      default:
+        lib3ds_chunk_unknown(chunk);
+    }
+  }
+  
+  lib3ds_chunk_read_end(&c, io);
+  return(LIB3DS_TRUE);
+}
+
+
+static Lib3dsBool
+texture_map_read(Lib3dsTextureMap *map, Lib3dsIo *io)
+{
+  Lib3dsChunk c;
+  Lib3dsWord chunk;
+
+  if (!lib3ds_chunk_read_start(&c, 0, io)) {
+    return(LIB3DS_FALSE);
+  }
+
+  while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) {
+    switch (chunk) {
+      case LIB3DS_INT_PERCENTAGE:
+        {
+          map->percent=1.0f*lib3ds_io_read_intw(io)/100.0f;
+        }
+        break;
+      case LIB3DS_MAT_MAPNAME:
+        {
+          if (!lib3ds_io_read_string(io, map->name, 64)) {
+            return(LIB3DS_FALSE);
+          }
+          lib3ds_chunk_dump_info("  NAME=%s", map->name);
+        }
+        break;
+      case LIB3DS_MAT_MAP_TILING:
+        {
+          map->flags=lib3ds_io_read_word(io);
+        }
+        break;
+      case LIB3DS_MAT_MAP_TEXBLUR:
+        {
+          map->blur=lib3ds_io_read_float(io);
+        }
+        break;
+      case LIB3DS_MAT_MAP_USCALE:
+        {
+          map->scale[0]=lib3ds_io_read_float(io);
+        }
+        break;
+      case LIB3DS_MAT_MAP_VSCALE:
+        {
+          map->scale[1]=lib3ds_io_read_float(io);
+        }
+        break;
+      case LIB3DS_MAT_MAP_UOFFSET:
+        {
+          map->offset[0]=lib3ds_io_read_float(io);
+        }
+        break;
+      case LIB3DS_MAT_MAP_VOFFSET:
+        {
+          map->offset[1]=lib3ds_io_read_float(io);
+        }
+        break;
+      case LIB3DS_MAT_MAP_ANG:
+        {
+          map->rotation=lib3ds_io_read_float(io);
+        }
+        break;
+      case LIB3DS_MAT_MAP_COL1:
+        {
+          map->tint_1[0]=1.0f*lib3ds_io_read_byte(io)/255.0f;
+          map->tint_1[1]=1.0f*lib3ds_io_read_byte(io)/255.0f;
+          map->tint_1[2]=1.0f*lib3ds_io_read_byte(io)/255.0f;
+        }
+        break;
+      case LIB3DS_MAT_MAP_COL2:
+        {
+          map->tint_2[0]=1.0f*lib3ds_io_read_byte(io)/255.0f;
+          map->tint_2[1]=1.0f*lib3ds_io_read_byte(io)/255.0f;
+          map->tint_2[2]=1.0f*lib3ds_io_read_byte(io)/255.0f;
+        }
+        break;
+      case LIB3DS_MAT_MAP_RCOL:
+        {
+          map->tint_r[0]=1.0f*lib3ds_io_read_byte(io)/255.0f;
+          map->tint_r[1]=1.0f*lib3ds_io_read_byte(io)/255.0f;
+          map->tint_r[2]=1.0f*lib3ds_io_read_byte(io)/255.0f;
+        }
+        break;
+      case LIB3DS_MAT_MAP_GCOL:
+        {
+          map->tint_g[0]=1.0f*lib3ds_io_read_byte(io)/255.0f;
+          map->tint_g[1]=1.0f*lib3ds_io_read_byte(io)/255.0f;
+          map->tint_g[2]=1.0f*lib3ds_io_read_byte(io)/255.0f;
+        }
+        break;
+      case LIB3DS_MAT_MAP_BCOL:
+        {
+          map->tint_b[0]=1.0f*lib3ds_io_read_byte(io)/255.0f;
+          map->tint_b[1]=1.0f*lib3ds_io_read_byte(io)/255.0f;
+          map->tint_b[2]=1.0f*lib3ds_io_read_byte(io)/255.0f;
+        }
+        break;
+      default:
+        lib3ds_chunk_unknown(chunk);
+    }
+  }
+  
+  lib3ds_chunk_read_end(&c, io);
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+ * \ingroup material
+ */
+static void
+texture_dump(const char *maptype, Lib3dsTextureMap *texture)
+{
+  ASSERT(texture);
+  if (strlen(texture->name)==0) {
+    return;
+  }
+  printf("  %s:\n", maptype);
+  printf("    name:        %s\n", texture->name);
+  printf("    flags:       %X\n", (unsigned)texture->flags);
+  printf("    percent:     %f\n", texture->percent);
+  printf("    blur:        %f\n", texture->blur);
+  printf("    scale:       (%f, %f)\n", texture->scale[0], texture->scale[1]);
+  printf("    offset:      (%f, %f)\n", texture->offset[0], texture->offset[1]);
+  printf("    rotation:    %f\n", texture->rotation);
+  printf("    tint_1:      (%f, %f, %f)\n",
+    texture->tint_1[0], texture->tint_1[1], texture->tint_1[2]);
+  printf("    tint_2:      (%f, %f, %f)\n",
+    texture->tint_2[0], texture->tint_2[1], texture->tint_2[2]);
+  printf("    tint_r:      (%f, %f, %f)\n",
+    texture->tint_r[0], texture->tint_r[1], texture->tint_r[2]);
+  printf("    tint_g:      (%f, %f, %f)\n",
+    texture->tint_g[0], texture->tint_g[1], texture->tint_g[2]);
+  printf("    tint_b:      (%f, %f, %f)\n",
+    texture->tint_b[0], texture->tint_b[1], texture->tint_b[2]);
+}
+
+
+/*!
+ * \ingroup material
+ */
+void
+lib3ds_material_dump(Lib3dsMaterial *material)
+{
+  ASSERT(material);
+  printf("  name:          %s\n", material->name);
+  printf("  ambient:       (%f, %f, %f)\n",
+    material->ambient[0], material->ambient[1], material->ambient[2]);
+  printf("  diffuse:       (%f, %f, %f)\n",
+    material->diffuse[0], material->diffuse[1], material->diffuse[2]);
+  printf("  specular:      (%f, %f, %f)\n",
+    material->specular[0], material->specular[1], material->specular[2]);
+  printf("  shininess:     %f\n", material->shininess);
+  printf("  shin_strength: %f\n", material->shin_strength);
+  printf("  use_blur:      %s\n", material->use_blur ? "yes" : "no");
+  printf("  blur:          %f\n", material->blur);
+  printf("  falloff:       %f\n", material->falloff);
+  printf("  additive:      %s\n", material->additive ? "yes" : "no");
+  printf("  use_falloff:   %s\n", material->use_falloff ? "yes" : "no");
+  printf("  self_illum:    %s\n", material->self_illum ? "yes" : "no");
+  printf("  self_ilpct:    %f\n", material->self_ilpct);
+  printf("  shading:       %d\n", material->shading);
+  printf("  soften:        %s\n", material->soften ? "yes" : "no");
+  printf("  face_map:      %s\n", material->face_map ? "yes" : "no");
+  printf("  two_sided:     %s\n", material->two_sided ? "yes" : "no");
+  printf("  map_decal:     %s\n", material->map_decal ? "yes" : "no");
+  printf("  use_wire:      %s\n", material->use_wire ? "yes" : "no");
+  printf("  use_wire_abs:  %s\n", material->use_wire_abs ? "yes" : "no");
+  printf("  wire_size:     %f\n", material->wire_size);
+  texture_dump("texture1_map", &material->texture1_map);
+  texture_dump("texture1_mask", &material->texture1_mask);
+  texture_dump("texture2_map", &material->texture2_map);
+  texture_dump("texture2_mask", &material->texture2_mask);
+  texture_dump("opacity_map", &material->opacity_map);
+  texture_dump("opacity_mask", &material->opacity_mask);
+  texture_dump("bump_map", &material->bump_map);
+  texture_dump("bump_mask", &material->bump_mask);
+  texture_dump("specular_map", &material->specular_map);
+  texture_dump("specular_mask", &material->specular_mask);
+  texture_dump("shininess_map", &material->shininess_map);
+  texture_dump("shininess_mask", &material->shininess_mask);
+  texture_dump("self_illum_map", &material->self_illum_map);
+  texture_dump("self_illum_mask", &material->self_illum_mask);
+  texture_dump("reflection_map", &material->reflection_map);
+  texture_dump("reflection_mask", &material->reflection_mask);
+  printf("  autorefl_map:\n");
+  printf("    flags        %X\n", (unsigned)material->autorefl_map.flags);
+  printf("    level        %d\n", (int)material->autorefl_map.level);
+  printf("    size         %d\n", (int)material->autorefl_map.size);
+  printf("    frame_step   %d\n", (int)material->autorefl_map.frame_step);
+  printf("\n");
+}
+
+
+/*!
+ * \ingroup material
+ */
+Lib3dsBool
+lib3ds_material_read(Lib3dsMaterial *material, Lib3dsIo *io)
+{
+  Lib3dsChunk c;
+  Lib3dsWord chunk;
+
+  ASSERT(material);
+  if (!lib3ds_chunk_read_start(&c, LIB3DS_MAT_ENTRY, io)) {
+    return(LIB3DS_FALSE);
+  }
+
+  while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) {
+    switch (chunk) {
+      case LIB3DS_MAT_NAME:
+        {
+          if (!lib3ds_io_read_string(io, material->name, 64)) {
+            return(LIB3DS_FALSE);
+          }
+          lib3ds_chunk_dump_info("  NAME=%s", material->name);
+        }
+        break;
+      case LIB3DS_MAT_AMBIENT:
+        {
+          lib3ds_chunk_read_reset(&c, io);
+          if (!color_read(material->ambient, io)) {
+            return(LIB3DS_FALSE);
+          }
+        }
+        break;
+      case LIB3DS_MAT_DIFFUSE:
+        {
+          lib3ds_chunk_read_reset(&c, io);
+          if (!color_read(material->diffuse, io)) {
+            return(LIB3DS_FALSE);
+          }
+        }
+        break;
+      case LIB3DS_MAT_SPECULAR:
+        {
+          lib3ds_chunk_read_reset(&c, io);
+          if (!color_read(material->specular, io)) {
+            return(LIB3DS_FALSE);
+          }
+        }
+        break;
+      case LIB3DS_MAT_SHININESS:
+        {
+          lib3ds_chunk_read_reset(&c, io);
+          if (!int_percentage_read(&material->shininess, io)) {
+            return(LIB3DS_FALSE);
+          }
+        }
+        break;
+      case LIB3DS_MAT_SHIN2PCT:
+        {
+          lib3ds_chunk_read_reset(&c, io);
+          if (!int_percentage_read(&material->shin_strength, io)) {
+            return(LIB3DS_FALSE);
+          }
+        }
+        break;
+      case LIB3DS_MAT_TRANSPARENCY:
+        {
+          lib3ds_chunk_read_reset(&c, io);
+          if (!int_percentage_read(&material->transparency, io)) {
+            return(LIB3DS_FALSE);
+          }
+        }
+        break;
+      case LIB3DS_MAT_XPFALL:
+        {
+          lib3ds_chunk_read_reset(&c, io);
+          if (!int_percentage_read(&material->falloff, io)) {
+            return(LIB3DS_FALSE);
+          }
+        }
+        break;
+      case LIB3DS_MAT_SELF_ILPCT:
+        {
+          lib3ds_chunk_read_reset(&c, io);
+          if (!int_percentage_read(&material->self_ilpct, io)) {
+            return(LIB3DS_FALSE);
+          }
+        }
+        break;
+      case LIB3DS_MAT_USE_XPFALL:
+        {
+          material->use_falloff=LIB3DS_TRUE;
+        }
+        break;
+      case LIB3DS_MAT_REFBLUR:
+        {
+          lib3ds_chunk_read_reset(&c, io);
+          if (!int_percentage_read(&material->blur, io)) {
+            return(LIB3DS_FALSE);
+          }
+        }
+        break;
+      case LIB3DS_MAT_USE_REFBLUR:
+        {
+          material->use_blur=LIB3DS_TRUE;
+        }
+        break;
+      case LIB3DS_MAT_SHADING:
+        {
+          material->shading=lib3ds_io_read_intw(io);
+        }
+        break;
+      case LIB3DS_MAT_SELF_ILLUM:
+        {
+          material->self_illum=LIB3DS_TRUE;
+        }
+        break;
+      case LIB3DS_MAT_TWO_SIDE:
+        {
+          material->two_sided=LIB3DS_TRUE;
+        }
+        break;
+      case LIB3DS_MAT_DECAL:
+        {
+          material->map_decal=LIB3DS_TRUE;
+        }
+        break;
+      case LIB3DS_MAT_ADDITIVE:
+        {
+          material->additive=LIB3DS_TRUE;
+        }
+        break;
+      case LIB3DS_MAT_FACEMAP:
+        {
+          material->face_map=LIB3DS_TRUE;
+        }
+        break;
+      case LIB3DS_MAT_PHONGSOFT:
+        {
+          material->soften=LIB3DS_TRUE;
+        }
+        break;
+      case LIB3DS_MAT_WIRE:
+        {
+          material->use_wire=LIB3DS_TRUE;
+        }
+        break;
+      case LIB3DS_MAT_WIREABS:
+        {
+          material->use_wire_abs=LIB3DS_TRUE;
+        }
+        break;
+      case LIB3DS_MAT_WIRE_SIZE:
+        {
+          material->wire_size=lib3ds_io_read_float(io);
+        }
+        break;
+      case LIB3DS_MAT_TEXMAP:
+        {
+          lib3ds_chunk_read_reset(&c, io);
+          if (!texture_map_read(&material->texture1_map, io)) {
+            return(LIB3DS_FALSE);
+          }
+        }
+        break;
+      case LIB3DS_MAT_TEXMASK:
+        {
+          lib3ds_chunk_read_reset(&c, io);
+          if (!texture_map_read(&material->texture1_mask, io)) {
+            return(LIB3DS_FALSE);
+          }
+        }
+        break;
+      case LIB3DS_MAT_TEX2MAP:
+        {
+          lib3ds_chunk_read_reset(&c, io);
+          if (!texture_map_read(&material->texture2_map, io)) {
+            return(LIB3DS_FALSE);
+          }
+        }
+        break;
+      case LIB3DS_MAT_TEX2MASK:
+        {
+          lib3ds_chunk_read_reset(&c, io);
+          if (!texture_map_read(&material->texture2_mask, io)) {
+            return(LIB3DS_FALSE);
+          }
+        }
+        break;
+      case LIB3DS_MAT_OPACMAP:
+        {
+          lib3ds_chunk_read_reset(&c, io);
+          if (!texture_map_read(&material->opacity_map, io)) {
+            return(LIB3DS_FALSE);
+          }
+        }
+        break;
+      case LIB3DS_MAT_OPACMASK:
+        {
+          lib3ds_chunk_read_reset(&c, io);
+          if (!texture_map_read(&material->opacity_mask, io)) {
+            return(LIB3DS_FALSE);
+          }
+        }
+        break;
+      case LIB3DS_MAT_BUMPMAP:
+        {
+          lib3ds_chunk_read_reset(&c, io);
+          if (!texture_map_read(&material->bump_map, io)) {
+            return(LIB3DS_FALSE);
+          }
+        }
+        break;
+      case LIB3DS_MAT_BUMPMASK:
+        {
+          lib3ds_chunk_read_reset(&c, io);
+          if (!texture_map_read(&material->bump_mask, io)) {
+            return(LIB3DS_FALSE);
+          }
+        }
+        break;
+      case LIB3DS_MAT_SPECMAP:
+        {
+          lib3ds_chunk_read_reset(&c, io);
+          if (!texture_map_read(&material->specular_map, io)) {
+            return(LIB3DS_FALSE);
+          }
+        }
+        break;
+      case LIB3DS_MAT_SPECMASK:
+        {
+          lib3ds_chunk_read_reset(&c, io);
+          if (!texture_map_read(&material->specular_mask, io)) {
+            return(LIB3DS_FALSE);
+          }
+        }
+        break;
+      case LIB3DS_MAT_SHINMAP:
+        {
+          lib3ds_chunk_read_reset(&c, io);
+          if (!texture_map_read(&material->shininess_map, io)) {
+            return(LIB3DS_FALSE);
+          }
+        }
+        break;
+      case LIB3DS_MAT_SHINMASK:
+        {
+          lib3ds_chunk_read_reset(&c, io);
+          if (!texture_map_read(&material->shininess_mask, io)) {
+            return(LIB3DS_FALSE);
+          }
+        }
+        break;
+      case LIB3DS_MAT_SELFIMAP:
+        {
+          lib3ds_chunk_read_reset(&c, io);
+          if (!texture_map_read(&material->self_illum_map, io)) {
+            return(LIB3DS_FALSE);
+          }
+        }
+        break;
+      case LIB3DS_MAT_SELFIMASK:
+        {
+          lib3ds_chunk_read_reset(&c, io);
+          if (!texture_map_read(&material->self_illum_mask, io)) {
+            return(LIB3DS_FALSE);
+          }
+        }
+        break;
+      case LIB3DS_MAT_REFLMAP:
+        {
+          lib3ds_chunk_read_reset(&c, io);
+          if (!texture_map_read(&material->reflection_map, io)) {
+            return(LIB3DS_FALSE);
+          }
+        }
+        break;
+      case LIB3DS_MAT_REFLMASK:
+        {
+          lib3ds_chunk_read_reset(&c, io);
+          if (!texture_map_read(&material->reflection_mask, io)) {
+            return(LIB3DS_FALSE);
+          }
+        }
+        break;
+      case LIB3DS_MAT_ACUBIC:
+        {
+          lib3ds_io_read_intb(io);
+          material->autorefl_map.level=lib3ds_io_read_intb(io);
+          material->autorefl_map.flags=lib3ds_io_read_intw(io);
+          material->autorefl_map.size=lib3ds_io_read_intd(io);
+          material->autorefl_map.frame_step=lib3ds_io_read_intd(io);
+        }
+        break;
+      default:
+        lib3ds_chunk_unknown(chunk);
+    }
+  }
+
+  lib3ds_chunk_read_end(&c, io);
+  return(LIB3DS_TRUE);
+}
+
+
+static Lib3dsBool
+color_write(Lib3dsRgba rgb, Lib3dsIo *io)
+{
+  Lib3dsChunk c;
+
+  c.chunk=LIB3DS_COLOR_24;
+  c.size=9;
+  lib3ds_chunk_write(&c,io);
+  lib3ds_io_write_byte(io, (Lib3dsByte)floor(255.0*rgb[0]+0.5));
+  lib3ds_io_write_byte(io, (Lib3dsByte)floor(255.0*rgb[1]+0.5));
+  lib3ds_io_write_byte(io, (Lib3dsByte)floor(255.0*rgb[2]+0.5));
+
+  c.chunk=LIB3DS_LIN_COLOR_24;
+  c.size=9;
+  lib3ds_chunk_write(&c,io);
+  lib3ds_io_write_byte(io, (Lib3dsByte)floor(255.0*rgb[0]+0.5));
+  lib3ds_io_write_byte(io, (Lib3dsByte)floor(255.0*rgb[1]+0.5));
+  lib3ds_io_write_byte(io, (Lib3dsByte)floor(255.0*rgb[2]+0.5));
+
+  return(LIB3DS_TRUE);
+}
+
+
+static Lib3dsBool
+int_percentage_write(Lib3dsFloat p, Lib3dsIo *io)
+{
+  Lib3dsChunk c;
+
+  c.chunk=LIB3DS_INT_PERCENTAGE;
+  c.size=8;
+  lib3ds_chunk_write(&c,io);
+  lib3ds_io_write_intw(io, (Lib3dsByte)floor(100.0*p+0.5));
+
+  return(LIB3DS_TRUE);
+}
+
+
+static Lib3dsBool
+texture_map_write(Lib3dsWord chunk, Lib3dsTextureMap *map, Lib3dsIo *io)
+{
+  Lib3dsChunk c;
+
+  if (strlen(map->name)==0) {
+    return(LIB3DS_TRUE);
+  }
+  c.chunk=chunk;
+  if (!lib3ds_chunk_write_start(&c,io)) {
+    return(LIB3DS_FALSE);
+  }
+  
+  int_percentage_write(map->percent,io);
+
+  { /*---- LIB3DS_MAT_MAPNAME ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_MAT_MAPNAME;
+    c.size=6+strlen(map->name)+1;
+    lib3ds_chunk_write(&c,io);
+    lib3ds_io_write_string(io, map->name);
+  }
+
+  { /*---- LIB3DS_MAT_MAP_TILING ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_MAT_MAP_TILING;
+    c.size=8;
+    lib3ds_chunk_write(&c,io);
+    lib3ds_io_write_word(io, (Lib3dsWord)map->flags);
+  }
+  
+  { /*---- LIB3DS_MAT_MAP_TEXBLUR ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_MAT_MAP_TEXBLUR;
+    c.size=10;
+    lib3ds_chunk_write(&c,io);
+    lib3ds_io_write_float(io, map->blur);
+  }
+
+  { /*---- LIB3DS_MAT_MAP_USCALE ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_MAT_MAP_USCALE;
+    c.size=10;
+    lib3ds_chunk_write(&c,io);
+    lib3ds_io_write_float(io, map->scale[0]);
+  }
+
+  { /*---- LIB3DS_MAT_MAP_VSCALE ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_MAT_MAP_VSCALE;
+    c.size=10;
+    lib3ds_chunk_write(&c,io);
+    lib3ds_io_write_float(io, map->scale[1]);
+  }
+
+  { /*---- LIB3DS_MAT_MAP_UOFFSET ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_MAT_MAP_UOFFSET;
+    c.size=10;
+    lib3ds_chunk_write(&c,io);
+    lib3ds_io_write_float(io, map->offset[0]);
+  }
+
+  { /*---- LIB3DS_MAT_MAP_VOFFSET ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_MAT_MAP_VOFFSET;
+    c.size=10;
+    lib3ds_chunk_write(&c,io);
+    lib3ds_io_write_float(io, map->offset[1]);
+  }
+
+  { /*---- LIB3DS_MAT_MAP_ANG ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_MAT_MAP_ANG;
+    c.size=10;
+    lib3ds_chunk_write(&c,io);
+    lib3ds_io_write_float(io, map->rotation);
+  }
+
+  { /*---- LIB3DS_MAT_MAP_COL1 ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_MAT_MAP_COL1;
+    c.size=9;
+    lib3ds_chunk_write(&c,io);
+    lib3ds_io_write_byte(io, (Lib3dsByte)floor(255.0*map->tint_1[0]+0.5));
+    lib3ds_io_write_byte(io, (Lib3dsByte)floor(255.0*map->tint_1[1]+0.5));
+    lib3ds_io_write_byte(io, (Lib3dsByte)floor(255.0*map->tint_1[2]+0.5));
+  }
+
+  { /*---- LIB3DS_MAT_MAP_COL2 ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_MAT_MAP_COL2;
+    c.size=9;
+    lib3ds_chunk_write(&c,io);
+    lib3ds_io_write_byte(io, (Lib3dsByte)floor(255.0*map->tint_2[0]+0.5));
+    lib3ds_io_write_byte(io, (Lib3dsByte)floor(255.0*map->tint_2[1]+0.5));
+    lib3ds_io_write_byte(io, (Lib3dsByte)floor(255.0*map->tint_2[2]+0.5));
+  }
+  
+  { /*---- LIB3DS_MAT_MAP_RCOL ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_MAT_MAP_RCOL;
+    c.size=9;
+    lib3ds_chunk_write(&c,io);
+    lib3ds_io_write_byte(io, (Lib3dsByte)floor(255.0*map->tint_r[0]+0.5));
+    lib3ds_io_write_byte(io, (Lib3dsByte)floor(255.0*map->tint_r[1]+0.5));
+    lib3ds_io_write_byte(io, (Lib3dsByte)floor(255.0*map->tint_r[2]+0.5));
+  }
+
+  { /*---- LIB3DS_MAT_MAP_GCOL ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_MAT_MAP_GCOL;
+    c.size=9;
+    lib3ds_chunk_write(&c,io);
+    lib3ds_io_write_byte(io, (Lib3dsByte)floor(255.0*map->tint_g[0]+0.5));
+    lib3ds_io_write_byte(io, (Lib3dsByte)floor(255.0*map->tint_g[1]+0.5));
+    lib3ds_io_write_byte(io, (Lib3dsByte)floor(255.0*map->tint_g[2]+0.5));
+  }
+  
+  { /*---- LIB3DS_MAT_MAP_BCOL ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_MAT_MAP_BCOL;
+    c.size=9;
+    lib3ds_chunk_write(&c,io);
+    lib3ds_io_write_byte(io, (Lib3dsByte)floor(255.0*map->tint_b[0]+0.5));
+    lib3ds_io_write_byte(io, (Lib3dsByte)floor(255.0*map->tint_b[1]+0.5));
+    lib3ds_io_write_byte(io, (Lib3dsByte)floor(255.0*map->tint_b[2]+0.5));
+  }
+
+  if (!lib3ds_chunk_write_end(&c,io)) {
+    return(LIB3DS_FALSE);
+  }
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+ * \ingroup material
+ */
+Lib3dsBool
+lib3ds_material_write(Lib3dsMaterial *material, Lib3dsIo *io)
+{
+  Lib3dsChunk c;
+
+  c.chunk=LIB3DS_MAT_ENTRY;
+  if (!lib3ds_chunk_write_start(&c,io)) {
+    return(LIB3DS_FALSE);
+  }
+
+  { /*---- LIB3DS_MAT_NAME ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_MAT_NAME;
+    c.size=6+strlen(material->name)+1;
+    lib3ds_chunk_write(&c,io);
+    lib3ds_io_write_string(io, material->name);
+  }
+
+  { /*---- LIB3DS_MAT_AMBIENT ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_MAT_AMBIENT;
+    c.size=24;
+    lib3ds_chunk_write(&c,io);
+    color_write(material->ambient,io);
+  }
+
+  { /*---- LIB3DS_MAT_DIFFUSE ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_MAT_DIFFUSE;
+    c.size=24;
+    lib3ds_chunk_write(&c,io);
+    color_write(material->diffuse,io);
+  }
+
+  { /*---- LIB3DS_MAT_SPECULAR ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_MAT_SPECULAR;
+    c.size=24;
+    lib3ds_chunk_write(&c,io);
+    color_write(material->specular,io);
+  }
+
+  { /*---- LIB3DS_MAT_SHININESS ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_MAT_SHININESS;
+    c.size=14;
+    lib3ds_chunk_write(&c,io);
+    int_percentage_write(material->shininess,io);
+  }
+
+  { /*---- LIB3DS_MAT_SHIN2PCT ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_MAT_SHIN2PCT;
+    c.size=14;
+    lib3ds_chunk_write(&c,io);
+    int_percentage_write(material->shin_strength,io);
+  }
+
+  { /*---- LIB3DS_MAT_TRANSPARENCY ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_MAT_TRANSPARENCY;
+    c.size=14;
+    lib3ds_chunk_write(&c,io);
+    int_percentage_write(material->transparency,io);
+  }
+
+  { /*---- LIB3DS_MAT_XPFALL ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_MAT_XPFALL;
+    c.size=14;
+    lib3ds_chunk_write(&c,io);
+    int_percentage_write(material->falloff,io);
+  }
+
+  if (material->use_falloff) { /*---- LIB3DS_MAT_USE_XPFALL ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_MAT_USE_XPFALL;
+    c.size=6;
+    lib3ds_chunk_write(&c,io);
+  }
+
+  { /*---- LIB3DS_MAT_SHADING ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_MAT_SHADING;
+    c.size=8;
+    lib3ds_chunk_write(&c,io);
+    lib3ds_io_write_intw(io, material->shading);
+  }
+
+  { /*---- LIB3DS_MAT_REFBLUR ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_MAT_REFBLUR;
+    c.size=14;
+    lib3ds_chunk_write(&c,io);
+    int_percentage_write(material->blur,io);
+  }
+
+  if (material->use_blur) { /*---- LIB3DS_MAT_USE_REFBLUR ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_MAT_USE_REFBLUR;
+    c.size=6;
+    lib3ds_chunk_write(&c,io);
+  }
+
+  if (material->self_illum) { /*---- LIB3DS_MAT_SELF_ILLUM ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_MAT_SELF_ILLUM;
+    c.size=6;
+    lib3ds_chunk_write(&c,io);
+  }
+
+  if (material->two_sided) { /*---- LIB3DS_MAT_TWO_SIDE ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_MAT_TWO_SIDE;
+    c.size=6;
+    lib3ds_chunk_write(&c,io);
+  }
+  
+  if (material->map_decal) { /*---- LIB3DS_MAT_DECAL ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_MAT_DECAL;
+    c.size=6;
+    lib3ds_chunk_write(&c,io);
+  }
+
+  if (material->additive) { /*---- LIB3DS_MAT_ADDITIVE ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_MAT_ADDITIVE;
+    c.size=6;
+    lib3ds_chunk_write(&c,io);
+  }
+
+  if (material->use_wire) { /*---- LIB3DS_MAT_WIRE ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_MAT_WIRE;
+    c.size=6;
+    lib3ds_chunk_write(&c,io);
+  }
+
+  if (material->use_wire_abs) { /*---- LIB3DS_MAT_WIREABS ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_MAT_WIREABS;
+    c.size=6;
+    lib3ds_chunk_write(&c,io);
+  }
+
+  { /*---- LIB3DS_MAT_WIRE_SIZE ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_MAT_WIRE_SIZE;
+    c.size=10;
+    lib3ds_chunk_write(&c,io);
+    lib3ds_io_write_float(io, material->wire_size);
+  }
+
+  if (material->face_map) { /*---- LIB3DS_MAT_FACEMAP ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_MAT_FACEMAP;
+    c.size=6;
+    lib3ds_chunk_write(&c,io);
+  }
+
+  if (material->soften) { /*---- LIB3DS_MAT_PHONGSOFT ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_MAT_PHONGSOFT;
+    c.size=6;
+    lib3ds_chunk_write(&c,io);
+  }
+
+  if (!texture_map_write(LIB3DS_MAT_TEXMAP, &material->texture1_map, io)) {
+    return(LIB3DS_FALSE);
+  }
+  if (!texture_map_write(LIB3DS_MAT_TEXMASK, &material->texture1_mask, io)) {
+    return(LIB3DS_FALSE);
+  }
+  if (!texture_map_write(LIB3DS_MAT_TEX2MAP, &material->texture2_map, io)) {
+    return(LIB3DS_FALSE);
+  }
+  if (!texture_map_write(LIB3DS_MAT_TEX2MASK, &material->texture2_mask, io)) {
+    return(LIB3DS_FALSE);
+  }
+  if (!texture_map_write(LIB3DS_MAT_OPACMAP, &material->opacity_map, io)) {
+    return(LIB3DS_FALSE);
+  }
+  if (!texture_map_write(LIB3DS_MAT_OPACMASK, &material->opacity_mask, io)) {
+    return(LIB3DS_FALSE);
+  }
+  if (!texture_map_write(LIB3DS_MAT_BUMPMAP, &material->bump_map, io)) {
+    return(LIB3DS_FALSE);
+  }
+  if (!texture_map_write(LIB3DS_MAT_BUMPMASK, &material->bump_mask, io)) {
+    return(LIB3DS_FALSE);
+  }
+  if (!texture_map_write(LIB3DS_MAT_SPECMAP, &material->specular_map, io)) {
+    return(LIB3DS_FALSE);
+  }
+  if (!texture_map_write(LIB3DS_MAT_SPECMASK, &material->specular_mask, io)) {
+    return(LIB3DS_FALSE);
+  }
+  if (!texture_map_write(LIB3DS_MAT_SHINMAP, &material->shininess_map, io)) {
+    return(LIB3DS_FALSE);
+  }
+  if (!texture_map_write(LIB3DS_MAT_SHINMASK, &material->shininess_mask, io)) {
+    return(LIB3DS_FALSE);
+  }
+  if (!texture_map_write(LIB3DS_MAT_SELFIMAP, &material->self_illum_map, io)) {
+    return(LIB3DS_FALSE);
+  }
+  if (!texture_map_write(LIB3DS_MAT_SELFIMASK, &material->self_illum_mask, io)) {
+    return(LIB3DS_FALSE);
+  }
+  if (!texture_map_write(LIB3DS_MAT_REFLMAP,  &material->reflection_map, io)) {
+    return(LIB3DS_FALSE);
+  }
+  if (!texture_map_write(LIB3DS_MAT_REFLMASK,  &material->reflection_mask, io)) {
+    return(LIB3DS_FALSE);
+  }
+
+  if (!lib3ds_chunk_write_end(&c,io)) {
+    return(LIB3DS_FALSE);
+  }
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+
+\typedef Lib3dsMaterial
+  \ingroup material
+  \sa _Lib3dsMaterial
+
+*/
+
diff --git a/src/3dengfx/libs/lib3ds/material.h b/src/3dengfx/libs/lib3ds/material.h
new file mode 100644 (file)
index 0000000..352bda1
--- /dev/null
@@ -0,0 +1,170 @@
+/* -*- c -*- */
+#ifndef INCLUDED_LIB3DS_MATERIAL_H
+#define INCLUDED_LIB3DS_MATERIAL_H
+/*
+ * The 3D Studio File Format Library
+ * Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
+ * All rights reserved.
+ *
+ * This program is  free  software;  you can redistribute it and/or modify it
+ * under the terms of the  GNU Lesser General Public License  as published by 
+ * the  Free Software Foundation;  either version 2.1 of the License,  or (at 
+ * your option) any later version.
+ *
+ * This  program  is  distributed in  the  hope that it will  be useful,  but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public  
+ * License for more details.
+ *
+ * You should  have received  a copy of the GNU Lesser General Public License
+ * along with  this program;  if not, write to the  Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: material.h,v 1.15 2004/12/31 16:17:15 reed Exp $
+ */
+
+#ifndef INCLUDED_LIB3DS_TYPES_H
+#include <lib3ds/types.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*!
+ * \ingroup material 
+ */
+typedef enum _Lib3dsTextureMapFlags {
+  LIB3DS_DECALE       =0x0001,
+  LIB3DS_MIRROR       =0x0002,
+  LIB3DS_NEGATE       =0x0004,
+  LIB3DS_NO_TILE      =0x0008,
+  LIB3DS_SUMMED_AREA  =0x0010,
+  LIB3DS_ALPHA_SOURCE =0x0020,
+  LIB3DS_TINT         =0x0040,
+  LIB3DS_IGNORE_ALPHA =0x0080,
+  LIB3DS_RGB_TINT     =0x0100
+} Lib3dsTextureMapFlags;
+
+/*!
+ * Mateial texture map
+ * \ingroup material 
+ */
+typedef struct _Lib3dsTextureMap {
+    Lib3dsUserData user;
+    char name[64];
+    Lib3dsDword flags;
+    Lib3dsFloat percent;
+    Lib3dsFloat blur;
+    Lib3dsFloat scale[2];
+    Lib3dsFloat offset[2];
+    Lib3dsFloat rotation;
+    Lib3dsRgb tint_1;
+    Lib3dsRgb tint_2;
+    Lib3dsRgb tint_r;
+    Lib3dsRgb tint_g;
+    Lib3dsRgb tint_b;
+} Lib3dsTextureMap;
+
+/*!
+ * \ingroup material 
+ */
+typedef enum _Lib3dsAutoReflMapFlags {
+  LIB3DS_USE_REFL_MAP          =0x0001,
+  LIB3DS_READ_FIRST_FRAME_ONLY =0x0004,
+  LIB3DS_FLAT_MIRROR           =0x0008 
+} Lib3dsAutoReflectionMapFlags;
+
+/*!
+ * \ingroup material 
+ */
+typedef enum _Lib3dsAutoReflMapAntiAliasLevel {
+  LIB3DS_ANTI_ALIAS_NONE   =0,
+  LIB3DS_ANTI_ALIAS_LOW    =1,
+  LIB3DS_ANTI_ALIAS_MEDIUM =2,
+  LIB3DS_ANTI_ALIAS_HIGH   =3
+} Lib3dsAutoReflMapAntiAliasLevel;
+
+/*!
+ * Auto reflection map settings
+ * \ingroup material 
+ */
+typedef struct _Lib3dsAutoReflMap {
+    Lib3dsDword flags;
+    Lib3dsIntd level;
+    Lib3dsIntd size;
+    Lib3dsIntd frame_step;
+} Lib3dsAutoReflMap;
+
+/*!
+ * \ingroup material 
+ */
+typedef enum _Lib3dsMaterialShading {
+  LIB3DS_WIRE_FRAME =0,
+  LIB3DS_FLAT       =1, 
+  LIB3DS_GOURAUD    =2, 
+  LIB3DS_PHONG      =3, 
+  LIB3DS_METAL      =4
+} Lib3dsMaterialShading; 
+
+/*!
+ * Material
+ * \ingroup material 
+ */
+struct _Lib3dsMaterial {
+    Lib3dsUserData user;               /*! Arbitrary user data */
+    Lib3dsMaterial *next;
+    char name[64];                     /*! Material name */
+    Lib3dsRgba ambient;                        /*! Material ambient reflectivity */
+    Lib3dsRgba diffuse;                        /*! Material diffuse reflectivity */
+    Lib3dsRgba specular;               /*! Material specular reflectivity */
+    Lib3dsFloat shininess;             /*! Material specular exponent */
+    Lib3dsFloat shin_strength;
+    Lib3dsBool use_blur;
+    Lib3dsFloat blur;
+    Lib3dsFloat transparency;
+    Lib3dsFloat falloff;
+    Lib3dsBool additive;
+    Lib3dsFloat self_ilpct;
+    Lib3dsBool use_falloff;
+    Lib3dsBool self_illum;
+    Lib3dsIntw shading;
+    Lib3dsBool soften;
+    Lib3dsBool face_map;
+    Lib3dsBool two_sided;              /*! Material visible from back */
+    Lib3dsBool map_decal;
+    Lib3dsBool use_wire;
+    Lib3dsBool use_wire_abs;
+    Lib3dsFloat wire_size;
+    Lib3dsTextureMap texture1_map;
+    Lib3dsTextureMap texture1_mask;
+    Lib3dsTextureMap texture2_map;
+    Lib3dsTextureMap texture2_mask;
+    Lib3dsTextureMap opacity_map;
+    Lib3dsTextureMap opacity_mask;
+    Lib3dsTextureMap bump_map;
+    Lib3dsTextureMap bump_mask;
+    Lib3dsTextureMap specular_map;
+    Lib3dsTextureMap specular_mask;
+    Lib3dsTextureMap shininess_map;
+    Lib3dsTextureMap shininess_mask;
+    Lib3dsTextureMap self_illum_map;
+    Lib3dsTextureMap self_illum_mask;
+    Lib3dsTextureMap reflection_map;
+    Lib3dsTextureMap reflection_mask;
+    Lib3dsAutoReflMap autorefl_map;
+};
+
+extern LIB3DSAPI Lib3dsMaterial* lib3ds_material_new();
+extern LIB3DSAPI void lib3ds_material_free(Lib3dsMaterial *material);
+extern LIB3DSAPI void lib3ds_material_dump(Lib3dsMaterial *material);
+extern LIB3DSAPI Lib3dsBool lib3ds_material_read(Lib3dsMaterial *material, Lib3dsIo *io);
+extern LIB3DSAPI Lib3dsBool lib3ds_material_write(Lib3dsMaterial *material, Lib3dsIo *io);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+
+
diff --git a/src/3dengfx/libs/lib3ds/matrix.c b/src/3dengfx/libs/lib3ds/matrix.c
new file mode 100644 (file)
index 0000000..e21534f
--- /dev/null
@@ -0,0 +1,723 @@
+/*
+ * The 3D Studio File Format Library
+ * Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
+ * All rights reserved.
+ *
+ * This program is  free  software;  you can redistribute it and/or modify it
+ * under the terms of the  GNU Lesser General Public License  as published by 
+ * the  Free Software Foundation;  either version 2.1 of the License,  or (at 
+ * your option) any later version.
+ *
+ * This  program  is  distributed in  the  hope that it will  be useful,  but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public  
+ * License for more details.
+ *
+ * You should  have received  a copy of the GNU Lesser General Public License
+ * along with  this program;  if not, write to the  Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: matrix.c,v 1.10 2004/11/16 07:41:44 efalk Exp $
+ */
+#define LIB3DS_EXPORT
+#include <lib3ds/matrix.h>
+#include <lib3ds/quat.h>
+#include <lib3ds/vector.h>
+#include <string.h>
+#include <math.h>
+
+
+/*!
+ * \defgroup matrix Matrix Mathematics
+ *
+ * \author J.E. Hoffmann <je-h@gmx.net>
+ */
+/*!
+ * \typedef Lib3dsMatrix
+ *   \ingroup matrix
+ */
+
+
+/*!
+ * Clear a matrix to all zeros.
+ *
+ * \param m Matrix to be cleared.
+ *
+ * \ingroup matrix
+ */
+void
+lib3ds_matrix_zero(Lib3dsMatrix m)
+{
+  int i,j;
+
+  for (i=0; i<4; i++) {
+    for (j=0; j<4; j++) m[i][j]=0.0f;
+  }
+}
+
+
+/*!
+ * Set a matrix to identity.
+ *
+ * \param m Matrix to be set.
+ *
+ * \ingroup matrix
+ */
+void
+lib3ds_matrix_identity(Lib3dsMatrix m)
+{
+  int i,j;
+
+  for (i=0; i<4; i++) {
+    for (j=0; j<4; j++) m[i][j]=0.0;
+  }
+  for (i=0; i<4; i++) m[i][i]=1.0;
+}
+
+
+/*!
+ * Copy a matrix.
+ *
+ * \ingroup matrix
+ */
+void
+lib3ds_matrix_copy(Lib3dsMatrix dest, Lib3dsMatrix src)
+{
+  memcpy(dest, src, sizeof(Lib3dsMatrix)); 
+}
+
+
+/*!
+ * Negate a matrix -- all elements negated.
+ *
+ * \ingroup matrix
+ */
+void 
+lib3ds_matrix_neg(Lib3dsMatrix m)
+{
+  int i,j;
+
+  for (j=0; j<4; j++) {
+    for (i=0; i<4; i++) {
+      m[j][i]=-m[j][i];
+    }
+  }
+}
+
+
+/*!
+ * Set all matrix elements to their absolute value.
+ *
+ * \ingroup matrix
+ */
+void 
+lib3ds_matrix_abs(Lib3dsMatrix m)
+{
+  int i,j;
+
+  for (j=0; j<4; j++) {
+    for (i=0; i<4; i++) {
+      m[j][i]=(Lib3dsFloat)fabs(m[j][i]);
+    }
+  }
+}
+
+
+/*!
+ * Transpose a matrix in place.
+ *
+ * \ingroup matrix
+ */
+void
+lib3ds_matrix_transpose(Lib3dsMatrix m)
+{
+  int i,j;
+  Lib3dsFloat swp;
+
+  for (j=0; j<4; j++) {
+    for (i=j+1; i<4; i++) {
+      swp=m[j][i];
+      m[j][i]=m[i][j];
+      m[i][j]=swp;
+    }
+  }
+}
+
+
+/*!
+ * Add two matrices.
+ *
+ * \ingroup matrix
+ */
+void
+lib3ds_matrix_add(Lib3dsMatrix m, Lib3dsMatrix a, Lib3dsMatrix b)
+{
+  int i,j;
+
+  for (j=0; j<4; j++) {
+    for (i=0; i<4; i++) {
+      m[j][i]=a[j][i]+b[j][i];
+    }
+  }
+}
+
+
+/*!
+ * Subtract two matrices.
+ *
+ * \param m Result.
+ * \param a Addend.
+ * \param b Minuend.
+ *
+ * \ingroup matrix
+ */
+void
+lib3ds_matrix_sub(Lib3dsMatrix m, Lib3dsMatrix a, Lib3dsMatrix b)
+{
+  int i,j;
+
+  for (j=0; j<4; j++) {
+    for (i=0; i<4; i++) {
+      m[j][i]=a[j][i]-b[j][i];
+    }
+  }
+}
+
+
+/*!
+ * Multiply two matrices.
+ *
+ * \param m Result.
+ * \param a Left matrix.
+ * \param b Right matrix.
+ *
+ * \ingroup matrix
+ */
+void
+lib3ds_matrix_mul(Lib3dsMatrix m, Lib3dsMatrix a, Lib3dsMatrix b)
+{
+  int i,j,k;
+  Lib3dsFloat ab;
+
+  for (j=0; j<4; j++) {
+    for (i=0; i<4; i++) {
+      ab=0.0f;
+      for (k=0; k<4; k++) ab+=a[k][i]*b[j][k];
+      m[j][i]=ab;
+    }
+  }
+}
+
+
+/*!
+ * Multiply a matrix by a scalar.
+ *
+ * \param m Matrix to be set.
+ * \param k Scalar.
+ *
+ * \ingroup matrix
+ */
+void
+lib3ds_matrix_scalar(Lib3dsMatrix m, Lib3dsFloat k)
+{
+  int i,j;
+
+  for (j=0; j<4; j++) {
+    for (i=0; i<4; i++) {
+      m[j][i]*=k;
+    }
+  }
+}
+
+
+static Lib3dsFloat
+det2x2(
+  Lib3dsFloat a, Lib3dsFloat b,
+  Lib3dsFloat c, Lib3dsFloat d) 
+{
+  return((a)*(d)-(b)*(c));
+}
+
+
+static Lib3dsFloat
+det3x3(
+  Lib3dsFloat a1, Lib3dsFloat a2, Lib3dsFloat a3,
+  Lib3dsFloat b1, Lib3dsFloat b2, Lib3dsFloat b3,
+  Lib3dsFloat c1, Lib3dsFloat c2, Lib3dsFloat c3)
+{
+  return(
+    a1*det2x2(b2,b3,c2,c3)-
+    b1*det2x2(a2,a3,c2,c3)+
+    c1*det2x2(a2,a3,b2,b3)
+  );
+}
+
+
+/*!
+ * Find determinant of a matrix.
+ *
+ * \ingroup matrix
+ */
+Lib3dsFloat
+lib3ds_matrix_det(Lib3dsMatrix m)
+{
+  Lib3dsFloat a1,a2,a3,a4,b1,b2,b3,b4,c1,c2,c3,c4,d1,d2,d3,d4;
+
+  a1 = m[0][0];
+  b1 = m[1][0];
+  c1 = m[2][0];
+  d1 = m[3][0];
+  a2 = m[0][1];
+  b2 = m[1][1];
+  c2 = m[2][1];
+  d2 = m[3][1];
+  a3 = m[0][2];
+  b3 = m[1][2];
+  c3 = m[2][2];
+  d3 = m[3][2];
+  a4 = m[0][3];
+  b4 = m[1][3];
+  c4 = m[2][3];
+  d4 = m[3][3];
+  return(
+    a1 * det3x3(b2, b3, b4, c2, c3, c4, d2, d3, d4)-
+    b1 * det3x3(a2, a3, a4, c2, c3, c4, d2, d3, d4)+
+    c1 * det3x3(a2, a3, a4, b2, b3, b4, d2, d3, d4)-
+    d1 * det3x3(a2, a3, a4, b2, b3, b4, c2, c3, c4)
+  );
+}
+
+
+/*!
+ * Find the adjoint of a matrix.
+ *
+ * \ingroup matrix
+ */
+void
+lib3ds_matrix_adjoint(Lib3dsMatrix m)
+{
+  Lib3dsFloat a1,a2,a3,a4,b1,b2,b3,b4,c1,c2,c3,c4,d1,d2,d3,d4;
+
+  a1 = m[0][0];
+  b1 = m[1][0];
+  c1 = m[2][0];
+  d1 = m[3][0];
+  a2 = m[0][1];
+  b2 = m[1][1];
+  c2 = m[2][1];
+  d2 = m[3][1];
+  a3 = m[0][2];
+  b3 = m[1][2];
+  c3 = m[2][2];
+  d3 = m[3][2];
+  a4 = m[0][3];
+  b4 = m[1][3];
+  c4 = m[2][3];
+  d4 = m[3][3];
+  m[0][0]=  det3x3 (b2, b3, b4, c2, c3, c4, d2, d3, d4);
+  m[0][1]= -det3x3 (a2, a3, a4, c2, c3, c4, d2, d3, d4);
+  m[0][2]=  det3x3 (a2, a3, a4, b2, b3, b4, d2, d3, d4);
+  m[0][3]= -det3x3 (a2, a3, a4, b2, b3, b4, c2, c3, c4);
+  m[1][0]= -det3x3 (b1, b3, b4, c1, c3, c4, d1, d3, d4);
+  m[1][1]=  det3x3 (a1, a3, a4, c1, c3, c4, d1, d3, d4);
+  m[1][2]= -det3x3 (a1, a3, a4, b1, b3, b4, d1, d3, d4);
+  m[1][3]=  det3x3 (a1, a3, a4, b1, b3, b4, c1, c3, c4);
+  m[2][0]=  det3x3 (b1, b2, b4, c1, c2, c4, d1, d2, d4);
+  m[2][1]= -det3x3 (a1, a2, a4, c1, c2, c4, d1, d2, d4);
+  m[2][2]=  det3x3 (a1, a2, a4, b1, b2, b4, d1, d2, d4);
+  m[2][3]= -det3x3 (a1, a2, a4, b1, b2, b4, c1, c2, c4);
+  m[3][0]= -det3x3 (b1, b2, b3, c1, c2, c3, d1, d2, d3);
+  m[3][1]=  det3x3 (a1, a2, a3, c1, c2, c3, d1, d2, d3);
+  m[3][2]= -det3x3 (a1, a2, a3, b1, b2, b3, d1, d2, d3);
+  m[3][3]=  det3x3 (a1, a2, a3, b1, b2, b3, c1, c2, c3);
+}
+
+
+/*!
+ * Invert a matrix in place.
+ *
+ * \param m Matrix to invert.
+ *
+ * \return LIB3DS_TRUE on success, LIB3DS_FALSE on failure.
+ * \ingroup matrix
+ *
+ * GGemsII, K.Wu, Fast Matrix Inversion 
+ */
+Lib3dsBool
+lib3ds_matrix_inv(Lib3dsMatrix m)
+{                          
+  int i,j,k;               
+  int pvt_i[4], pvt_j[4];            /* Locations of pivot elements */
+  Lib3dsFloat pvt_val;               /* Value of current pivot element */
+  Lib3dsFloat hold;                  /* Temporary storage */
+  Lib3dsFloat determinat;            
+
+  determinat = 1.0f;
+  for (k=0; k<4; k++)  {
+    /* Locate k'th pivot element */
+    pvt_val=m[k][k];            /* Initialize for search */
+    pvt_i[k]=k;
+    pvt_j[k]=k;
+    for (i=k; i<4; i++) {
+      for (j=k; j<4; j++) {
+        if (fabs(m[i][j]) > fabs(pvt_val)) {
+          pvt_i[k]=i;
+          pvt_j[k]=j;
+          pvt_val=m[i][j];
+        }
+      }
+    }
+
+    /* Product of pivots, gives determinant when finished */
+    determinat*=pvt_val;
+    if (fabs(determinat)<LIB3DS_EPSILON) {    
+      return(LIB3DS_FALSE);  /* Matrix is singular (zero determinant) */
+    }
+
+    /* "Interchange" rows (with sign change stuff) */
+    i=pvt_i[k];
+    if (i!=k) {               /* If rows are different */
+      for (j=0; j<4; j++) {
+        hold=-m[k][j];
+        m[k][j]=m[i][j];
+        m[i][j]=hold;
+      }
+    }
+
+    /* "Interchange" columns */
+    j=pvt_j[k];
+    if (j!=k) {              /* If columns are different */
+      for (i=0; i<4; i++) {
+        hold=-m[i][k];
+        m[i][k]=m[i][j];
+        m[i][j]=hold;
+      }
+    }
+    
+    /* Divide column by minus pivot value */
+    for (i=0; i<4; i++) {
+      if (i!=k) m[i][k]/=( -pvt_val) ; 
+    }
+
+    /* Reduce the matrix */
+    for (i=0; i<4; i++) {
+      hold = m[i][k];
+      for (j=0; j<4; j++) {
+        if (i!=k && j!=k) m[i][j]+=hold*m[k][j];
+      }
+    }
+
+    /* Divide row by pivot */
+    for (j=0; j<4; j++) {
+      if (j!=k) m[k][j]/=pvt_val;
+    }
+
+    /* Replace pivot by reciprocal (at last we can touch it). */
+    m[k][k] = 1.0f/pvt_val;
+  }
+
+  /* That was most of the work, one final pass of row/column interchange */
+  /* to finish */
+  for (k=4-2; k>=0; k--) { /* Don't need to work with 1 by 1 corner*/
+    i=pvt_j[k];            /* Rows to swap correspond to pivot COLUMN */
+    if (i!=k) {            /* If rows are different */
+      for(j=0; j<4; j++) {
+        hold = m[k][j];
+        m[k][j]=-m[i][j];
+        m[i][j]=hold;
+      }
+    }
+
+    j=pvt_i[k];           /* Columns to swap correspond to pivot ROW */
+    if (j!=k)             /* If columns are different */
+    for (i=0; i<4; i++) {
+      hold=m[i][k];
+      m[i][k]=-m[i][j];
+      m[i][j]=hold;
+    }
+  }
+  return(LIB3DS_TRUE);                          
+}
+
+
+/*!
+ * Apply a translation to a matrix.
+ *
+ * \ingroup matrix
+ */
+void
+lib3ds_matrix_translate_xyz(Lib3dsMatrix m, Lib3dsFloat x, Lib3dsFloat y, Lib3dsFloat z)
+{
+  int i;
+  
+  for (i=0; i<3; i++) {
+    m[3][i]+= m[0][i]*x + m[1][i]*y + m[2][i]*z;
+  }
+}
+
+
+/*!
+ * Apply a translation to a matrix.
+ *
+ * \ingroup matrix
+ */
+void
+lib3ds_matrix_translate(Lib3dsMatrix m, Lib3dsVector t)
+{
+  int i;
+  
+  for (i=0; i<3; i++) {
+    m[3][i]+= m[0][i]*t[0] + m[1][i]*t[1] + m[2][i]*t[2];
+  }
+}
+
+
+/*!
+ * Apply scale factors to a matrix.
+ *
+ * \ingroup matrix
+ */
+void
+lib3ds_matrix_scale_xyz(Lib3dsMatrix m, Lib3dsFloat x, Lib3dsFloat y, Lib3dsFloat z)
+{
+  int i;
+
+  for (i=0; i<4; i++) {
+    m[0][i]*=x;
+    m[1][i]*=y;
+    m[2][i]*=z;
+  }
+}
+
+
+/*!
+ * Apply scale factors to a matrix.
+ *
+ * \ingroup matrix
+ */
+void
+lib3ds_matrix_scale(Lib3dsMatrix m, Lib3dsVector s)
+{
+  int i;
+
+  for (i=0; i<4; i++) {
+    m[0][i]*=s[0];
+    m[1][i]*=s[1];
+    m[2][i]*=s[2];
+  }
+}
+
+
+/*!
+ * Apply a rotation about the x axis to a matrix.
+ *
+ * \ingroup matrix
+ */
+void
+lib3ds_matrix_rotate_x(Lib3dsMatrix m, Lib3dsFloat phi)
+{
+  Lib3dsFloat SinPhi,CosPhi;
+  Lib3dsFloat a1[4],a2[4];
+
+  SinPhi=(Lib3dsFloat)sin(phi);
+  CosPhi=(Lib3dsFloat)cos(phi);
+  memcpy(a1,m[1],4*sizeof(Lib3dsFloat));
+  memcpy(a2,m[2],4*sizeof(Lib3dsFloat));
+  m[1][0]=CosPhi*a1[0]+SinPhi*a2[0];
+  m[1][1]=CosPhi*a1[1]+SinPhi*a2[1];
+  m[1][2]=CosPhi*a1[2]+SinPhi*a2[2];
+  m[1][3]=CosPhi*a1[3]+SinPhi*a2[3];
+  m[2][0]=-SinPhi*a1[0]+CosPhi*a2[0];
+  m[2][1]=-SinPhi*a1[1]+CosPhi*a2[1];
+  m[2][2]=-SinPhi*a1[2]+CosPhi*a2[2];
+  m[2][3]=-SinPhi*a1[3]+CosPhi*a2[3];
+}
+
+
+/*!
+ * Apply a rotation about the y axis to a matrix.
+ *
+ * \ingroup matrix
+ */
+void
+lib3ds_matrix_rotate_y(Lib3dsMatrix m, Lib3dsFloat phi)
+{
+  Lib3dsFloat SinPhi,CosPhi;
+  Lib3dsFloat a0[4],a2[4];
+
+  SinPhi=(Lib3dsFloat)sin(phi);
+  CosPhi=(Lib3dsFloat)cos(phi);
+  memcpy(a0,m[0],4*sizeof(Lib3dsFloat));
+  memcpy(a2,m[2],4*sizeof(Lib3dsFloat));
+  m[0][0]=CosPhi*a0[0]-SinPhi*a2[0];
+  m[0][1]=CosPhi*a0[1]-SinPhi*a2[1];
+  m[0][2]=CosPhi*a0[2]-SinPhi*a2[2];
+  m[0][3]=CosPhi*a0[3]-SinPhi*a2[3];
+  m[2][0]=SinPhi*a0[0]+CosPhi*a2[0];
+  m[2][1]=SinPhi*a0[1]+CosPhi*a2[1];
+  m[2][2]=SinPhi*a0[2]+CosPhi*a2[2];
+  m[2][3]=SinPhi*a0[3]+CosPhi*a2[3];
+}
+
+
+/*!
+ * Apply a rotation about the z axis to a matrix.
+ *
+ * \ingroup matrix
+ */
+void
+lib3ds_matrix_rotate_z(Lib3dsMatrix m, Lib3dsFloat phi)
+{
+  Lib3dsFloat SinPhi,CosPhi;
+  Lib3dsFloat a0[4],a1[4];
+  
+  SinPhi=(Lib3dsFloat)sin(phi);
+  CosPhi=(Lib3dsFloat)cos(phi);
+  memcpy(a0,m[0],4*sizeof(Lib3dsFloat));
+  memcpy(a1,m[1],4*sizeof(Lib3dsFloat));
+  m[0][0]=CosPhi*a0[0]+SinPhi*a1[0];
+  m[0][1]=CosPhi*a0[1]+SinPhi*a1[1];
+  m[0][2]=CosPhi*a0[2]+SinPhi*a1[2];
+  m[0][3]=CosPhi*a0[3]+SinPhi*a1[3];
+  m[1][0]=-SinPhi*a0[0]+CosPhi*a1[0];
+  m[1][1]=-SinPhi*a0[1]+CosPhi*a1[1];
+  m[1][2]=-SinPhi*a0[2]+CosPhi*a1[2];
+  m[1][3]=-SinPhi*a0[3]+CosPhi*a1[3];
+}
+
+
+/*!
+ * Apply a rotation about an arbitrary axis to a matrix.
+ *
+ * \ingroup matrix
+ */
+void
+lib3ds_matrix_rotate(Lib3dsMatrix m, Lib3dsQuat q)
+{
+  Lib3dsFloat s,xs,ys,zs,wx,wy,wz,xx,xy,xz,yy,yz,zz,l;
+  Lib3dsMatrix a,b;
+
+  lib3ds_matrix_copy(a, m);
+
+  l=q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3];
+  if (fabs(l)<LIB3DS_EPSILON) {
+    s=1.0f;
+  }
+  else {
+    s=2.0f/l;
+  }
+
+  xs = q[0] * s;   ys = q[1] * s;  zs = q[2] * s;
+  wx = q[3] * xs;  wy = q[3] * ys; wz = q[3] * zs;
+  xx = q[0] * xs;  xy = q[0] * ys; xz = q[0] * zs;
+  yy = q[1] * ys;  yz = q[1] * zs; zz = q[2] * zs;
+
+  b[0][0]=1.0f - (yy +zz);
+  b[1][0]=xy - wz;
+  b[2][0]=xz + wy;
+  b[0][1]=xy + wz;
+  b[1][1]=1.0f - (xx +zz);
+  b[2][1]=yz - wx;
+  b[0][2]=xz - wy;
+  b[1][2]=yz + wx;
+  b[2][2]=1.0f - (xx + yy);
+  b[3][0]=b[3][1]=b[3][2]=b[0][3]=b[1][3]=b[2][3]=0.0f;
+  b[3][3]=1.0f;
+
+  lib3ds_matrix_mul(m,a,b);
+}
+
+
+/*!
+ * Apply a rotation about an arbitrary axis to a matrix.
+ *
+ * \ingroup matrix
+ */
+void
+lib3ds_matrix_rotate_axis(Lib3dsMatrix m, Lib3dsVector axis, Lib3dsFloat angle)
+{
+  Lib3dsQuat q;
+  
+  lib3ds_quat_axis_angle(q,axis,angle);
+  lib3ds_matrix_rotate(m,q);
+}
+
+
+/*!
+ * Compute a camera matrix based on position, target and roll.
+ *
+ * Generates a translate/rotate matrix that maps world coordinates
+ * to camera coordinates.  Resulting matrix does not include perspective
+ * transform.
+ *
+ * \param matrix Destination matrix.
+ * \param pos Camera position
+ * \param tgt Camera target
+ * \param roll Roll angle
+ *
+ * \ingroup matrix
+ */
+void
+lib3ds_matrix_camera(Lib3dsMatrix matrix, Lib3dsVector pos,
+  Lib3dsVector tgt, Lib3dsFloat roll)
+{
+  Lib3dsMatrix M,R;
+  Lib3dsVector x, y, z;
+
+  lib3ds_vector_sub(y, tgt, pos);
+  lib3ds_vector_normalize(y);
+
+  if (y[0] != 0. || y[1] != 0) {
+    z[0] = 0;
+    z[1] = 0;
+    z[2] = 1.0;
+  }
+  else {       /* Special case:  looking straight up or down z axis */
+    z[0] = -1.0;
+    z[1] = 0;
+    z[2] = 0;
+  }
+
+  lib3ds_vector_cross(x, y, z);
+  lib3ds_vector_cross(z, x, y);
+  lib3ds_vector_normalize(x);
+  lib3ds_vector_normalize(z);
+
+  lib3ds_matrix_identity(M);
+  M[0][0] = x[0];
+  M[1][0] = x[1];
+  M[2][0] = x[2];
+  M[0][1] = y[0];
+  M[1][1] = y[1];
+  M[2][1] = y[2];
+  M[0][2] = z[0];
+  M[1][2] = z[1];
+  M[2][2] = z[2];
+
+  lib3ds_matrix_identity(R);
+  lib3ds_matrix_rotate_y(R, roll);
+  lib3ds_matrix_mul(matrix, R,M);
+  lib3ds_matrix_translate_xyz(matrix, -pos[0],-pos[1],-pos[2]);
+}
+
+
+/*!
+ * \ingroup matrix
+ */
+void
+lib3ds_matrix_dump(Lib3dsMatrix matrix)
+{
+  int i,j;
+
+  for (i=0; i<4; ++i) {
+    for (j=0; j<4; ++j) {
+      printf("%f ", matrix[j][i]);
+    }
+    printf("\n");
+  }
+}
+
+
+
+
+
diff --git a/src/3dengfx/libs/lib3ds/matrix.h b/src/3dengfx/libs/lib3ds/matrix.h
new file mode 100644 (file)
index 0000000..47dac75
--- /dev/null
@@ -0,0 +1,67 @@
+/* -*- c -*- */
+#ifndef INCLUDED_LIB3DS_MATRIX_H
+#define INCLUDED_LIB3DS_MATRIX_H
+/*
+ * The 3D Studio File Format Library
+ * Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
+ * All rights reserved.
+ *
+ * This program is  free  software;  you can redistribute it and/or modify it
+ * under the terms of the  GNU Lesser General Public License  as published by 
+ * the  Free Software Foundation;  either version 2.1 of the License,  or (at 
+ * your option) any later version.
+ *
+ * This  program  is  distributed in  the  hope that it will  be useful,  but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public  
+ * License for more details.
+ *
+ * You should  have received  a copy of the GNU Lesser General Public License
+ * along with  this program;  if not, write to the  Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: matrix.h,v 1.5 2004/12/31 16:17:15 reed Exp $
+ */
+
+#ifndef INCLUDED_LIB3DS_TYPES_H
+#include <lib3ds/types.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern LIB3DSAPI void lib3ds_matrix_zero(Lib3dsMatrix m);
+extern LIB3DSAPI void lib3ds_matrix_identity(Lib3dsMatrix m);
+extern LIB3DSAPI void lib3ds_matrix_copy(Lib3dsMatrix dest, Lib3dsMatrix src);
+extern LIB3DSAPI void lib3ds_matrix_neg(Lib3dsMatrix m);
+extern LIB3DSAPI void lib3ds_matrix_abs(Lib3dsMatrix m);
+extern LIB3DSAPI void lib3ds_matrix_transpose(Lib3dsMatrix m);
+extern LIB3DSAPI void lib3ds_matrix_add(Lib3dsMatrix m, Lib3dsMatrix a, Lib3dsMatrix b);
+extern LIB3DSAPI void lib3ds_matrix_sub(Lib3dsMatrix m, Lib3dsMatrix a, Lib3dsMatrix b);
+extern LIB3DSAPI void lib3ds_matrix_mul(Lib3dsMatrix m, Lib3dsMatrix a, Lib3dsMatrix b);
+extern LIB3DSAPI void lib3ds_matrix_scalar(Lib3dsMatrix m, Lib3dsFloat k);
+extern LIB3DSAPI Lib3dsFloat lib3ds_matrix_det(Lib3dsMatrix m);
+extern LIB3DSAPI void lib3ds_matrix_adjoint(Lib3dsMatrix m);
+extern LIB3DSAPI Lib3dsBool lib3ds_matrix_inv(Lib3dsMatrix m);
+void lib3ds_matrix_translate_xyz(Lib3dsMatrix m, Lib3dsFloat x,
+  Lib3dsFloat y, Lib3dsFloat z);
+extern LIB3DSAPI void lib3ds_matrix_translate(Lib3dsMatrix m, Lib3dsVector t);
+extern LIB3DSAPI void lib3ds_matrix_scale_xyz(Lib3dsMatrix m, Lib3dsFloat x,
+  Lib3dsFloat y, Lib3dsFloat z);
+extern LIB3DSAPI void lib3ds_matrix_scale(Lib3dsMatrix m, Lib3dsVector s);
+extern LIB3DSAPI void lib3ds_matrix_rotate_x(Lib3dsMatrix m, Lib3dsFloat phi);
+extern LIB3DSAPI void lib3ds_matrix_rotate_y(Lib3dsMatrix m, Lib3dsFloat phi);
+extern LIB3DSAPI void lib3ds_matrix_rotate_z(Lib3dsMatrix m, Lib3dsFloat phi);
+extern LIB3DSAPI void lib3ds_matrix_rotate(Lib3dsMatrix m, Lib3dsQuat q);
+extern LIB3DSAPI void lib3ds_matrix_rotate_axis(Lib3dsMatrix m,
+  Lib3dsVector axis, Lib3dsFloat angle);
+extern LIB3DSAPI void lib3ds_matrix_camera(Lib3dsMatrix matrix, Lib3dsVector pos,
+  Lib3dsVector tgt, Lib3dsFloat roll);
+extern LIB3DSAPI void lib3ds_matrix_dump(Lib3dsMatrix matrix);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/src/3dengfx/libs/lib3ds/mesh.c b/src/3dengfx/libs/lib3ds/mesh.c
new file mode 100644 (file)
index 0000000..f0e5b3e
--- /dev/null
@@ -0,0 +1,1063 @@
+/*
+ * The 3D Studio File Format Library
+ * Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
+ * All rights reserved.
+ *
+ * This program is  free  software;  you can redistribute it and/or modify it
+ * under the terms of the  GNU Lesser General Public License  as published by 
+ * the  Free Software Foundation;  either version 2.1 of the License,  or (at 
+ * your option) any later version.
+ *
+ * This  program  is  distributed in  the  hope that it will  be useful,  but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public  
+ * License for more details.
+ *
+ * You should  have received  a copy of the GNU Lesser General Public License
+ * along with  this program;  if not, write to the  Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: mesh.c,v 1.22 2004/11/20 08:33:56 efalk Exp $
+ */
+#define LIB3DS_EXPORT
+#include <lib3ds/mesh.h>
+#include <lib3ds/io.h>
+#include <lib3ds/chunk.h>
+#include <lib3ds/vector.h>
+#include <lib3ds/matrix.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#ifdef WITH_DMALLOC
+#include <dmalloc.h>
+#endif
+
+
+/*!
+ * \defgroup mesh Meshes
+ *
+ * \author J.E. Hoffmann <je-h@gmx.net>
+ */
+
+
+static Lib3dsBool
+face_array_read(Lib3dsMesh *mesh, Lib3dsIo *io)
+{
+  Lib3dsChunk c;
+  Lib3dsWord chunk;
+  int i;
+  int faces;
+
+  if (!lib3ds_chunk_read_start(&c, LIB3DS_FACE_ARRAY, io)) {
+    return(LIB3DS_FALSE);
+  }
+  lib3ds_mesh_free_face_list(mesh);
+  
+  faces=lib3ds_io_read_word(io);
+  if (faces) {
+    if (!lib3ds_mesh_new_face_list(mesh, faces)) {
+      LIB3DS_ERROR_LOG;
+      return(LIB3DS_FALSE);
+    }
+    for (i=0; i<faces; ++i) {
+      strcpy(mesh->faceL[i].material, "");
+      mesh->faceL[i].points[0]=lib3ds_io_read_word(io);
+      mesh->faceL[i].points[1]=lib3ds_io_read_word(io);
+      mesh->faceL[i].points[2]=lib3ds_io_read_word(io);
+      mesh->faceL[i].flags=lib3ds_io_read_word(io);
+    }
+    lib3ds_chunk_read_tell(&c, io);
+
+    while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) {
+      switch (chunk) {
+        case LIB3DS_SMOOTH_GROUP:
+          {
+            unsigned i;
+
+            for (i=0; i<mesh->faces; ++i) {
+              mesh->faceL[i].smoothing=lib3ds_io_read_dword(io);
+            }
+          }
+          break;
+        case LIB3DS_MSH_MAT_GROUP:
+          {
+            char name[64];
+            unsigned faces;
+            unsigned i;
+            unsigned index;
+
+            if (!lib3ds_io_read_string(io, name, 64)) {
+              return(LIB3DS_FALSE);
+            }
+            faces=lib3ds_io_read_word(io);
+            for (i=0; i<faces; ++i) {
+              index=lib3ds_io_read_word(io);
+              ASSERT(index<mesh->faces);
+              strcpy(mesh->faceL[index].material, name);
+            }
+          }
+          break;
+        case LIB3DS_MSH_BOXMAP:
+          {
+            char name[64];
+
+            if (!lib3ds_io_read_string(io, name, 64)) {
+              return(LIB3DS_FALSE);
+            }
+            strcpy(mesh->box_map.front, name);
+            if (!lib3ds_io_read_string(io, name, 64)) {
+              return(LIB3DS_FALSE);
+            }
+            strcpy(mesh->box_map.back, name);
+            if (!lib3ds_io_read_string(io, name, 64)) {
+              return(LIB3DS_FALSE);
+            }
+            strcpy(mesh->box_map.left, name);
+            if (!lib3ds_io_read_string(io, name, 64)) {
+              return(LIB3DS_FALSE);
+            }
+            strcpy(mesh->box_map.right, name);
+            if (!lib3ds_io_read_string(io, name, 64)) {
+              return(LIB3DS_FALSE);
+            }
+            strcpy(mesh->box_map.top, name);
+            if (!lib3ds_io_read_string(io, name, 64)) {
+              return(LIB3DS_FALSE);
+            }
+            strcpy(mesh->box_map.bottom, name);
+          }
+          break;
+        default:
+          lib3ds_chunk_unknown(chunk);
+      }
+    }
+    
+  }
+  lib3ds_chunk_read_end(&c, io);
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+ * Create and return a new empty mesh object.
+ *
+ * Mesh is initialized with the name and an identity matrix; all
+ * other fields are zero.
+ *
+ * See Lib3dsFaceFlag for definitions of per-face flags.
+ *
+ * \param name Mesh name.  Must not be NULL.  Must be < 64 characters.
+ *
+ * \return mesh object or NULL on error.
+ *
+ * \ingroup mesh
+ */
+Lib3dsMesh*
+lib3ds_mesh_new(const char *name)
+{
+  Lib3dsMesh *mesh;
+
+  ASSERT(name);
+  ASSERT(strlen(name)<64);
+  
+  mesh=(Lib3dsMesh*)calloc(sizeof(Lib3dsMesh), 1);
+  if (!mesh) {
+    return(0);
+  }
+  strcpy(mesh->name, name);
+  lib3ds_matrix_identity(mesh->matrix);
+  mesh->map_data.maptype=LIB3DS_MAP_NONE;
+  return(mesh);
+}
+
+
+/*!
+ * Free a mesh object and all of its resources.
+ *
+ * \param mesh Mesh object to be freed.
+ *
+ * \ingroup mesh
+ */
+void
+lib3ds_mesh_free(Lib3dsMesh *mesh)
+{
+  lib3ds_mesh_free_point_list(mesh);
+  lib3ds_mesh_free_flag_list(mesh);
+  lib3ds_mesh_free_texel_list(mesh);
+  lib3ds_mesh_free_face_list(mesh);
+  memset(mesh, 0, sizeof(Lib3dsMesh));
+  free(mesh);
+}
+
+
+/*!
+ * Allocate point list in mesh object.
+ *
+ * This function frees the current point list, if any, and allocates
+ * a new one large enough to hold the specified number of points.
+ *
+ * \param mesh Mesh object for which points are to be allocated.
+ * \param points Number of points in the new point list.
+ *
+ * \return LIB3DS_TRUE on success, LIB3DS_FALSE on failure.
+ *
+ * \ingroup mesh
+ */
+Lib3dsBool
+lib3ds_mesh_new_point_list(Lib3dsMesh *mesh, Lib3dsDword points)
+{
+  ASSERT(mesh);
+  if (mesh->pointL) {
+    ASSERT(mesh->points);
+    lib3ds_mesh_free_point_list(mesh);
+  }
+  ASSERT(!mesh->pointL && !mesh->points);
+  mesh->points=0;
+  mesh->pointL=calloc(sizeof(Lib3dsPoint)*points,1);
+  if (!mesh->pointL) {
+    LIB3DS_ERROR_LOG;
+    return(LIB3DS_FALSE);
+  }
+  mesh->points=points;
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+ * Free point list in mesh object.
+ *
+ * The current point list is freed and set to NULL.  mesh->points is
+ * set to zero.
+ *
+ * \param mesh Mesh object to be modified.
+ *
+ * \ingroup mesh
+ */
+void
+lib3ds_mesh_free_point_list(Lib3dsMesh *mesh)
+{
+  ASSERT(mesh);
+  if (mesh->pointL) {
+    ASSERT(mesh->points);
+    free(mesh->pointL);
+    mesh->pointL=0;
+    mesh->points=0;
+  }
+  else {
+    ASSERT(!mesh->points);
+  }
+}
+
+
+/*!
+ * Allocate flag list in mesh object.
+ *
+ * This function frees the current flag list, if any, and allocates
+ * a new one large enough to hold the specified number of flags.
+ * All flags are initialized to 0
+ *
+ * \param mesh Mesh object for which points are to be allocated.
+ * \param flags Number of flags in the new flag list.
+ *
+ * \return LIB3DS_TRUE on success, LIB3DS_FALSE on failure.
+ *
+ * \ingroup mesh
+ */
+Lib3dsBool
+lib3ds_mesh_new_flag_list(Lib3dsMesh *mesh, Lib3dsDword flags)
+{
+  ASSERT(mesh);
+  if (mesh->flagL) {
+    ASSERT(mesh->flags);
+    lib3ds_mesh_free_flag_list(mesh);
+  }
+  ASSERT(!mesh->flagL && !mesh->flags);
+  mesh->flags=0;
+  mesh->flagL=calloc(sizeof(Lib3dsWord)*flags,1);
+  if (!mesh->flagL) {
+    LIB3DS_ERROR_LOG;
+    return(LIB3DS_FALSE);
+  }
+  mesh->flags=flags;
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+ * Free flag list in mesh object.
+ *
+ * The current flag list is freed and set to NULL.  mesh->flags is
+ * set to zero.
+ *
+ * \param mesh Mesh object to be modified.
+ *
+ * \ingroup mesh
+ */
+void
+lib3ds_mesh_free_flag_list(Lib3dsMesh *mesh)
+{
+  ASSERT(mesh);
+  if (mesh->flagL) {
+    ASSERT(mesh->flags);
+    free(mesh->flagL);
+    mesh->flagL=0;
+    mesh->flags=0;
+  }
+  else {
+    ASSERT(!mesh->flags);
+  }
+}
+
+
+/*!
+ * Allocate texel list in mesh object.
+ *
+ * This function frees the current texel list, if any, and allocates
+ * a new one large enough to hold the specified number of texels.
+ *
+ * \param mesh Mesh object for which points are to be allocated.
+ * \param texels Number of texels in the new texel list.
+ *
+ * \return LIB3DS_TRUE on success, LIB3DS_FALSE on failure.
+ *
+ * \ingroup mesh
+ */
+Lib3dsBool
+lib3ds_mesh_new_texel_list(Lib3dsMesh *mesh, Lib3dsDword texels)
+{
+  ASSERT(mesh);
+  if (mesh->texelL) {
+    ASSERT(mesh->texels);
+    lib3ds_mesh_free_texel_list(mesh);
+  }
+  ASSERT(!mesh->texelL && !mesh->texels);
+  mesh->texels=0;
+  mesh->texelL=calloc(sizeof(Lib3dsTexel)*texels,1);
+  if (!mesh->texelL) {
+    LIB3DS_ERROR_LOG;
+    return(LIB3DS_FALSE);
+  }
+  mesh->texels=texels;
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+ * Free texel list in mesh object.
+ *
+ * The current texel list is freed and set to NULL.  mesh->texels is
+ * set to zero.
+ *
+ * \param mesh Mesh object to be modified.
+ *
+ * \ingroup mesh
+ */
+void
+lib3ds_mesh_free_texel_list(Lib3dsMesh *mesh)
+{
+  ASSERT(mesh);
+  if (mesh->texelL) {
+    ASSERT(mesh->texels);
+    free(mesh->texelL);
+    mesh->texelL=0;
+    mesh->texels=0;
+  }
+  else {
+    ASSERT(!mesh->texels);
+  }
+}
+
+
+/*!
+ * Allocate face list in mesh object.
+ *
+ * This function frees the current face list, if any, and allocates
+ * a new one large enough to hold the specified number of faces.
+ *
+ * \param mesh Mesh object for which points are to be allocated.
+ * \param faces Number of faces in the new face list.
+ *
+ * \return LIB3DS_TRUE on success, LIB3DS_FALSE on failure.
+ *
+ * \ingroup mesh
+ */
+Lib3dsBool
+lib3ds_mesh_new_face_list(Lib3dsMesh *mesh, Lib3dsDword faces)
+{
+  ASSERT(mesh);
+  if (mesh->faceL) {
+    ASSERT(mesh->faces);
+    lib3ds_mesh_free_face_list(mesh);
+  }
+  ASSERT(!mesh->faceL && !mesh->faces);
+  mesh->faces=0;
+  mesh->faceL=calloc(sizeof(Lib3dsFace)*faces,1);
+  if (!mesh->faceL) {
+    LIB3DS_ERROR_LOG;
+    return(LIB3DS_FALSE);
+  }
+  mesh->faces=faces;
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+ * Free face list in mesh object.
+ *
+ * The current face list is freed and set to NULL.  mesh->faces is
+ * set to zero.
+ *
+ * \param mesh Mesh object to be modified.
+ *
+ * \ingroup mesh
+ */
+void
+lib3ds_mesh_free_face_list(Lib3dsMesh *mesh)
+{
+  ASSERT(mesh);
+  if (mesh->faceL) {
+    ASSERT(mesh->faces);
+    free(mesh->faceL);
+    mesh->faceL=0;
+    mesh->faces=0;
+  }
+  else {
+    ASSERT(!mesh->faces);
+  }
+}
+
+
+typedef struct _Lib3dsFaces Lib3dsFaces; 
+
+struct _Lib3dsFaces {
+  Lib3dsFaces *next;
+  Lib3dsFace *face;
+};
+
+
+
+
+/*!
+ * Find the bounding box of a mesh object.
+ *
+ * \param mesh The mesh object
+ * \param min Returned bounding box
+ * \param max Returned bounding box
+ *
+ * \ingroup mesh
+ */
+void
+lib3ds_mesh_bounding_box(Lib3dsMesh *mesh, Lib3dsVector min, Lib3dsVector max)
+{
+  unsigned i,j;
+  Lib3dsFloat v;
+
+  if (!mesh->points) {
+    lib3ds_vector_zero(min);
+    lib3ds_vector_zero(max);
+    return;
+  }
+  lib3ds_vector_copy(min, mesh->pointL[0].pos);
+  lib3ds_vector_copy(max, mesh->pointL[0].pos);
+  for (i=1; i<mesh->points; ++i) {
+    for (j=0; j<3; ++j) {
+      v=mesh->pointL[i].pos[j];
+      if (v<min[j]) {
+        min[j]=v;
+      }
+      if (v>max[j]) {
+        max[j]=v;
+      }
+    }
+  };
+}
+
+
+/*!
+ * Calculates the vertex normals corresponding to the smoothing group
+ * settings for each face of a mesh.
+ *
+ * \param mesh      A pointer to the mesh to calculate the normals for.
+ * \param normalL   A pointer to a buffer to store the calculated
+ *                  normals. The buffer must have the size:
+ *                  3*sizeof(Lib3dsVector)*mesh->faces. 
+ *
+ * To allocate the normal buffer do for example the following:
+ * \code
+ *  Lib3dsVector *normalL = malloc(3*sizeof(Lib3dsVector)*mesh->faces);
+ * \endcode
+ *
+ * To access the normal of the i-th vertex of the j-th face do the 
+ * following:
+ * \code
+ *   normalL[3*j+i]
+ * \endcode
+ *
+ * \ingroup mesh
+ */
+void
+lib3ds_mesh_calculate_normals(Lib3dsMesh *mesh, Lib3dsVector *normalL)
+{
+  Lib3dsFaces **fl; 
+  Lib3dsFaces *fa; 
+  unsigned i,j,k;
+
+  if (!mesh->faces) {
+    return;
+  }
+
+  fl=calloc(sizeof(Lib3dsFaces*),mesh->points);
+  ASSERT(fl);
+  fa=calloc(sizeof(Lib3dsFaces),3*mesh->faces);
+  ASSERT(fa);
+  k=0;
+  for (i=0; i<mesh->faces; ++i) {
+    Lib3dsFace *f=&mesh->faceL[i];
+    for (j=0; j<3; ++j) {
+      Lib3dsFaces* l=&fa[k++];
+      ASSERT(f->points[j]<mesh->points);
+      l->face=f;
+      l->next=fl[f->points[j]];
+      fl[f->points[j]]=l;
+    }
+  }
+  
+  for (i=0; i<mesh->faces; ++i) {
+    Lib3dsFace *f=&mesh->faceL[i];
+    for (j=0; j<3; ++j) {
+      /* FIXME: static array needs at least check!! */
+      Lib3dsVector n,N[128];
+      Lib3dsFaces *p;
+      int k,l;
+      int found;
+
+      ASSERT(f->points[j]<mesh->points);
+
+      if (f->smoothing) {
+        lib3ds_vector_zero(n);
+        k=0;
+        for (p=fl[f->points[j]]; p; p=p->next) {
+          found=0;
+          for (l=0; l<k; ++l) {
+           if( l >= 128 )
+             printf("array N overflow: i=%d, j=%d, k=%d\n", i,j,k);
+            if (fabs(lib3ds_vector_dot(N[l], p->face->normal)-1.0)<1e-5) {
+              found=1;
+              break;
+            }
+          }
+          if (!found) {
+            if (f->smoothing & p->face->smoothing) {
+              lib3ds_vector_add(n,n, p->face->normal);
+              lib3ds_vector_copy(N[k], p->face->normal);
+              ++k;
+            }
+          }
+        }
+      } 
+      else {
+        lib3ds_vector_copy(n, f->normal);
+      }
+      lib3ds_vector_normalize(n);
+
+      lib3ds_vector_copy(normalL[3*i+j], n);
+    }
+  }
+
+  free(fa);
+  free(fl);
+}
+
+
+/*!
+ * This function prints data associated with the specified mesh such as
+ * vertex and point lists.
+ *
+ * \param mesh  Points to a mesh that you wish to view the data for.
+ *
+ * \return None
+ *
+ * \warning WIN32: Should only be used in a console window not in a GUI.
+ *
+ * \ingroup mesh
+ */
+void
+lib3ds_mesh_dump(Lib3dsMesh *mesh)
+{
+  unsigned i;
+  Lib3dsVector p;
+
+  ASSERT(mesh);
+  printf("  %s vertices=%ld faces=%ld\n",
+    mesh->name,
+    mesh->points,
+    mesh->faces
+  );
+  printf("  matrix:\n");
+  lib3ds_matrix_dump(mesh->matrix);
+  printf("  point list:\n");
+  for (i=0; i<mesh->points; ++i) {
+    lib3ds_vector_copy(p, mesh->pointL[i].pos);
+    printf ("    %8f %8f %8f\n", p[0], p[1], p[2]);
+  }
+  printf("  facelist:\n");
+  for (i=0; i<mesh->faces; ++i) {
+    printf ("    %4d %4d %4d  smoothing:%X  flags:%X  material:\"%s\"\n",
+      mesh->faceL[i].points[0],
+      mesh->faceL[i].points[1],
+      mesh->faceL[i].points[2],
+      (unsigned)mesh->faceL[i].smoothing,
+      mesh->faceL[i].flags,
+      mesh->faceL[i].material
+    );
+  }
+}
+
+
+/*!
+ * \ingroup mesh
+ */
+Lib3dsBool
+lib3ds_mesh_read(Lib3dsMesh *mesh, Lib3dsIo *io)
+{
+  Lib3dsChunk c;
+  Lib3dsWord chunk;
+
+  if (!lib3ds_chunk_read_start(&c, LIB3DS_N_TRI_OBJECT, io)) {
+    return(LIB3DS_FALSE);
+  }
+
+  while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) {
+    switch (chunk) {
+      case LIB3DS_MESH_MATRIX:
+        {
+          int i,j;
+          
+          lib3ds_matrix_identity(mesh->matrix);
+          for (i=0; i<4; i++) {
+            for (j=0; j<3; j++) {
+              mesh->matrix[i][j]=lib3ds_io_read_float(io);
+            }
+          }
+        }
+        break;
+      case LIB3DS_MESH_COLOR:
+        {
+          mesh->color=lib3ds_io_read_byte(io);
+        }
+        break;
+      case LIB3DS_POINT_ARRAY:
+        {
+          unsigned i,j;
+          unsigned points;
+          
+          lib3ds_mesh_free_point_list(mesh);
+          points=lib3ds_io_read_word(io);
+          if (points) {
+            if (!lib3ds_mesh_new_point_list(mesh, points)) {
+              LIB3DS_ERROR_LOG;
+              return(LIB3DS_FALSE);
+            }
+            for (i=0; i<mesh->points; ++i) {
+              for (j=0; j<3; ++j) {
+                mesh->pointL[i].pos[j]=lib3ds_io_read_float(io);
+              }
+            }
+            ASSERT((!mesh->flags) || (mesh->points==mesh->flags));
+            ASSERT((!mesh->texels) || (mesh->points==mesh->texels));
+          }
+        }
+        break;
+      case LIB3DS_POINT_FLAG_ARRAY:
+        {
+          unsigned i;
+          unsigned flags;
+          
+          lib3ds_mesh_free_flag_list(mesh);
+          flags=lib3ds_io_read_word(io);
+          if (flags) {
+            if (!lib3ds_mesh_new_flag_list(mesh, flags)) {
+              LIB3DS_ERROR_LOG;
+              return(LIB3DS_FALSE);
+            }
+            for (i=0; i<mesh->flags; ++i) {
+              mesh->flagL[i]=lib3ds_io_read_word(io);
+            }
+            ASSERT((!mesh->points) || (mesh->flags==mesh->points));
+            ASSERT((!mesh->texels) || (mesh->flags==mesh->texels));
+          }
+        }
+        break;
+      case LIB3DS_FACE_ARRAY:
+        {
+          lib3ds_chunk_read_reset(&c, io);
+          if (!face_array_read(mesh, io)) {
+            return(LIB3DS_FALSE);
+          }
+        }
+        break;
+      case LIB3DS_MESH_TEXTURE_INFO:
+        {
+          int i,j;
+
+          for (i=0; i<2; ++i) {
+            mesh->map_data.tile[i]=lib3ds_io_read_float(io);
+          }
+          for (i=0; i<3; ++i) {
+            mesh->map_data.pos[i]=lib3ds_io_read_float(io);
+          }
+          mesh->map_data.scale=lib3ds_io_read_float(io);
+
+          lib3ds_matrix_identity(mesh->map_data.matrix);
+          for (i=0; i<4; i++) {
+            for (j=0; j<3; j++) {
+              mesh->map_data.matrix[i][j]=lib3ds_io_read_float(io);
+            }
+          }
+          for (i=0; i<2; ++i) {
+            mesh->map_data.planar_size[i]=lib3ds_io_read_float(io);
+          }
+          mesh->map_data.cylinder_height=lib3ds_io_read_float(io);
+        }
+        break;
+      case LIB3DS_TEX_VERTS:
+        {
+          unsigned i;
+          unsigned texels;
+          
+          lib3ds_mesh_free_texel_list(mesh);
+          texels=lib3ds_io_read_word(io);
+          if (texels) {
+            if (!lib3ds_mesh_new_texel_list(mesh, texels)) {
+              LIB3DS_ERROR_LOG;
+              return(LIB3DS_FALSE);
+            }
+            for (i=0; i<mesh->texels; ++i) {
+              mesh->texelL[i][0]=lib3ds_io_read_float(io);
+              mesh->texelL[i][1]=lib3ds_io_read_float(io);
+            }
+            ASSERT((!mesh->points) || (mesh->texels==mesh->points));
+            ASSERT((!mesh->flags) || (mesh->texels==mesh->flags));
+          }
+        }
+        break;
+      default:
+        lib3ds_chunk_unknown(chunk);
+    }
+  }
+  {
+    unsigned j;
+
+    for (j=0; j<mesh->faces; ++j) {
+      ASSERT(mesh->faceL[j].points[0]<mesh->points);
+      ASSERT(mesh->faceL[j].points[1]<mesh->points);
+      ASSERT(mesh->faceL[j].points[2]<mesh->points);
+      lib3ds_vector_normal(
+        mesh->faceL[j].normal,
+        mesh->pointL[mesh->faceL[j].points[0]].pos,
+        mesh->pointL[mesh->faceL[j].points[1]].pos,
+        mesh->pointL[mesh->faceL[j].points[2]].pos
+      );
+    }
+  }
+  
+  lib3ds_chunk_read_end(&c, io);
+  return(LIB3DS_TRUE);
+}
+
+
+static Lib3dsBool
+point_array_write(Lib3dsMesh *mesh, Lib3dsIo *io)
+{
+  Lib3dsChunk c;
+  unsigned i;
+
+  if (!mesh->points || !mesh->pointL) {
+    return(LIB3DS_TRUE);
+  }
+  ASSERT(mesh->points<0x10000);
+  c.chunk=LIB3DS_POINT_ARRAY;
+  c.size=8+12*mesh->points;
+  lib3ds_chunk_write(&c, io);
+  
+  lib3ds_io_write_word(io, (Lib3dsWord)mesh->points);
+  for (i=0; i<mesh->points; ++i) {
+    lib3ds_io_write_vector(io, mesh->pointL[i].pos);
+  }
+  return(LIB3DS_TRUE);
+}
+
+
+static Lib3dsBool
+flag_array_write(Lib3dsMesh *mesh, Lib3dsIo *io)
+{
+  Lib3dsChunk c;
+  unsigned i;
+  
+  if (!mesh->flags || !mesh->flagL) {
+    return(LIB3DS_TRUE);
+  }
+  ASSERT(mesh->flags<0x10000);
+  c.chunk=LIB3DS_POINT_FLAG_ARRAY;
+  c.size=8+2*mesh->flags;
+  lib3ds_chunk_write(&c, io);
+  
+  lib3ds_io_write_word(io, (Lib3dsWord)mesh->flags);
+  for (i=0; i<mesh->flags; ++i) {
+    lib3ds_io_write_word(io, mesh->flagL[i]);
+  }
+  return(LIB3DS_TRUE);
+}
+
+
+static Lib3dsBool
+face_array_write(Lib3dsMesh *mesh, Lib3dsIo *io)
+{
+  Lib3dsChunk c;
+  
+  if (!mesh->faces || !mesh->faceL) {
+    return(LIB3DS_TRUE);
+  }
+  ASSERT(mesh->faces<0x10000);
+  c.chunk=LIB3DS_FACE_ARRAY;
+  if (!lib3ds_chunk_write_start(&c, io)) {
+    return(LIB3DS_FALSE);
+  }
+  {
+    unsigned i;
+
+    lib3ds_io_write_word(io, (Lib3dsWord)mesh->faces);
+    for (i=0; i<mesh->faces; ++i) {
+      lib3ds_io_write_word(io, mesh->faceL[i].points[0]);
+      lib3ds_io_write_word(io, mesh->faceL[i].points[1]);
+      lib3ds_io_write_word(io, mesh->faceL[i].points[2]);
+      lib3ds_io_write_word(io, mesh->faceL[i].flags);
+    }
+  }
+
+  { /*---- MSH_MAT_GROUP ----*/
+    Lib3dsChunk c;
+    unsigned i,j;
+    Lib3dsWord num;
+    char *matf=calloc(sizeof(char), mesh->faces);
+    if (!matf) {
+      return(LIB3DS_FALSE);
+    }
+    
+    for (i=0; i<mesh->faces; ++i) {
+      if (!matf[i] && strlen(mesh->faceL[i].material)) {
+        matf[i]=1;
+        num=1;
+        
+        for (j=i+1; j<mesh->faces; ++j) {
+          if (strcmp(mesh->faceL[i].material, mesh->faceL[j].material)==0) ++num;
+        }
+        
+        c.chunk=LIB3DS_MSH_MAT_GROUP;
+        c.size=6+ strlen(mesh->faceL[i].material)+1 +2+2*num;
+        lib3ds_chunk_write(&c, io);
+        lib3ds_io_write_string(io, mesh->faceL[i].material);
+        lib3ds_io_write_word(io, num);
+        lib3ds_io_write_word(io, (Lib3dsWord)i);
+        
+        for (j=i+1; j<mesh->faces; ++j) {
+          if (strcmp(mesh->faceL[i].material, mesh->faceL[j].material)==0) {
+            lib3ds_io_write_word(io, (Lib3dsWord)j);
+            matf[j]=1;
+          }
+        }
+      }      
+    }
+    free(matf);
+  }
+
+  { /*---- SMOOTH_GROUP ----*/
+    Lib3dsChunk c;
+    unsigned i;
+    
+    c.chunk=LIB3DS_SMOOTH_GROUP;
+    c.size=6+4*mesh->faces;
+    lib3ds_chunk_write(&c, io);
+    
+    for (i=0; i<mesh->faces; ++i) {
+      lib3ds_io_write_dword(io, mesh->faceL[i].smoothing);
+    }
+  }
+  
+  { /*---- MSH_BOXMAP ----*/
+    Lib3dsChunk c;
+
+    if (strlen(mesh->box_map.front) ||
+      strlen(mesh->box_map.back) ||
+      strlen(mesh->box_map.left) ||
+      strlen(mesh->box_map.right) ||
+      strlen(mesh->box_map.top) ||
+      strlen(mesh->box_map.bottom)) {
+    
+      c.chunk=LIB3DS_MSH_BOXMAP;
+      if (!lib3ds_chunk_write_start(&c, io)) {
+        return(LIB3DS_FALSE);
+      }
+      
+      lib3ds_io_write_string(io, mesh->box_map.front);
+      lib3ds_io_write_string(io, mesh->box_map.back);
+      lib3ds_io_write_string(io, mesh->box_map.left);
+      lib3ds_io_write_string(io, mesh->box_map.right);
+      lib3ds_io_write_string(io, mesh->box_map.top);
+      lib3ds_io_write_string(io, mesh->box_map.bottom);
+      
+      if (!lib3ds_chunk_write_end(&c, io)) {
+        return(LIB3DS_FALSE);
+      }
+    }
+  }
+
+  if (!lib3ds_chunk_write_end(&c, io)) {
+    return(LIB3DS_FALSE);
+  }
+  return(LIB3DS_TRUE);
+}
+
+
+static Lib3dsBool
+texel_array_write(Lib3dsMesh *mesh, Lib3dsIo *io)
+{
+  Lib3dsChunk c;
+  unsigned i;
+  
+  if (!mesh->texels || !mesh->texelL) {
+    return(LIB3DS_TRUE);
+  }
+  ASSERT(mesh->texels<0x10000);
+  c.chunk=LIB3DS_TEX_VERTS;
+  c.size=8+8*mesh->texels;
+  lib3ds_chunk_write(&c, io);
+  
+  lib3ds_io_write_word(io, (Lib3dsWord)mesh->texels);
+  for (i=0; i<mesh->texels; ++i) {
+    lib3ds_io_write_float(io, mesh->texelL[i][0]);
+    lib3ds_io_write_float(io, mesh->texelL[i][1]);
+  }
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+ * \ingroup mesh
+ */
+Lib3dsBool
+lib3ds_mesh_write(Lib3dsMesh *mesh, Lib3dsIo *io)
+{
+  Lib3dsChunk c;
+
+  c.chunk=LIB3DS_N_TRI_OBJECT;
+  if (!lib3ds_chunk_write_start(&c,io)) {
+    return(LIB3DS_FALSE);
+  }
+  if (!point_array_write(mesh, io)) {
+    return(LIB3DS_FALSE);
+  }
+  if (!texel_array_write(mesh, io)) {
+    return(LIB3DS_FALSE);
+  }
+
+  if (mesh->map_data.maptype!=LIB3DS_MAP_NONE) { /*---- LIB3DS_MESH_TEXTURE_INFO ----*/
+    Lib3dsChunk c;
+    int i,j;
+    
+    c.chunk=LIB3DS_MESH_TEXTURE_INFO;
+    c.size=92;
+    if (!lib3ds_chunk_write(&c,io)) {
+      return(LIB3DS_FALSE);
+    }
+
+    lib3ds_io_write_word(io, mesh->map_data.maptype);
+
+    for (i=0; i<2; ++i) {
+      lib3ds_io_write_float(io, mesh->map_data.tile[i]);
+    }
+    for (i=0; i<3; ++i) {
+      lib3ds_io_write_float(io, mesh->map_data.pos[i]);
+    }
+    lib3ds_io_write_float(io, mesh->map_data.scale);
+
+    for (i=0; i<4; i++) {
+      for (j=0; j<3; j++) {
+        lib3ds_io_write_float(io, mesh->map_data.matrix[i][j]);
+      }
+    }
+    for (i=0; i<2; ++i) {
+      lib3ds_io_write_float(io, mesh->map_data.planar_size[i]);
+    }
+    lib3ds_io_write_float(io, mesh->map_data.cylinder_height);
+  }
+
+  if (!flag_array_write(mesh, io)) {
+    return(LIB3DS_FALSE);
+  }
+  { /*---- LIB3DS_MESH_MATRIX ----*/
+    Lib3dsChunk c;
+    int i,j;
+
+    c.chunk=LIB3DS_MESH_MATRIX;
+    c.size=54;
+    if (!lib3ds_chunk_write(&c,io)) {
+      return(LIB3DS_FALSE);
+    }
+    for (i=0; i<4; i++) {
+      for (j=0; j<3; j++) {
+        lib3ds_io_write_float(io, mesh->matrix[i][j]);
+      }
+    }
+  }
+
+  if (mesh->color) { /*---- LIB3DS_MESH_COLOR ----*/
+    Lib3dsChunk c;
+    
+    c.chunk=LIB3DS_MESH_COLOR;
+    c.size=7;
+    if (!lib3ds_chunk_write(&c,io)) {
+      return(LIB3DS_FALSE);
+    }
+    lib3ds_io_write_byte(io, mesh->color);
+  }
+  if (!face_array_write(mesh, io)) {
+    return(LIB3DS_FALSE);
+  }
+
+  if (!lib3ds_chunk_write_end(&c,io)) {
+    return(LIB3DS_FALSE);
+  }
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+
+\typedef Lib3dsFace
+  \ingroup mesh
+  \sa _Lib3dsFace
+
+*/
+/*!
+
+\typedef Lib3dsBoxMap
+  \ingroup mesh
+  \sa _Lib3dsBoxMap
+
+*/
+/*!
+
+\typedef Lib3dsMapData
+  \ingroup mesh
+  \sa _Lib3dsMapData
+
+*/
+/*!
+
+\typedef Lib3dsMesh
+  \ingroup mesh
+  \sa _Lib3dsMesh
+
+*/
diff --git a/src/3dengfx/libs/lib3ds/mesh.h b/src/3dengfx/libs/lib3ds/mesh.h
new file mode 100644 (file)
index 0000000..61b336c
--- /dev/null
@@ -0,0 +1,153 @@
+/* -*- c -*- */
+#ifndef INCLUDED_LIB3DS_MESH_H
+#define INCLUDED_LIB3DS_MESH_H
+/*
+ * The 3D Studio File Format Library
+ * Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
+ * All rights reserved.
+ *
+ * This program is  free  software;  you can redistribute it and/or modify it
+ * under the terms of the  GNU Lesser General Public License  as published by 
+ * the  Free Software Foundation;  either version 2.1 of the License,  or (at 
+ * your option) any later version.
+ *
+ * This  program  is  distributed in  the  hope that it will  be useful,  but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public  
+ * License for more details.
+ *
+ * You should  have received  a copy of the GNU Lesser General Public License
+ * along with  this program;  if not, write to the  Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: mesh.h,v 1.16 2004/12/31 16:17:15 reed Exp $
+ */
+
+#ifndef INCLUDED_LIB3DS_TYPES_H
+#include <lib3ds/types.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*!
+ * Triangular mesh point
+ * \ingroup mesh
+ */
+typedef struct _Lib3dsPoint {
+    Lib3dsVector pos;
+} Lib3dsPoint;
+
+/*!
+ * Triangular mesh face
+ * \ingroup mesh
+ * \sa Lib3dsFaceFlag
+ */
+struct _Lib3dsFace {
+    Lib3dsUserData user;       /*! Arbitrary user data */
+    char material[64];         /*! Material name */
+    Lib3dsWord points[3];      /*! Indices into mesh points list */
+    Lib3dsWord flags;          /*! See Lib3dsFaceFlag, below */
+    Lib3dsDword smoothing;     /*! Bitmask; each bit identifies a group */
+    Lib3dsVector normal;
+};
+
+
+/*! Meaning of _Lib3dsFace::flags. ABC are points of the current face (A: is
+1st vertex, B is 2nd vertex, C is 3rd vertex */
+typedef enum {
+  LIB3DS_FACE_FLAG_VIS_AC = 0x1,       /*!< Bit 0: Edge visibility AC */
+  LIB3DS_FACE_FLAG_VIS_BC = 0x2,       /*!< Bit 1: Edge visibility BC */
+  LIB3DS_FACE_FLAG_VIS_AB = 0x4,       /*!< Bit 2: Edge visibility AB */
+  LIB3DS_FACE_FLAG_WRAP_U = 0x8,       /*!< Bit 3: Face is at tex U wrap seam */
+  LIB3DS_FACE_FLAG_WRAP_V = 0x10,      /*!< Bit 4: Face is at tex V wrap seam */
+  LIB3DS_FACE_FLAG_UNK7 = 0x80,        /* Bit 5-8: Unused ? */
+  LIB3DS_FACE_FLAG_UNK10 = 0x400,      /* Bit 9-10: Random ? */
+                                       /* Bit 11-12: Unused ? */
+  LIB3DS_FACE_FLAG_SELECT_3 = (1<<13),   /*!< Bit 13: Selection of the face in selection 3*/
+  LIB3DS_FACE_FLAG_SELECT_2 = (1<<14),   /*!< Bit 14: Selection of the face in selection 2*/
+  LIB3DS_FACE_FLAG_SELECT_1 = (1<<15)   /*!< Bit 15: Selection of the face in selection 1*/
+} Lib3dsFaceFlag;
+
+/*!
+ * Triangular mesh box mapping settings
+ * \ingroup mesh
+ */
+struct _Lib3dsBoxMap {
+    char front[64];
+    char back[64];
+    char left[64];
+    char right[64];
+    char top[64];
+    char bottom[64];
+};
+
+/*!
+ * Lib3dsMapData maptype
+ * \ingroup tracks
+ */
+typedef enum {
+  LIB3DS_MAP_NONE        =0xFFFF,
+  LIB3DS_MAP_PLANAR      =0,
+  LIB3DS_MAP_CYLINDRICAL =1,
+  LIB3DS_MAP_SPHERICAL   =2
+} Lib3dsMapType;
+
+/*!
+ * Triangular mesh texture mapping data
+ * \ingroup mesh
+ */
+struct _Lib3dsMapData {
+    Lib3dsWord maptype;
+    Lib3dsVector pos;
+    Lib3dsMatrix matrix;
+    Lib3dsFloat scale;
+    Lib3dsFloat tile[2];
+    Lib3dsFloat planar_size[2];
+    Lib3dsFloat cylinder_height;
+};
+
+/*!
+ * Triangular mesh object
+ * \ingroup mesh
+ */
+struct _Lib3dsMesh {
+    Lib3dsUserData user;       /*! Arbitrary user data */
+    Lib3dsMesh *next;
+    char name[64];             /*! Mesh name */
+    Lib3dsByte color;
+    Lib3dsMatrix matrix;       /*! Transformation matrix for mesh data */
+    Lib3dsDword points;                /*! Number of points in point list */
+    Lib3dsPoint *pointL;       /*! Point list */
+    Lib3dsDword flags;         /*! Number of flags in per-point flags list */
+    Lib3dsWord *flagL;         /*! Per-point flags list */
+    Lib3dsDword texels;                /*! Number of U-V texel coordinates */
+    Lib3dsTexel *texelL;       /*! U-V texel coordinates */
+    Lib3dsDword faces;         /*! Number of faces in face list */
+    Lib3dsFace *faceL;         /*! Face list */
+    Lib3dsBoxMap box_map;
+    Lib3dsMapData map_data;
+}; 
+
+extern LIB3DSAPI Lib3dsMesh* lib3ds_mesh_new(const char *name);
+extern LIB3DSAPI void lib3ds_mesh_free(Lib3dsMesh *mesh);
+extern LIB3DSAPI Lib3dsBool lib3ds_mesh_new_point_list(Lib3dsMesh *mesh, Lib3dsDword points);
+extern LIB3DSAPI void lib3ds_mesh_free_point_list(Lib3dsMesh *mesh);
+extern LIB3DSAPI Lib3dsBool lib3ds_mesh_new_flag_list(Lib3dsMesh *mesh, Lib3dsDword flags);
+extern LIB3DSAPI void lib3ds_mesh_free_flag_list(Lib3dsMesh *mesh);
+extern LIB3DSAPI Lib3dsBool lib3ds_mesh_new_texel_list(Lib3dsMesh *mesh, Lib3dsDword texels);
+extern LIB3DSAPI void lib3ds_mesh_free_texel_list(Lib3dsMesh *mesh);
+extern LIB3DSAPI Lib3dsBool lib3ds_mesh_new_face_list(Lib3dsMesh *mesh, Lib3dsDword flags);
+extern LIB3DSAPI void lib3ds_mesh_free_face_list(Lib3dsMesh *mesh);
+extern LIB3DSAPI void lib3ds_mesh_bounding_box(Lib3dsMesh *mesh, Lib3dsVector min, Lib3dsVector max);
+extern LIB3DSAPI void lib3ds_mesh_calculate_normals(Lib3dsMesh *mesh, Lib3dsVector *normalL);
+extern LIB3DSAPI void lib3ds_mesh_dump(Lib3dsMesh *mesh);
+extern LIB3DSAPI Lib3dsBool lib3ds_mesh_read(Lib3dsMesh *mesh, Lib3dsIo *io);
+extern LIB3DSAPI Lib3dsBool lib3ds_mesh_write(Lib3dsMesh *mesh, Lib3dsIo *io);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/src/3dengfx/libs/lib3ds/node.c b/src/3dengfx/libs/lib3ds/node.c
new file mode 100644 (file)
index 0000000..574d9b0
--- /dev/null
@@ -0,0 +1,1173 @@
+/*
+ * The 3D Studio File Format Library
+ * Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
+ * All rights reserved.
+ *
+ * This program is  free  software;  you can redistribute it and/or modify it
+ * under the terms of the  GNU Lesser General Public License  as published by 
+ * the  Free Software Foundation;  either version 2.1 of the License,  or (at 
+ * your option) any later version.
+ *
+ * This  program  is  distributed in  the  hope that it will  be useful,  but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public  
+ * License for more details.
+ *
+ * You should  have received  a copy of the GNU Lesser General Public License
+ * along with  this program;  if not, write to the  Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: node.c,v 1.13 2004/11/16 07:41:44 efalk Exp $
+ */
+#define LIB3DS_EXPORT
+#include <lib3ds/node.h>
+#include <lib3ds/file.h>
+#include <lib3ds/io.h>
+#include <lib3ds/chunk.h>
+#include <lib3ds/matrix.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#ifdef WITH_DMALLOC
+#include <dmalloc.h>
+#endif
+
+
+/*!
+ * \defgroup node Animation Nodes
+ *
+ * \author J.E. Hoffmann <je-h@gmx.net>
+ */
+
+
+/*!
+ * Create and return a new ambient node.
+ *
+ * The node is returned with an identity matrix.  All other fields
+ * are zero.
+ *
+ * \return Lib3dsNode
+ *
+ * \ingroup node
+ */
+Lib3dsNode*
+lib3ds_node_new_ambient()
+{
+  Lib3dsNode *node=(Lib3dsNode*)calloc(sizeof(Lib3dsNode), 1);
+  node->type=LIB3DS_AMBIENT_NODE;
+  lib3ds_matrix_identity(node->matrix);
+  return(node);
+}
+
+
+/*!
+ * Create and return a new object node.
+ *
+ * The node is returned with an identity matrix.  All other fields
+ * are zero.
+ *
+ * \return Lib3dsNode
+ *
+ * \ingroup node
+ */
+Lib3dsNode*
+lib3ds_node_new_object()
+{
+  Lib3dsNode *node=(Lib3dsNode*)calloc(sizeof(Lib3dsNode), 1);
+  node->type=LIB3DS_OBJECT_NODE;
+  lib3ds_matrix_identity(node->matrix);
+  return(node);
+}
+
+
+/*!
+ * Create and return a new camera node.
+ *
+ * The node is returned with an identity matrix.  All other fields
+ * are zero.
+ *
+ * \return Lib3dsNode
+ *
+ * \ingroup node
+ */
+Lib3dsNode*
+lib3ds_node_new_camera()
+{
+  Lib3dsNode *node=(Lib3dsNode*)calloc(sizeof(Lib3dsNode), 1);
+  node->type=LIB3DS_CAMERA_NODE;
+  lib3ds_matrix_identity(node->matrix);
+  return(node);
+}
+
+
+/*!
+ * Create and return a new target node.
+ *
+ * The node is returned with an identity matrix.  All other fields
+ * are zero.
+ *
+ * \return Lib3dsNode
+ *
+ * \ingroup node
+ */
+Lib3dsNode*
+lib3ds_node_new_target()
+{
+  Lib3dsNode *node=(Lib3dsNode*)calloc(sizeof(Lib3dsNode), 1);
+  node->type=LIB3DS_TARGET_NODE;
+  lib3ds_matrix_identity(node->matrix);
+  return(node);
+}
+
+
+/*!
+ * Create and return a new light node.
+ *
+ * The node is returned with an identity matrix.  All other fields
+ * are zero.
+ *
+ * \return Lib3dsNode
+ *
+ * \ingroup node
+ */
+Lib3dsNode*
+lib3ds_node_new_light()
+{
+  Lib3dsNode *node=(Lib3dsNode*)calloc(sizeof(Lib3dsNode), 1);
+  node->type=LIB3DS_LIGHT_NODE;
+  lib3ds_matrix_identity(node->matrix);
+  return(node);
+}
+
+
+/*!
+ * Create and return a new spot node.
+ *
+ * The node is returned with an identity matrix.  All other fields
+ * are zero.
+ *
+ * \return Lib3dsNode
+ *
+ * \ingroup node
+ */
+Lib3dsNode*
+lib3ds_node_new_spot()
+{
+  Lib3dsNode *node=(Lib3dsNode*)calloc(sizeof(Lib3dsNode), 1);
+  node->type=LIB3DS_SPOT_NODE;
+  lib3ds_matrix_identity(node->matrix);
+  return(node);
+}
+
+
+static void
+free_node_and_childs(Lib3dsNode *node)
+{
+  ASSERT(node);
+  switch (node->type) {
+    case LIB3DS_UNKNOWN_NODE:
+      break;
+    case LIB3DS_AMBIENT_NODE:
+      {
+        Lib3dsAmbientData *n=&node->data.ambient;
+        lib3ds_lin3_track_free_keys(&n->col_track);
+      }
+      break;
+    case LIB3DS_OBJECT_NODE:
+      {
+        Lib3dsObjectData *n=&node->data.object;
+
+        lib3ds_lin3_track_free_keys(&n->pos_track);
+        lib3ds_quat_track_free_keys(&n->rot_track);
+        lib3ds_lin3_track_free_keys(&n->scl_track);
+        lib3ds_bool_track_free_keys(&n->hide_track);
+        lib3ds_morph_track_free_keys(&n->morph_track);
+      }
+      break;
+    case LIB3DS_CAMERA_NODE:
+      {
+        Lib3dsCameraData *n=&node->data.camera;
+        lib3ds_lin3_track_free_keys(&n->pos_track);
+        lib3ds_lin1_track_free_keys(&n->fov_track);
+        lib3ds_lin1_track_free_keys(&n->roll_track);
+      }
+      break;
+    case LIB3DS_TARGET_NODE:
+      {
+        Lib3dsTargetData *n=&node->data.target;
+        lib3ds_lin3_track_free_keys(&n->pos_track);
+      }
+      break;
+    case LIB3DS_LIGHT_NODE:
+      {
+        Lib3dsLightData *n=&node->data.light;
+        lib3ds_lin3_track_free_keys(&n->pos_track);
+        lib3ds_lin3_track_free_keys(&n->col_track);
+        lib3ds_lin1_track_free_keys(&n->hotspot_track);
+        lib3ds_lin1_track_free_keys(&n->falloff_track);
+        lib3ds_lin1_track_free_keys(&n->roll_track);
+      }
+      break;
+    case LIB3DS_SPOT_NODE:
+      {
+        Lib3dsSpotData *n=&node->data.spot;
+        lib3ds_lin3_track_free_keys(&n->pos_track);
+      }
+      break;
+  }
+  {
+    Lib3dsNode *p,*q;
+    for (p=node->childs; p; p=q) {
+      q=p->next;
+      free_node_and_childs(p);
+    }
+  }
+  node->type=LIB3DS_UNKNOWN_NODE;
+  free(node);
+}
+
+
+/*!
+ * Free a node and all of its resources.
+ *
+ * \param node Lib3dsNode object to be freed.
+ *
+ * \ingroup node
+ */
+void
+lib3ds_node_free(Lib3dsNode *node)
+{
+  ASSERT(node);
+  free_node_and_childs(node);
+}
+
+
+/*!
+ * Evaluate an animation node.
+ *
+ * Recursively sets node and its children to their appropriate values
+ * for this point in the animation.
+ *
+ * \param node Node to be evaluated.
+ * \param t time value, between 0. and file->frames
+ *
+ * \ingroup node
+ */
+void
+lib3ds_node_eval(Lib3dsNode *node, Lib3dsFloat t)
+{
+  ASSERT(node);
+  switch (node->type) {
+    case LIB3DS_UNKNOWN_NODE:
+      {
+        ASSERT(LIB3DS_FALSE);
+      }
+      break;
+    case LIB3DS_AMBIENT_NODE:
+      {
+        Lib3dsAmbientData *n=&node->data.ambient;
+        if (node->parent) {
+          lib3ds_matrix_copy(node->matrix, node->parent->matrix);
+        }
+        else {
+          lib3ds_matrix_identity(node->matrix);
+        }
+        lib3ds_lin3_track_eval(&n->col_track, n->col, t);
+      }
+      break;
+    case LIB3DS_OBJECT_NODE:
+      {
+        Lib3dsMatrix M;
+        Lib3dsObjectData *n=&node->data.object;
+
+        lib3ds_lin3_track_eval(&n->pos_track, n->pos, t);
+        lib3ds_quat_track_eval(&n->rot_track, n->rot, t);
+        lib3ds_lin3_track_eval(&n->scl_track, n->scl, t);
+        lib3ds_bool_track_eval(&n->hide_track, &n->hide, t);
+        lib3ds_morph_track_eval(&n->morph_track, n->morph, t);
+
+        lib3ds_matrix_identity(M);
+        lib3ds_matrix_translate(M, n->pos);
+        lib3ds_matrix_rotate(M, n->rot);
+        lib3ds_matrix_scale(M, n->scl);
+        
+        if (node->parent) {
+          lib3ds_matrix_mul(node->matrix, node->parent->matrix, M);
+        }
+        else {
+          lib3ds_matrix_copy(node->matrix, M);
+        }
+      }
+      break;
+    case LIB3DS_CAMERA_NODE:
+      {
+        Lib3dsCameraData *n=&node->data.camera;
+        lib3ds_lin3_track_eval(&n->pos_track, n->pos, t);
+        lib3ds_lin1_track_eval(&n->fov_track, &n->fov, t);
+        lib3ds_lin1_track_eval(&n->roll_track, &n->roll, t);
+        if (node->parent) {
+          lib3ds_matrix_copy(node->matrix, node->parent->matrix);
+        }
+        else {
+          lib3ds_matrix_identity(node->matrix);
+        }
+        lib3ds_matrix_translate(node->matrix, n->pos);
+      }
+      break;
+    case LIB3DS_TARGET_NODE:
+      {
+        Lib3dsTargetData *n=&node->data.target;
+        lib3ds_lin3_track_eval(&n->pos_track, n->pos, t);
+        if (node->parent) {
+          lib3ds_matrix_copy(node->matrix, node->parent->matrix);
+        }
+        else {
+          lib3ds_matrix_identity(node->matrix);
+        }
+        lib3ds_matrix_translate(node->matrix, n->pos);
+      }
+      break;
+    case LIB3DS_LIGHT_NODE:
+      {
+        Lib3dsLightData *n=&node->data.light;
+        lib3ds_lin3_track_eval(&n->pos_track, n->pos, t);
+        lib3ds_lin3_track_eval(&n->col_track, n->col, t);
+        lib3ds_lin1_track_eval(&n->hotspot_track, &n->hotspot, t);
+        lib3ds_lin1_track_eval(&n->falloff_track, &n->falloff, t);
+        lib3ds_lin1_track_eval(&n->roll_track, &n->roll, t);
+        if (node->parent) {
+          lib3ds_matrix_copy(node->matrix, node->parent->matrix);
+        }
+        else {
+          lib3ds_matrix_identity(node->matrix);
+        }
+        lib3ds_matrix_translate(node->matrix, n->pos);
+      }
+      break;
+    case LIB3DS_SPOT_NODE:
+      {
+        Lib3dsSpotData *n=&node->data.spot;
+        lib3ds_lin3_track_eval(&n->pos_track, n->pos, t);
+        if (node->parent) {
+          lib3ds_matrix_copy(node->matrix, node->parent->matrix);
+        }
+        else {
+          lib3ds_matrix_identity(node->matrix);
+        }
+        lib3ds_matrix_translate(node->matrix, n->pos);
+      }
+      break;
+  }
+  {
+    Lib3dsNode *p;
+
+    for (p=node->childs; p!=0; p=p->next) {
+      lib3ds_node_eval(p, t);
+    }
+  }
+}
+
+
+/*!
+ * Return a node object by name and type.
+ *
+ * This function performs a recursive search for the specified node.
+ * Both name and type must match.
+ *
+ * \param node The parent node for the search
+ * \param name The target node name.
+ * \param type The target node type
+ *
+ * \return A pointer to the first matching node, or NULL if not found.
+ *
+ * \ingroup node
+ */
+Lib3dsNode*
+lib3ds_node_by_name(Lib3dsNode *node, const char* name, Lib3dsNodeTypes type)
+{
+  Lib3dsNode *p,*q;
+
+  for (p=node->childs; p!=0; p=p->next) {
+    if ((p->type==type) && (strcmp(p->name, name)==0)) {
+      return(p);
+    }
+    q=lib3ds_node_by_name(p, name, type);
+    if (q) {
+      return(q);
+    }
+  }
+  return(0);
+}
+
+
+/*!
+ * Return a node object by id.
+ *
+ * This function performs a recursive search for the specified node.
+ *
+ * \param node The parent node for the search
+ * \param node_id The target node id.
+ *
+ * \return A pointer to the first matching node, or NULL if not found.
+ *
+ * \ingroup node
+ */
+Lib3dsNode*
+lib3ds_node_by_id(Lib3dsNode *node, Lib3dsWord node_id)
+{
+  Lib3dsNode *p,*q;
+
+  for (p=node->childs; p!=0; p=p->next) {
+    if (p->node_id==node_id) {
+      return(p);
+    }
+    q=lib3ds_node_by_id(p, node_id);
+    if (q) {
+      return(q);
+    }
+  }
+  return(0);
+}
+
+
+static const char* node_names_table[]= {
+  "***Unknown***",
+  "Ambient",
+  "Object",
+  "Camera",
+  "Target",
+  "Light",
+  "Spot"
+};
+
+
+/*!
+ * Dump node and all descendants recursively.
+ *
+ * \param node The top-level node to be dumped.
+ * \param level current recursion depth
+ *
+ * \ingroup node
+ */
+void
+lib3ds_node_dump(Lib3dsNode *node, Lib3dsIntd level)
+{
+  Lib3dsNode *p;
+  char l[128];
+
+  ASSERT(node);
+  memset(l, ' ', 2*level);
+  l[2*level]=0;
+
+  if (node->type==LIB3DS_OBJECT_NODE) {
+    printf("%s%s [%s] (%s)\n",
+      l,
+      node->name,
+      node->data.object.instance,
+      node_names_table[node->type]
+    );
+  }
+  else {
+    printf("%s%s (%s)\n",
+      l,
+      node->name,
+      node_names_table[node->type]
+    );
+  }
+  
+  for (p=node->childs; p!=0; p=p->next) {
+    lib3ds_node_dump(p, level+1);
+  }
+}
+
+
+/*!
+ * \ingroup node
+ */
+Lib3dsBool
+lib3ds_node_read(Lib3dsNode *node, Lib3dsFile *file, Lib3dsIo *io)
+{
+  Lib3dsChunk c;
+  Lib3dsWord chunk;
+
+  ASSERT(node);
+  if (!lib3ds_chunk_read_start(&c, 0, io)) {
+    return(LIB3DS_FALSE);
+  }
+  switch (c.chunk) {
+    case LIB3DS_AMBIENT_NODE_TAG:
+    case LIB3DS_OBJECT_NODE_TAG:
+    case LIB3DS_CAMERA_NODE_TAG:
+    case LIB3DS_TARGET_NODE_TAG:
+    case LIB3DS_LIGHT_NODE_TAG:
+    case LIB3DS_SPOTLIGHT_NODE_TAG:
+    case LIB3DS_L_TARGET_NODE_TAG:
+      break;
+    default:
+      return(LIB3DS_FALSE);
+  }
+
+  while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) {
+    switch (chunk) {
+      case LIB3DS_NODE_ID:
+        {
+          node->node_id=lib3ds_io_read_word(io);
+          lib3ds_chunk_dump_info("  ID = %d", (short)node->node_id);
+        }
+        break;
+      case LIB3DS_NODE_HDR:
+        {
+          if (!lib3ds_io_read_string(io, node->name, 64)) {
+            return(LIB3DS_FALSE);
+          }
+          node->flags1=lib3ds_io_read_word(io);
+          node->flags2=lib3ds_io_read_word(io);
+          node->parent_id=lib3ds_io_read_word(io);
+          lib3ds_chunk_dump_info("  NAME =%s", node->name);
+          lib3ds_chunk_dump_info("  PARENT=%d", (short)node->parent_id);
+        }
+        break;
+      case LIB3DS_PIVOT:
+        {
+          if (node->type==LIB3DS_OBJECT_NODE) {
+            int i;
+            for (i=0; i<3; ++i) {
+              node->data.object.pivot[i]=lib3ds_io_read_float(io);
+            }
+          }
+          else {
+            lib3ds_chunk_unknown(chunk);
+          }
+        }
+        break;
+      case LIB3DS_INSTANCE_NAME:
+        {
+          if (node->type==LIB3DS_OBJECT_NODE) {
+            if (!lib3ds_io_read_string(io, node->data.object.instance, 64)) {
+              return(LIB3DS_FALSE);
+            }
+          }
+          else {
+            lib3ds_chunk_unknown(chunk);
+          }
+        }
+        break;
+      case LIB3DS_BOUNDBOX:
+        {
+          if (node->type==LIB3DS_OBJECT_NODE) {
+            int i;
+            for (i=0; i<3; ++i) {
+              node->data.object.bbox_min[i]=lib3ds_io_read_float(io);
+            }
+            for (i=0; i<3; ++i) {
+              node->data.object.bbox_max[i]=lib3ds_io_read_float(io);
+            }
+          }
+          else {
+            lib3ds_chunk_unknown(chunk);
+          }
+        }
+        break;
+      case LIB3DS_COL_TRACK_TAG:
+        {
+          Lib3dsBool result=LIB3DS_TRUE;
+          
+          switch (node->type) {
+            case LIB3DS_AMBIENT_NODE:
+              result=lib3ds_lin3_track_read(&node->data.ambient.col_track, io);
+              break;
+            case LIB3DS_LIGHT_NODE:
+              result=lib3ds_lin3_track_read(&node->data.light.col_track, io);
+              break;
+            default:
+              lib3ds_chunk_unknown(chunk);
+          }
+          if (!result) {
+            return(LIB3DS_FALSE);
+          }
+        }
+        break;
+      case LIB3DS_POS_TRACK_TAG:
+        {
+          Lib3dsBool result=LIB3DS_TRUE;
+
+          switch (node->type) {
+            case LIB3DS_OBJECT_NODE:
+              result=lib3ds_lin3_track_read(&node->data.object.pos_track, io);
+              break;
+            case LIB3DS_CAMERA_NODE:
+              result=lib3ds_lin3_track_read(&node->data.camera.pos_track, io);
+              break;
+            case LIB3DS_TARGET_NODE:
+              result=lib3ds_lin3_track_read(&node->data.target.pos_track, io);
+              break;
+            case LIB3DS_LIGHT_NODE:
+              result=lib3ds_lin3_track_read(&node->data.light.pos_track, io);
+              break;
+            case LIB3DS_SPOT_NODE:
+              result=lib3ds_lin3_track_read(&node->data.spot.pos_track, io);
+              break;
+            default:
+              lib3ds_chunk_unknown(chunk);
+          }
+          if (!result) {
+            return(LIB3DS_FALSE);
+          }
+        }
+        break;
+      case LIB3DS_ROT_TRACK_TAG:
+        {
+          if (node->type==LIB3DS_OBJECT_NODE) {
+            if (!lib3ds_quat_track_read(&node->data.object.rot_track, io)) {
+              return(LIB3DS_FALSE);
+            }
+          }
+          else {
+            lib3ds_chunk_unknown(chunk);
+          }
+        }
+        break;
+      case LIB3DS_SCL_TRACK_TAG:
+        {
+          if (node->type==LIB3DS_OBJECT_NODE) {
+            if (!lib3ds_lin3_track_read(&node->data.object.scl_track, io)) {
+              return(LIB3DS_FALSE);
+            }
+          }
+          else {
+            lib3ds_chunk_unknown(chunk);
+          }
+        }
+        break;
+      case LIB3DS_FOV_TRACK_TAG:
+        {
+          if (node->type==LIB3DS_CAMERA_NODE) {
+            if (!lib3ds_lin1_track_read(&node->data.camera.fov_track, io)) {
+              return(LIB3DS_FALSE);
+            }
+          }
+          else {
+            lib3ds_chunk_unknown(chunk);
+          }
+        }
+        break;
+      case LIB3DS_HOT_TRACK_TAG:
+        {
+          if (node->type==LIB3DS_LIGHT_NODE) {
+            if (!lib3ds_lin1_track_read(&node->data.light.hotspot_track, io)) {
+              return(LIB3DS_FALSE);
+            }
+          }
+          else {
+            lib3ds_chunk_unknown(chunk);
+          }
+        }
+        break;
+      case LIB3DS_FALL_TRACK_TAG:
+        {
+          if (node->type==LIB3DS_LIGHT_NODE) {
+            if (!lib3ds_lin1_track_read(&node->data.light.falloff_track, io)) {
+              return(LIB3DS_FALSE);
+            }
+          }
+          else {
+            lib3ds_chunk_unknown(chunk);
+          }
+        }
+        break;
+      case LIB3DS_ROLL_TRACK_TAG:
+        {
+          Lib3dsBool result=LIB3DS_TRUE;
+
+          switch (node->type) {
+            case LIB3DS_CAMERA_NODE:
+              result=lib3ds_lin1_track_read(&node->data.camera.roll_track, io);
+              break;
+            case LIB3DS_LIGHT_NODE:
+              result=lib3ds_lin1_track_read(&node->data.light.roll_track, io);
+              break;
+            default:
+              lib3ds_chunk_unknown(chunk);
+          }
+          if (!result) {
+            return(LIB3DS_FALSE);
+          }
+        }
+        break;
+      case LIB3DS_HIDE_TRACK_TAG:
+        {
+          if (node->type==LIB3DS_OBJECT_NODE) {
+            if (!lib3ds_bool_track_read(&node->data.object.hide_track, io)) {
+              return(LIB3DS_FALSE);
+            }
+          }
+          else {
+            lib3ds_chunk_unknown(chunk);
+          }
+        }
+        break;
+      case LIB3DS_MORPH_SMOOTH:
+        {
+          if (node->type==LIB3DS_OBJECT_NODE) {
+            node->data.object.morph_smooth=lib3ds_io_read_float(io);
+          }
+          else {
+            lib3ds_chunk_unknown(chunk);
+          }
+        }
+        break;
+      case LIB3DS_MORPH_TRACK_TAG:
+        {
+          if (node->type==LIB3DS_OBJECT_NODE) {
+            if (!lib3ds_morph_track_read(&node->data.object.morph_track, io)) {
+              return(LIB3DS_FALSE);
+            }
+          }
+          else {
+            lib3ds_chunk_unknown(chunk);
+          }
+        }
+        break;
+      default:
+        lib3ds_chunk_unknown(chunk);
+    }
+  }
+
+  lib3ds_chunk_read_end(&c, io);
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+ * \ingroup node
+ */
+Lib3dsBool
+lib3ds_node_write(Lib3dsNode *node, Lib3dsFile *file, Lib3dsIo *io)
+{
+  Lib3dsChunk c;
+
+  switch (node->type) {
+    case LIB3DS_AMBIENT_NODE:
+      c.chunk=LIB3DS_AMBIENT_NODE_TAG;
+      break;
+    case LIB3DS_OBJECT_NODE:
+      c.chunk=LIB3DS_OBJECT_NODE_TAG;
+      break;
+    case LIB3DS_CAMERA_NODE:
+      c.chunk=LIB3DS_CAMERA_NODE_TAG;
+      break;
+    case LIB3DS_TARGET_NODE:
+      c.chunk=LIB3DS_TARGET_NODE_TAG;
+      break;
+    case LIB3DS_LIGHT_NODE:
+      if (lib3ds_file_node_by_name(file, node->name, LIB3DS_SPOT_NODE)) {
+        c.chunk=LIB3DS_SPOTLIGHT_NODE_TAG;
+      }
+      else {
+        c.chunk=LIB3DS_LIGHT_NODE_TAG;
+      }
+      break;
+    case LIB3DS_SPOT_NODE:
+      c.chunk=LIB3DS_L_TARGET_NODE_TAG;
+      break;
+    default:
+      return(LIB3DS_FALSE);
+  }
+  if (!lib3ds_chunk_write_start(&c,io)) {
+    return(LIB3DS_FALSE);
+  }
+
+  { /*---- LIB3DS_NODE_ID ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_NODE_ID;
+    c.size=8;
+    lib3ds_chunk_write(&c,io);
+    lib3ds_io_write_intw(io, node->node_id);
+  }
+
+  { /*---- LIB3DS_NODE_HDR ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_NODE_HDR;
+    c.size=6+ 1+strlen(node->name) +2+2+2;
+    lib3ds_chunk_write(&c,io);
+    lib3ds_io_write_string(io, node->name);
+    lib3ds_io_write_word(io, node->flags1);
+    lib3ds_io_write_word(io, node->flags2);
+    lib3ds_io_write_word(io, node->parent_id);
+  }
+
+  switch (c.chunk) {
+    case LIB3DS_AMBIENT_NODE_TAG:
+      { /*---- LIB3DS_COL_TRACK_TAG ----*/
+        Lib3dsChunk c;
+        c.chunk=LIB3DS_COL_TRACK_TAG;
+        if (!lib3ds_chunk_write_start(&c,io)) {
+          return(LIB3DS_FALSE);
+        }
+        if (!lib3ds_lin3_track_write(&node->data.ambient.col_track,io)) {
+          return(LIB3DS_FALSE);
+        }
+        if (!lib3ds_chunk_write_end(&c,io)) {
+          return(LIB3DS_FALSE);
+        }
+      }
+      break;
+    case LIB3DS_OBJECT_NODE_TAG:
+      { /*---- LIB3DS_PIVOT ----*/
+        Lib3dsChunk c;
+        c.chunk=LIB3DS_PIVOT;
+        c.size=18;
+        lib3ds_chunk_write(&c,io);
+        lib3ds_io_write_vector(io, node->data.object.pivot);
+      }
+      { /*---- LIB3DS_INSTANCE_NAME ----*/
+        Lib3dsChunk c;
+        const char *name;
+        if (strlen(node->data.object.instance)) {
+          name=node->data.object.instance;
+
+          c.chunk=LIB3DS_INSTANCE_NAME;
+          c.size=6+1+strlen(name);
+          lib3ds_chunk_write(&c,io);
+          lib3ds_io_write_string(io, name);
+        }
+      }
+      {
+        int i;
+        for (i=0; i<3; ++i) {
+          if ((fabs(node->data.object.bbox_min[i])>LIB3DS_EPSILON) ||
+            (fabs(node->data.object.bbox_max[i])>LIB3DS_EPSILON)) {
+            break;
+          }
+        }
+        
+        if (i<3) { /*---- LIB3DS_BOUNDBOX ----*/
+          Lib3dsChunk c;
+          c.chunk=LIB3DS_BOUNDBOX;
+          c.size=30;
+          lib3ds_chunk_write(&c,io);
+          lib3ds_io_write_vector(io, node->data.object.bbox_min);
+          lib3ds_io_write_vector(io, node->data.object.bbox_max);
+        }
+      }
+      { /*---- LIB3DS_POS_TRACK_TAG ----*/
+        Lib3dsChunk c;
+        c.chunk=LIB3DS_POS_TRACK_TAG;
+        if (!lib3ds_chunk_write_start(&c,io)) {
+          return(LIB3DS_FALSE);
+        }
+        if (!lib3ds_lin3_track_write(&node->data.object.pos_track,io)) {
+          return(LIB3DS_FALSE);
+        }
+        if (!lib3ds_chunk_write_end(&c,io)) {
+          return(LIB3DS_FALSE);
+        }
+      }
+      { /*---- LIB3DS_ROT_TRACK_TAG ----*/
+        Lib3dsChunk c;
+        c.chunk=LIB3DS_ROT_TRACK_TAG;
+        if (!lib3ds_chunk_write_start(&c,io)) {
+          return(LIB3DS_FALSE);
+        }
+        if (!lib3ds_quat_track_write(&node->data.object.rot_track,io)) {
+          return(LIB3DS_FALSE);
+        }
+        if (!lib3ds_chunk_write_end(&c,io)) {
+          return(LIB3DS_FALSE);
+        }
+      }
+      { /*---- LIB3DS_SCL_TRACK_TAG ----*/
+        Lib3dsChunk c;
+        c.chunk=LIB3DS_SCL_TRACK_TAG;
+        if (!lib3ds_chunk_write_start(&c,io)) {
+          return(LIB3DS_FALSE);
+        }
+        if (!lib3ds_lin3_track_write(&node->data.object.scl_track,io)) {
+          return(LIB3DS_FALSE);
+        }
+        if (!lib3ds_chunk_write_end(&c,io)) {
+          return(LIB3DS_FALSE);
+        }
+      }
+      if (node->data.object.hide_track.keyL) { /*---- LIB3DS_HIDE_TRACK_TAG ----*/
+        Lib3dsChunk c;
+        c.chunk=LIB3DS_HIDE_TRACK_TAG;
+        if (!lib3ds_chunk_write_start(&c,io)) {
+          return(LIB3DS_FALSE);
+        }
+        if (!lib3ds_bool_track_write(&node->data.object.hide_track,io)) {
+          return(LIB3DS_FALSE);
+        }
+        if (!lib3ds_chunk_write_end(&c,io)) {
+          return(LIB3DS_FALSE);
+        }
+      }
+      if (fabs(node->data.object.morph_smooth)>LIB3DS_EPSILON){ /*---- LIB3DS_MORPH_SMOOTH ----*/
+        Lib3dsChunk c;
+        c.chunk=LIB3DS_MORPH_SMOOTH;
+        c.size=10;
+        lib3ds_chunk_write(&c,io);
+        lib3ds_io_write_float(io, node->data.object.morph_smooth);
+      }
+      break;
+    case LIB3DS_CAMERA_NODE_TAG:
+      { /*---- LIB3DS_POS_TRACK_TAG ----*/
+        Lib3dsChunk c;
+        c.chunk=LIB3DS_POS_TRACK_TAG;
+        if (!lib3ds_chunk_write_start(&c,io)) {
+          return(LIB3DS_FALSE);
+        }
+        if (!lib3ds_lin3_track_write(&node->data.camera.pos_track,io)) {
+          return(LIB3DS_FALSE);
+        }
+        if (!lib3ds_chunk_write_end(&c,io)) {
+          return(LIB3DS_FALSE);
+        }
+      }
+      { /*---- LIB3DS_FOV_TRACK_TAG ----*/
+        Lib3dsChunk c;
+        c.chunk=LIB3DS_FOV_TRACK_TAG;
+        if (!lib3ds_chunk_write_start(&c,io)) {
+          return(LIB3DS_FALSE);
+        }
+        if (!lib3ds_lin1_track_write(&node->data.camera.fov_track,io)) {
+          return(LIB3DS_FALSE);
+        }
+        if (!lib3ds_chunk_write_end(&c,io)) {
+          return(LIB3DS_FALSE);
+        }
+      }
+      { /*---- LIB3DS_ROLL_TRACK_TAG ----*/
+        Lib3dsChunk c;
+        c.chunk=LIB3DS_ROLL_TRACK_TAG;
+        if (!lib3ds_chunk_write_start(&c,io)) {
+          return(LIB3DS_FALSE);
+        }
+        if (!lib3ds_lin1_track_write(&node->data.camera.roll_track,io)) {
+          return(LIB3DS_FALSE);
+        }
+        if (!lib3ds_chunk_write_end(&c,io)) {
+          return(LIB3DS_FALSE);
+        }
+      }
+      break;
+    case LIB3DS_TARGET_NODE_TAG:
+      { /*---- LIB3DS_POS_TRACK_TAG ----*/
+        Lib3dsChunk c;
+        c.chunk=LIB3DS_POS_TRACK_TAG;
+        if (!lib3ds_chunk_write_start(&c,io)) {
+          return(LIB3DS_FALSE);
+        }
+        if (!lib3ds_lin3_track_write(&node->data.target.pos_track,io)) {
+          return(LIB3DS_FALSE);
+        }
+        if (!lib3ds_chunk_write_end(&c,io)) {
+          return(LIB3DS_FALSE);
+        }
+      }
+      break;
+    case LIB3DS_LIGHT_NODE_TAG:
+      { /*---- LIB3DS_POS_TRACK_TAG ----*/
+        Lib3dsChunk c;
+        c.chunk=LIB3DS_POS_TRACK_TAG;
+        if (!lib3ds_chunk_write_start(&c,io)) {
+          return(LIB3DS_FALSE);
+        }
+        if (!lib3ds_lin3_track_write(&node->data.light.pos_track,io)) {
+          return(LIB3DS_FALSE);
+        }
+        if (!lib3ds_chunk_write_end(&c,io)) {
+          return(LIB3DS_FALSE);
+        }
+      }
+      { /*---- LIB3DS_COL_TRACK_TAG ----*/
+        Lib3dsChunk c;
+        c.chunk=LIB3DS_COL_TRACK_TAG;
+        if (!lib3ds_chunk_write_start(&c,io)) {
+          return(LIB3DS_FALSE);
+        }
+        if (!lib3ds_lin3_track_write(&node->data.light.col_track,io)) {
+          return(LIB3DS_FALSE);
+        }
+        if (!lib3ds_chunk_write_end(&c,io)) {
+          return(LIB3DS_FALSE);
+        }
+      }
+      break;
+    case LIB3DS_SPOTLIGHT_NODE_TAG:
+      { /*---- LIB3DS_POS_TRACK_TAG ----*/
+        Lib3dsChunk c;
+        c.chunk=LIB3DS_POS_TRACK_TAG;
+        if (!lib3ds_chunk_write_start(&c,io)) {
+          return(LIB3DS_FALSE);
+        }
+        if (!lib3ds_lin3_track_write(&node->data.light.pos_track,io)) {
+          return(LIB3DS_FALSE);
+        }
+        if (!lib3ds_chunk_write_end(&c,io)) {
+          return(LIB3DS_FALSE);
+        }
+      }
+      { /*---- LIB3DS_COL_TRACK_TAG ----*/
+        Lib3dsChunk c;
+        c.chunk=LIB3DS_COL_TRACK_TAG;
+        if (!lib3ds_chunk_write_start(&c,io)) {
+          return(LIB3DS_FALSE);
+        }
+        if (!lib3ds_lin3_track_write(&node->data.light.col_track,io)) {
+          return(LIB3DS_FALSE);
+        }
+        if (!lib3ds_chunk_write_end(&c,io)) {
+          return(LIB3DS_FALSE);
+        }
+      }
+      { /*---- LIB3DS_HOT_TRACK_TAG ----*/
+        Lib3dsChunk c;
+        c.chunk=LIB3DS_HOT_TRACK_TAG;
+        if (!lib3ds_chunk_write_start(&c,io)) {
+          return(LIB3DS_FALSE);
+        }
+        if (!lib3ds_lin1_track_write(&node->data.light.hotspot_track,io)) {
+          return(LIB3DS_FALSE);
+        }
+        if (!lib3ds_chunk_write_end(&c,io)) {
+          return(LIB3DS_FALSE);
+        }
+      }
+      { /*---- LIB3DS_FALL_TRACK_TAG ----*/
+        Lib3dsChunk c;
+        c.chunk=LIB3DS_FALL_TRACK_TAG;
+        if (!lib3ds_chunk_write_start(&c,io)) {
+          return(LIB3DS_FALSE);
+        }
+        if (!lib3ds_lin1_track_write(&node->data.light.falloff_track,io)) {
+          return(LIB3DS_FALSE);
+        }
+        if (!lib3ds_chunk_write_end(&c,io)) {
+          return(LIB3DS_FALSE);
+        }
+      }
+      { /*---- LIB3DS_ROLL_TRACK_TAG ----*/
+        Lib3dsChunk c;
+        c.chunk=LIB3DS_ROLL_TRACK_TAG;
+        if (!lib3ds_chunk_write_start(&c,io)) {
+          return(LIB3DS_FALSE);
+        }
+        if (!lib3ds_lin1_track_write(&node->data.light.roll_track,io)) {
+          return(LIB3DS_FALSE);
+        }
+        if (!lib3ds_chunk_write_end(&c,io)) {
+          return(LIB3DS_FALSE);
+        }
+      }
+      break;
+    case LIB3DS_L_TARGET_NODE_TAG:
+      { /*---- LIB3DS_POS_TRACK_TAG ----*/
+        Lib3dsChunk c;
+        c.chunk=LIB3DS_POS_TRACK_TAG;
+        if (!lib3ds_chunk_write_start(&c,io)) {
+          return(LIB3DS_FALSE);
+        }
+        if (!lib3ds_lin3_track_write(&node->data.spot.pos_track,io)) {
+          return(LIB3DS_FALSE);
+        }
+        if (!lib3ds_chunk_write_end(&c,io)) {
+          return(LIB3DS_FALSE);
+        }
+      }
+      break;
+    default:
+      return(LIB3DS_FALSE);
+  }
+
+  if (!lib3ds_chunk_write_end(&c,io)) {
+    return(LIB3DS_FALSE);
+  }
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+
+\typedef Lib3dsNodeTypes
+  \ingroup node
+
+*/
+/*!
+
+\enum _Lib3dsNodeTypes
+  \ingroup node
+
+*/
+/*!
+
+\typedef Lib3dsBoolKey
+  \ingroup node
+  \sa _Lib3dsBoolKey
+
+*/
+/*!
+
+\typedef Lib3dsBoolTrack
+  \ingroup node
+  \sa _Lib3dsBoolTrack
+
+*/
+/*!
+
+\typedef Lib3dsLin1Key
+  \ingroup node
+  \sa _Lib3dsLin1Key
+
+*/
+/*!
+
+\typedef Lib3dsLin1Track
+  \ingroup node
+  \sa _Lib3dsLin1Track
+
+*/
+/*!
+
+\typedef Lib3dsLin3Key
+  \ingroup node
+  \sa _Lib3dsLin3Key
+
+*/
+/*!
+
+\typedef Lib3dsLin3Track
+  \ingroup node
+  \sa _Lib3dsLin3Track
+
+*/
+/*!
+
+\typedef Lib3dsQuatKey
+  \ingroup node
+  \sa _Lib3dsQuatKey
+
+*/
+/*!
+
+\typedef Lib3dsQuatTrack
+  \ingroup node
+  \sa _Lib3dsLin3Key
+
+*/
+/*!
+
+\typedef Lib3dsMorphKey
+  \ingroup node
+  \sa _Lib3dsMorphKey
+
+*/
+/*!
+
+\typedef Lib3dsMorphTrack
+  \ingroup node
+  \sa _Lib3dsMorphTrack
+
+*/
+
+
diff --git a/src/3dengfx/libs/lib3ds/node.h b/src/3dengfx/libs/lib3ds/node.h
new file mode 100644 (file)
index 0000000..7021a10
--- /dev/null
@@ -0,0 +1,188 @@
+/* -*- c -*- */
+#ifndef INCLUDED_LIB3DS_NODE_H
+#define INCLUDED_LIB3DS_NODE_H
+/*
+ * The 3D Studio File Format Library
+ * Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
+ * All rights reserved.
+ *
+ * This program is  free  software;  you can redistribute it and/or modify it
+ * under the terms of the  GNU Lesser General Public License  as published by 
+ * the  Free Software Foundation;  either version 2.1 of the License,  or (at 
+ * your option) any later version.
+ *
+ * This  program  is  distributed in  the  hope that it will  be useful,  but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public  
+ * License for more details.
+ *
+ * You should  have received  a copy of the GNU Lesser General Public License
+ * along with  this program;  if not, write to the  Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: node.h,v 1.9 2004/12/31 16:17:15 reed Exp $
+ */
+
+#ifndef INCLUDED_LIB3DS_TRACKS_H
+#include <lib3ds/tracks.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*!
+ * Scene graph ambient color node data
+ * \ingroup node
+ */
+typedef struct _Lib3dsAmbientData {
+    Lib3dsRgb col;
+    Lib3dsLin3Track col_track;
+} Lib3dsAmbientData;
+
+/*!
+ * Scene graph object instance node data
+ * \ingroup node
+ */
+typedef struct _Lib3dsObjectData {
+    Lib3dsVector pivot;
+    char instance[64];
+    Lib3dsVector bbox_min;
+    Lib3dsVector bbox_max;
+    Lib3dsVector pos;
+    Lib3dsLin3Track pos_track;
+    Lib3dsQuat rot;
+    Lib3dsQuatTrack rot_track;
+    Lib3dsVector scl;
+    Lib3dsLin3Track scl_track;
+    Lib3dsFloat morph_smooth;
+    char morph[64];
+    Lib3dsMorphTrack morph_track;
+    Lib3dsBool hide;
+    Lib3dsBoolTrack hide_track;
+} Lib3dsObjectData;
+
+/*!
+ * Scene graph camera node data
+ * \ingroup node
+ */
+typedef struct _Lib3dsCameraData {
+    Lib3dsVector pos;
+    Lib3dsLin3Track pos_track;
+    Lib3dsFloat fov;
+    Lib3dsLin1Track fov_track;
+    Lib3dsFloat roll;
+    Lib3dsLin1Track roll_track;
+} Lib3dsCameraData;
+
+/*!
+ * Scene graph camera target node data
+ * \ingroup node
+ */
+typedef struct _Lib3dsTargetData {
+    Lib3dsVector pos;
+    Lib3dsLin3Track pos_track;
+} Lib3dsTargetData;
+
+/*!
+ * Scene graph light node data
+ * \ingroup node
+ */
+typedef struct _Lib3dsLightData {
+    Lib3dsVector pos;
+    Lib3dsLin3Track pos_track;
+    Lib3dsRgb col;
+    Lib3dsLin3Track col_track;
+    Lib3dsFloat hotspot;
+    Lib3dsLin1Track hotspot_track;
+    Lib3dsFloat falloff;
+    Lib3dsLin1Track falloff_track;
+    Lib3dsFloat roll;
+    Lib3dsLin1Track roll_track;
+} Lib3dsLightData;
+
+/*!
+ * Scene graph spotlight target node data
+ * \ingroup node
+ */
+typedef struct _Lib3dsSpotData {
+    Lib3dsVector pos;
+    Lib3dsLin3Track pos_track;
+} Lib3dsSpotData;
+
+/*!
+ * Scene graph node data union
+ * \ingroup node
+ */
+typedef union _Lib3dsNodeData {
+    Lib3dsAmbientData ambient;
+    Lib3dsObjectData object;
+    Lib3dsCameraData camera;
+    Lib3dsTargetData target;
+    Lib3dsLightData light;
+    Lib3dsSpotData spot;
+} Lib3dsNodeData;
+
+/*!
+ * \ingroup node
+ */
+#define LIB3DS_NO_PARENT 65535
+
+/*!
+ * Scene graph node
+ * \ingroup node
+ */
+struct _Lib3dsNode {
+    Lib3dsUserData user;
+    Lib3dsNode *next;\
+    Lib3dsNode *childs;\
+    Lib3dsNode *parent;\
+    Lib3dsNodeTypes type;\
+    Lib3dsWord node_id;\
+    char name[64];\
+    Lib3dsWord flags1;\
+    Lib3dsWord flags2;\
+    Lib3dsWord parent_id;
+    Lib3dsMatrix matrix;
+    Lib3dsNodeData data;
+};
+
+/*!
+ * Node flags
+ * \ingroup node
+ */
+typedef enum {
+  LIB3DS_HIDDEN = 0x800
+} Lib3dsNodeFlags1;
+
+/*!
+ * Node flags
+ * \ingroup node
+ */
+typedef enum {
+  LIB3DS_SHOW_PATH = 0x1,
+  LIB3DS_SMOOTHING = 0x2,
+  LIB3DS_MOTION_BLUR = 0x10,
+  LIB3DS_MORPH_MATERIALS = 0x40
+} Lib3dsNodeFlags2;
+
+extern LIB3DSAPI Lib3dsNode* lib3ds_node_new_ambient();
+extern LIB3DSAPI Lib3dsNode* lib3ds_node_new_object();
+extern LIB3DSAPI Lib3dsNode* lib3ds_node_new_camera();
+extern LIB3DSAPI Lib3dsNode* lib3ds_node_new_target();
+extern LIB3DSAPI Lib3dsNode* lib3ds_node_new_light();
+extern LIB3DSAPI Lib3dsNode* lib3ds_node_new_spot();
+extern LIB3DSAPI void lib3ds_node_free(Lib3dsNode *node);
+extern LIB3DSAPI void lib3ds_node_eval(Lib3dsNode *node, Lib3dsFloat t);
+extern LIB3DSAPI Lib3dsNode* lib3ds_node_by_name(Lib3dsNode *node, const char* name,
+  Lib3dsNodeTypes type);
+extern LIB3DSAPI Lib3dsNode* lib3ds_node_by_id(Lib3dsNode *node, Lib3dsWord node_id);
+extern LIB3DSAPI void lib3ds_node_dump(Lib3dsNode *node, Lib3dsIntd level);
+extern LIB3DSAPI Lib3dsBool lib3ds_node_read(Lib3dsNode *node, Lib3dsFile *file, Lib3dsIo *io);
+extern LIB3DSAPI Lib3dsBool lib3ds_node_write(Lib3dsNode *node, Lib3dsFile *file, Lib3dsIo *io);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/src/3dengfx/libs/lib3ds/quat.c b/src/3dengfx/libs/lib3ds/quat.c
new file mode 100644 (file)
index 0000000..2c81dfe
--- /dev/null
@@ -0,0 +1,419 @@
+/*
+ * The 3D Studio File Format Library
+ * Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
+ * All rights reserved.
+ *
+ * This program is  free  software;  you can redistribute it and/or modify it
+ * under the terms of the  GNU Lesser General Public License  as published by 
+ * the  Free Software Foundation;  either version 2.1 of the License,  or (at 
+ * your option) any later version.
+ *
+ * This  program  is  distributed in  the  hope that it will  be useful,  but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public  
+ * License for more details.
+ *
+ * You should  have received  a copy of the GNU Lesser General Public License
+ * along with  this program;  if not, write to the  Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: quat.c,v 1.6 2004/11/20 08:31:31 efalk Exp $
+ */
+#define LIB3DS_EXPORT
+#include <lib3ds/quat.h>
+#include <math.h>
+
+
+/*!
+ * \defgroup quat Quaternion Mathematics
+ *
+ * \author J.E. Hoffmann <je-h@gmx.net>
+ */
+/*!
+ * \typedef Lib3dsQuat
+ *   \ingroup quat
+ */
+
+
+/*!
+ * Clear a quaternion.
+ * \ingroup quat
+ */
+void
+lib3ds_quat_zero(Lib3dsQuat c)
+{
+  c[0]=c[1]=c[2]=c[3]=0.0f;
+}
+
+
+/*!
+ * Set a quaternion to Identity
+ * \ingroup quat
+ */
+void
+lib3ds_quat_identity(Lib3dsQuat c)
+{
+  c[0]=c[1]=c[2]=0.0f;
+  c[3]=1.0f;
+}
+
+
+/*!
+ * Copy a quaternion.
+ * \ingroup quat
+ */
+void 
+lib3ds_quat_copy(Lib3dsQuat dest, Lib3dsQuat src)
+{
+  int i;
+  for (i=0; i<4; ++i) {
+    dest[i]=src[i];
+  }
+}
+
+
+/*!
+ * Compute a quaternion from axis and angle.
+ *
+ * \param c Computed quaternion
+ * \param axis Rotation axis
+ * \param angle Angle of rotation, radians.
+ *
+ * \ingroup quat
+ */
+void
+lib3ds_quat_axis_angle(Lib3dsQuat c, Lib3dsVector axis, Lib3dsFloat angle)
+{
+  Lib3dsDouble omega,s;
+  Lib3dsDouble l;
+
+  l=sqrt(axis[0]*axis[0] + axis[1]*axis[1] + axis[2]*axis[2]);
+  if (l<LIB3DS_EPSILON) {
+    c[0]=c[1]=c[2]=0.0f;
+    c[3]=1.0f;
+  }
+  else {
+    omega=-0.5*angle;
+    s=sin(omega)/l;
+    c[0]=(Lib3dsFloat)s*axis[0];
+    c[1]=(Lib3dsFloat)s*axis[1];
+    c[2]=(Lib3dsFloat)s*axis[2];
+    c[3]=(Lib3dsFloat)cos(omega);
+  }
+}
+
+
+/*!
+ * Negate a quaternion
+ *
+ * \ingroup quat
+ */
+void
+lib3ds_quat_neg(Lib3dsQuat c)
+{
+  int i;
+  for (i=0; i<4; ++i) {
+    c[i]=-c[i];
+  }
+}
+
+
+/*!
+ * Compute the absolute value of a quaternion
+ *
+ * \ingroup quat
+ */
+void
+lib3ds_quat_abs(Lib3dsQuat c)
+{
+  int i;
+  for (i=0; i<4; ++i) {
+    c[i]=(Lib3dsFloat)fabs(c[i]);
+  }
+}
+
+
+/*!
+ * Compute the conjugate of a quaternion
+ *
+ * \ingroup quat
+ */
+void
+lib3ds_quat_cnj(Lib3dsQuat c)
+{
+  int i;
+  for (i=0; i<3; ++i) {
+    c[i]=-c[i];
+  }
+}
+
+
+/*!
+ * Multiply two quaternions.
+ *
+ * \param c Result
+ * \param a,b Inputs
+ * \ingroup quat
+ */
+void
+lib3ds_quat_mul(Lib3dsQuat c, Lib3dsQuat a, Lib3dsQuat b)
+{
+  c[0]=a[3]*b[0] + a[0]*b[3] + a[1]*b[2] - a[2]*b[1];
+  c[1]=a[3]*b[1] + a[1]*b[3] + a[2]*b[0] - a[0]*b[2];
+  c[2]=a[3]*b[2] + a[2]*b[3] + a[0]*b[1] - a[1]*b[0];
+  c[3]=a[3]*b[3] - a[0]*b[0] - a[1]*b[1] - a[2]*b[2];
+}
+
+
+/*!
+ * Multiply a quaternion by a scalar.
+ *
+ * \ingroup quat
+ */
+void
+lib3ds_quat_scalar(Lib3dsQuat c, Lib3dsFloat k)
+{
+  int i;
+  for (i=0; i<4; ++i) {
+    c[i]*=k;
+  }
+}
+
+
+/*!
+ * Normalize a quaternion.
+ *
+ * \ingroup quat
+ */
+void
+lib3ds_quat_normalize(Lib3dsQuat c)
+{
+  Lib3dsDouble l,m;
+
+  l=sqrt(c[0]*c[0] + c[1]*c[1] + c[2]*c[2] + c[3]*c[3]);
+  if (fabs(l)<LIB3DS_EPSILON) {
+    c[0]=c[1]=c[2]=0.0f;
+    c[3]=1.0f; 
+  }
+  else {  
+    int i;
+    m=1.0f/l;
+    for (i=0; i<4; ++i) {
+      c[i]=(Lib3dsFloat)(c[i]*m);
+    }
+  }
+}
+
+
+/*!
+ * Compute the inverse of a quaternion.
+ *
+ * \ingroup quat
+ */
+void
+lib3ds_quat_inv(Lib3dsQuat c)
+{
+  Lib3dsDouble l,m;
+
+  l=sqrt(c[0]*c[0] + c[1]*c[1] + c[2]*c[2] + c[3]*c[3]);
+  if (fabs(l)<LIB3DS_EPSILON) {
+    c[0]=c[1]=c[2]=0.0f;
+    c[3]=1.0f; 
+  }
+  else {  
+    m=1.0f/l;
+    c[0]=(Lib3dsFloat)(-c[0]*m);
+    c[1]=(Lib3dsFloat)(-c[1]*m);
+    c[2]=(Lib3dsFloat)(-c[2]*m);
+    c[3]=(Lib3dsFloat)(c[3]*m);
+  }
+}
+
+
+/*!
+ * Compute the dot-product of a quaternion.
+ *
+ * \ingroup quat
+ */
+Lib3dsFloat
+lib3ds_quat_dot(Lib3dsQuat a, Lib3dsQuat b)
+{
+  return(a[0]*b[0] + a[1]*b[1] + a[2]*b[2] + a[3]*b[3]);
+}
+
+
+/*!
+ * \ingroup quat
+ */
+Lib3dsFloat
+lib3ds_quat_squared(Lib3dsQuat c)
+{
+  return(c[0]*c[0] + c[1]*c[1] + c[2]*c[2] + c[3]*c[3]);
+}
+
+
+/*!
+ * \ingroup quat
+ */
+Lib3dsFloat
+lib3ds_quat_length(Lib3dsQuat c)
+{
+  return((Lib3dsFloat)sqrt(c[0]*c[0] + c[1]*c[1] + c[2]*c[2] + c[3]*c[3]));
+}
+
+
+/*!
+ * \ingroup quat
+ */
+void
+lib3ds_quat_ln(Lib3dsQuat c)
+{
+  Lib3dsDouble om,s,t;
+
+  s=sqrt(c[0]*c[0] + c[1]*c[1] + c[2]*c[2]);
+  om=atan2(s,c[3]);
+  if (fabs(s)<LIB3DS_EPSILON) {
+    t=0.0f;
+  }
+  else {
+    t=om/s;
+  }
+  {
+    int i;
+    for (i=0; i<3; ++i) {
+      c[i]=(Lib3dsFloat)(c[i]*t);
+    }
+    c[3]=0.0f;
+  }
+}
+
+
+/*!
+ * \ingroup quat
+ */
+void
+lib3ds_quat_ln_dif(Lib3dsQuat c, Lib3dsQuat a, Lib3dsQuat b)
+{
+  Lib3dsQuat invp;
+
+  lib3ds_quat_copy(invp, a);
+  lib3ds_quat_inv(invp);
+  lib3ds_quat_mul(c, invp, b);
+  lib3ds_quat_ln(c);
+}
+
+
+/*!
+ * \ingroup quat
+ */
+void
+lib3ds_quat_exp(Lib3dsQuat c)
+{
+  Lib3dsDouble om,sinom;
+
+  om=sqrt(c[0]*c[0] + c[1]*c[1] + c[2]*c[2]);
+  if (fabs(om)<LIB3DS_EPSILON) {
+    sinom=1.0f;
+  }
+  else {
+    sinom=sin(om)/om;
+  }
+  {
+    int i;
+    for (i=0; i<3; ++i) {
+      c[i]=(Lib3dsFloat)(c[i]*sinom);
+    }
+    c[3]=(Lib3dsFloat)cos(om);
+  }
+}
+
+
+/*!
+ * \ingroup quat
+ */
+void
+lib3ds_quat_slerp(Lib3dsQuat c, Lib3dsQuat a, Lib3dsQuat b, Lib3dsFloat t)
+{
+  Lib3dsDouble l;
+  Lib3dsDouble om,sinom;
+  Lib3dsDouble sp,sq;
+  Lib3dsQuat q;
+
+  l=a[0]*b[0] + a[1]*b[1] + a[2]*b[2] + a[3]*b[3];
+  if ((1.0+l)>LIB3DS_EPSILON) {
+    if (fabs(l)>1.0f) l/=fabs(l);
+    om=acos(l);
+    sinom=sin(om);
+    if (fabs(sinom)>LIB3DS_EPSILON) {
+      sp=sin((1.0f-t)*om)/sinom;
+      sq=sin(t*om)/sinom;
+    }
+    else {
+      sp=1.0f-t;
+      sq=t;
+    }
+    c[0]=(Lib3dsFloat)(sp*a[0] + sq*b[0]);
+    c[1]=(Lib3dsFloat)(sp*a[1] + sq*b[1]);
+    c[2]=(Lib3dsFloat)(sp*a[2] + sq*b[2]);
+    c[3]=(Lib3dsFloat)(sp*a[3] + sq*b[3]);
+  }
+  else {
+    q[0]=-a[1];
+    q[1]=a[0];
+    q[2]=-a[3];
+    q[3]=a[2];
+    sp=sin((1.0-t)*LIB3DS_HALFPI);
+    sq=sin(t*LIB3DS_HALFPI);
+    c[0]=(Lib3dsFloat)(sp*a[0] + sq*q[0]);
+    c[1]=(Lib3dsFloat)(sp*a[1] + sq*q[1]);
+    c[2]=(Lib3dsFloat)(sp*a[2] + sq*q[2]);
+    c[3]=(Lib3dsFloat)(sp*a[3] + sq*q[3]);
+  }
+}
+
+
+/*!
+ * \ingroup quat
+ */
+void
+lib3ds_quat_squad(Lib3dsQuat c, Lib3dsQuat a, Lib3dsQuat p, Lib3dsQuat q,
+  Lib3dsQuat b, Lib3dsFloat t)
+{
+  Lib3dsQuat ab;
+  Lib3dsQuat pq;
+
+  lib3ds_quat_slerp(ab,a,b,t);
+  lib3ds_quat_slerp(pq,p,q,t);
+  lib3ds_quat_slerp(c,ab,pq,2*t*(1-t));
+}
+
+
+/*!
+ * \ingroup quat
+ */
+void
+lib3ds_quat_tangent(Lib3dsQuat c, Lib3dsQuat p, Lib3dsQuat q, Lib3dsQuat n)
+{
+  Lib3dsQuat dn,dp,x;
+  int i;
+
+  lib3ds_quat_ln_dif(dn, q, n);
+  lib3ds_quat_ln_dif(dp, q, p);
+
+  for (i=0; i<4; i++) {
+    x[i]=-1.0f/4.0f*(dn[i]+dp[i]);
+  }
+  lib3ds_quat_exp(x);
+  lib3ds_quat_mul(c,q,x);
+}
+
+
+/*!
+ * \ingroup quat
+ */
+void
+lib3ds_quat_dump(Lib3dsQuat q)
+{
+  printf("%f %f %f %f\n", q[0], q[1], q[2], q[3]);
+}
+
diff --git a/src/3dengfx/libs/lib3ds/quat.h b/src/3dengfx/libs/lib3ds/quat.h
new file mode 100644 (file)
index 0000000..796a83d
--- /dev/null
@@ -0,0 +1,61 @@
+/* -*- c -*- */
+#ifndef INCLUDED_LIB3DS_QUAT_H
+#define INCLUDED_LIB3DS_QUAT_H
+/*
+ * The 3D Studio File Format Library
+ * Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
+ * All rights reserved.
+ *
+ * This program is  free  software;  you can redistribute it and/or modify it
+ * under the terms of the  GNU Lesser General Public License  as published by 
+ * the  Free Software Foundation;  either version 2.1 of the License,  or (at 
+ * your option) any later version.
+ *
+ * This  program  is  distributed in  the  hope that it will  be useful,  but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public  
+ * License for more details.
+ *
+ * You should  have received  a copy of the GNU Lesser General Public License
+ * along with  this program;  if not, write to the  Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: quat.h,v 1.6 2004/12/31 16:17:15 reed Exp $
+ */
+
+#ifndef INCLUDED_LIB3DS_TYPES_H
+#include <lib3ds/types.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern LIB3DSAPI void lib3ds_quat_zero(Lib3dsQuat c);
+extern LIB3DSAPI void lib3ds_quat_identity(Lib3dsQuat c);
+extern LIB3DSAPI void lib3ds_quat_copy(Lib3dsQuat dest, Lib3dsQuat src);
+extern LIB3DSAPI void lib3ds_quat_axis_angle(Lib3dsQuat c, Lib3dsVector axis, Lib3dsFloat angle);
+extern LIB3DSAPI void lib3ds_quat_neg(Lib3dsQuat c);
+extern LIB3DSAPI void lib3ds_quat_abs(Lib3dsQuat c);
+extern LIB3DSAPI void lib3ds_quat_cnj(Lib3dsQuat c);
+extern LIB3DSAPI void lib3ds_quat_mul(Lib3dsQuat c, Lib3dsQuat a, Lib3dsQuat b);
+extern LIB3DSAPI void lib3ds_quat_scalar(Lib3dsQuat c, Lib3dsFloat k);
+extern LIB3DSAPI void lib3ds_quat_normalize(Lib3dsQuat c);
+extern LIB3DSAPI void lib3ds_quat_inv(Lib3dsQuat c);
+extern LIB3DSAPI Lib3dsFloat lib3ds_quat_dot(Lib3dsQuat a, Lib3dsQuat b);
+extern LIB3DSAPI Lib3dsFloat lib3ds_quat_squared(Lib3dsQuat c);
+extern LIB3DSAPI Lib3dsFloat lib3ds_quat_length(Lib3dsQuat c);
+extern LIB3DSAPI void lib3ds_quat_ln(Lib3dsQuat c);
+extern LIB3DSAPI void lib3ds_quat_ln_dif(Lib3dsQuat c, Lib3dsQuat a, Lib3dsQuat b);
+extern LIB3DSAPI void lib3ds_quat_exp(Lib3dsQuat c);
+extern LIB3DSAPI void lib3ds_quat_slerp(Lib3dsQuat c, Lib3dsQuat a, Lib3dsQuat b, Lib3dsFloat t);
+extern LIB3DSAPI void lib3ds_quat_squad(Lib3dsQuat c, Lib3dsQuat a, Lib3dsQuat p, Lib3dsQuat q,
+  Lib3dsQuat b, Lib3dsFloat t);
+extern LIB3DSAPI void lib3ds_quat_tangent(Lib3dsQuat c, Lib3dsQuat p, Lib3dsQuat q, Lib3dsQuat n);
+extern LIB3DSAPI void lib3ds_quat_dump(Lib3dsQuat q);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/src/3dengfx/libs/lib3ds/shadow.c b/src/3dengfx/libs/lib3ds/shadow.c
new file mode 100644 (file)
index 0000000..a38f13c
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ * The 3D Studio File Format Library
+ * Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
+ * All rights reserved.
+ *
+ * This program is  free  software;  you can redistribute it and/or modify it
+ * under the terms of the  GNU Lesser General Public License  as published by 
+ * the  Free Software Foundation;  either version 2.1 of the License,  or (at 
+ * your option) any later version.
+ *
+ * This  program  is  distributed in  the  hope that it will  be useful,  but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public  
+ * License for more details.
+ *
+ * You should  have received  a copy of the GNU Lesser General Public License
+ * along with  this program;  if not, write to the  Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: shadow.c,v 1.8 2001/07/07 19:05:30 jeh Exp $
+ */
+#define LIB3DS_EXPORT
+#include <lib3ds/shadow.h>
+#include <lib3ds/chunk.h>
+#include <lib3ds/io.h>
+#include <math.h>
+
+
+/*!
+ * \defgroup shadow Shadow Map Settings
+ *
+ * \author J.E. Hoffmann <je-h@gmx.net>
+ */
+
+
+/*!
+ * \ingroup shadow 
+ */
+Lib3dsBool
+lib3ds_shadow_read(Lib3dsShadow *shadow, Lib3dsIo *io)
+{
+  Lib3dsChunk c;
+
+  if (!lib3ds_chunk_read(&c, io)) {
+    return(LIB3DS_FALSE);
+  }
+  
+  switch (c.chunk) {
+    case LIB3DS_SHADOW_MAP_SIZE:
+      {
+        shadow->map_size=lib3ds_io_read_intw(io);
+      }
+      break;
+    case LIB3DS_LO_SHADOW_BIAS:
+      {
+          shadow->lo_bias=lib3ds_io_read_float(io);
+      }
+      break;
+    case LIB3DS_HI_SHADOW_BIAS:
+      {
+        shadow->hi_bias=lib3ds_io_read_float(io);
+      }
+      break;
+    case LIB3DS_SHADOW_SAMPLES:
+      {
+        shadow->samples=lib3ds_io_read_intw(io);
+      }
+      break;
+    case LIB3DS_SHADOW_RANGE:
+      {
+        shadow->range=lib3ds_io_read_intd(io);
+      }
+      break;
+    case LIB3DS_SHADOW_FILTER:
+      {
+        shadow->filter=lib3ds_io_read_float(io);
+      }
+      break;
+    case LIB3DS_RAY_BIAS:
+      {
+        shadow->ray_bias=lib3ds_io_read_float(io);
+      }
+      break;
+  }
+  
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+ * \ingroup shadow 
+ */
+Lib3dsBool
+lib3ds_shadow_write(Lib3dsShadow *shadow, Lib3dsIo *io)
+{
+  if (fabs(shadow->lo_bias)>LIB3DS_EPSILON) { /*---- LIB3DS_LO_SHADOW_BIAS ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_LO_SHADOW_BIAS;
+    c.size=10;
+    lib3ds_chunk_write(&c,io);
+    lib3ds_io_write_float(io, shadow->lo_bias);
+  }
+
+  if (fabs(shadow->hi_bias)>LIB3DS_EPSILON) { /*---- LIB3DS_HI_SHADOW_BIAS ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_HI_SHADOW_BIAS;
+    c.size=10;
+    lib3ds_chunk_write(&c,io);
+    lib3ds_io_write_float(io, shadow->hi_bias);
+  }
+
+  if (shadow->map_size) { /*---- LIB3DS_SHADOW_MAP_SIZE ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_SHADOW_MAP_SIZE;
+    c.size=8;
+    lib3ds_chunk_write(&c,io);
+    lib3ds_io_write_intw(io, shadow->map_size);
+  }
+  
+  if (shadow->samples) { /*---- LIB3DS_SHADOW_SAMPLES ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_SHADOW_SAMPLES;
+    c.size=8;
+    lib3ds_chunk_write(&c,io);
+    lib3ds_io_write_intw(io, shadow->samples);
+  }
+
+  if (shadow->range) { /*---- LIB3DS_SHADOW_RANGE ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_SHADOW_RANGE;
+    c.size=10;
+    lib3ds_chunk_write(&c,io);
+    lib3ds_io_write_intd(io, shadow->range);
+  }
+
+  if (fabs(shadow->filter)>LIB3DS_EPSILON) { /*---- LIB3DS_SHADOW_FILTER ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_SHADOW_FILTER;
+    c.size=10;
+    lib3ds_chunk_write(&c,io);
+    lib3ds_io_write_float(io, shadow->filter);
+  }
+  if (fabs(shadow->ray_bias)>LIB3DS_EPSILON) { /*---- LIB3DS_RAY_BIAS ----*/
+    Lib3dsChunk c;
+    c.chunk=LIB3DS_RAY_BIAS;
+    c.size=10;
+    lib3ds_chunk_write(&c,io);
+    lib3ds_io_write_float(io, shadow->ray_bias);
+  }
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+
+\typedef Lib3dsShadow
+  \ingroup shadow
+  \sa _Lib3dsShadow
+
+*/
diff --git a/src/3dengfx/libs/lib3ds/shadow.h b/src/3dengfx/libs/lib3ds/shadow.h
new file mode 100644 (file)
index 0000000..ecc0af1
--- /dev/null
@@ -0,0 +1,59 @@
+/* -*- c -*- */
+#ifndef INCLUDED_LIB3DS_SHADOW_H
+#define INCLUDED_LIB3DS_SHADOW_H
+/*
+ * The 3D Studio File Format Library
+ * Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
+ * All rights reserved.
+ *
+ * This program is  free  software;  you can redistribute it and/or modify it
+ * under the terms of the  GNU Lesser General Public License  as published by 
+ * the  Free Software Foundation;  either version 2.1 of the License,  or (at 
+ * your option) any later version.
+ *
+ * This  program  is  distributed in  the  hope that it will  be useful,  but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public  
+ * License for more details.
+ *
+ * You should  have received  a copy of the GNU Lesser General Public License
+ * along with  this program;  if not, write to the  Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: shadow.h,v 1.9 2004/12/31 16:17:15 reed Exp $
+ */
+
+#ifndef INCLUDED_LIB3DS_TYPES_H
+#include <lib3ds/types.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*!
+ * Shadow map settings
+ * \ingroup shadow
+ */
+struct _Lib3dsShadow {
+    Lib3dsIntw map_size;
+    Lib3dsFloat lo_bias;
+    Lib3dsFloat hi_bias;
+    Lib3dsIntw samples;
+    Lib3dsIntd range;
+    Lib3dsFloat filter;
+    Lib3dsFloat ray_bias;
+};
+
+extern LIB3DSAPI Lib3dsBool lib3ds_shadow_read(Lib3dsShadow *shadow, Lib3dsIo *io);
+extern LIB3DSAPI Lib3dsBool lib3ds_shadow_write(Lib3dsShadow *shadow, Lib3dsIo *io);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+
+
+
+
diff --git a/src/3dengfx/libs/lib3ds/tcb.c b/src/3dengfx/libs/lib3ds/tcb.c
new file mode 100644 (file)
index 0000000..6427f97
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * The 3D Studio File Format Library
+ * Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
+ * All rights reserved.
+ *
+ * This program is  free  software;  you can redistribute it and/or modify it
+ * under the terms of the  GNU Lesser General Public License  as published by 
+ * the  Free Software Foundation;  either version 2.1 of the License,  or (at 
+ * your option) any later version.
+ *
+ * This  program  is  distributed in  the  hope that it will  be useful,  but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public  
+ * License for more details.
+ *
+ * You should  have received  a copy of the GNU Lesser General Public License
+ * along with  this program;  if not, write to the  Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: tcb.c,v 1.9 2001/07/07 19:05:30 jeh Exp $
+ */
+#define LIB3DS_EXPORT
+#include <lib3ds/tcb.h>
+#include <lib3ds/io.h>
+#include <math.h>
+
+
+/*!
+ * \defgroup tcb Tension/Continuity/Bias Splines
+ *
+ * \author J.E. Hoffmann <je-h@gmx.net>
+ */
+
+
+/*!
+ * \ingroup tcb 
+ */
+void
+lib3ds_tcb(Lib3dsTcb *p, Lib3dsTcb *pc, Lib3dsTcb *c, Lib3dsTcb *nc, Lib3dsTcb *n,
+  Lib3dsFloat *ksm, Lib3dsFloat *ksp, Lib3dsFloat *kdm, Lib3dsFloat *kdp)
+{
+  Lib3dsFloat tm,cm,cp,bm,bp,tmcm,tmcp,cc;
+  Lib3dsFloat dt,fp,fn;
+
+  if (!pc) {
+    pc=c;
+  }
+  if (!nc) {
+    nc=c;
+  }
+  
+  fp=fn=1.0f;
+  if (p&&n) {
+    dt=0.5f*(Lib3dsFloat)(pc->frame-p->frame+n->frame-nc->frame);
+    fp=((Lib3dsFloat)(pc->frame-p->frame))/dt;
+    fn=((Lib3dsFloat)(n->frame-nc->frame))/dt;
+    cc=(Lib3dsFloat)fabs(c->cont);
+    fp=fp+cc-cc*fp;
+    fn=fn+cc-cc*fn;
+  }
+
+  cm=1.0f-c->cont;
+  tm=0.5f*(1.0f-c->tens);
+  cp=2.0f-cm;
+  bm=1.0f-c->bias;
+  bp=2.0f-bm;      
+  tmcm=tm*cm;
+  tmcp=tm*cp;
+  *ksm=tmcm*bp*fp;
+  *ksp=tmcp*bm*fp;
+  *kdm=tmcp*bp*fn;
+  *kdp=tmcm*bm*fn;
+}
+
+
+/*!
+ * \ingroup tcb 
+ */
+Lib3dsBool
+lib3ds_tcb_read(Lib3dsTcb *tcb, Lib3dsIo *io)
+{
+  Lib3dsWord flags;
+  
+  tcb->frame=lib3ds_io_read_intd(io);
+  tcb->flags=flags=lib3ds_io_read_word(io);
+  if (flags&LIB3DS_USE_TENSION) {
+    tcb->tens=lib3ds_io_read_float(io);
+  }
+  if (flags&LIB3DS_USE_CONTINUITY) {
+    tcb->cont=lib3ds_io_read_float(io);
+  }
+  if (flags&LIB3DS_USE_BIAS) {
+    tcb->bias=lib3ds_io_read_float(io);
+  }
+  if (flags&LIB3DS_USE_EASE_TO) {
+    tcb->ease_to=lib3ds_io_read_float(io);
+  }
+  if (flags&LIB3DS_USE_EASE_FROM) {
+    tcb->ease_from=lib3ds_io_read_float(io);
+  }
+  if (lib3ds_io_error(io)) {
+    return(LIB3DS_FALSE);
+  }
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+ * \ingroup tcb 
+ */
+Lib3dsBool
+lib3ds_tcb_write(Lib3dsTcb *tcb, Lib3dsIo *io)
+{
+  lib3ds_io_write_intd(io, tcb->frame);
+  lib3ds_io_write_word(io, tcb->flags);
+  if (tcb->flags&LIB3DS_USE_TENSION) {
+    lib3ds_io_write_float(io, tcb->tens);
+  }
+  if (tcb->flags&LIB3DS_USE_CONTINUITY) {
+    lib3ds_io_write_float(io, tcb->cont);
+  }
+  if (tcb->flags&LIB3DS_USE_BIAS) {
+    lib3ds_io_write_float(io, tcb->bias);
+  }
+  if (tcb->flags&LIB3DS_USE_EASE_TO) {
+    lib3ds_io_write_float(io, tcb->ease_to);
+  }
+  if (tcb->flags&LIB3DS_USE_EASE_FROM) {
+    lib3ds_io_write_float(io, tcb->ease_from);
+  }
+  if (lib3ds_io_error(io)) {
+    return(LIB3DS_FALSE);
+  }
+  return(LIB3DS_TRUE);
+}
+
+
+
+
diff --git a/src/3dengfx/libs/lib3ds/tcb.h b/src/3dengfx/libs/lib3ds/tcb.h
new file mode 100644 (file)
index 0000000..f8198f7
--- /dev/null
@@ -0,0 +1,62 @@
+/* -*- c -*- */
+#ifndef INCLUDED_LIB3DS_TCB_H
+#define INCLUDED_LIB3DS_TCB_H
+/*
+ * The 3D Studio File Format Library
+ * Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
+ * All rights reserved.
+ *
+ * This program is  free  software;  you can redistribute it and/or modify it
+ * under the terms of the  GNU Lesser General Public License  as published by 
+ * the  Free Software Foundation;  either version 2.1 of the License,  or (at 
+ * your option) any later version.
+ *
+ * This  program  is  distributed in  the  hope that it will  be useful,  but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public  
+ * License for more details.
+ *
+ * You should  have received  a copy of the GNU Lesser General Public License
+ * along with  this program;  if not, write to the  Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: tcb.h,v 1.9 2004/12/31 16:17:15 reed Exp $
+ */
+
+#ifndef INCLUDED_LIB3DS_TYPES_H
+#include <lib3ds/types.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum _Lib3dsTcbFlags{
+  LIB3DS_USE_TENSION    =0x0001,
+  LIB3DS_USE_CONTINUITY =0x0002,
+  LIB3DS_USE_BIAS       =0x0004,
+  LIB3DS_USE_EASE_TO    =0x0008,
+  LIB3DS_USE_EASE_FROM  =0x0010
+} Lib3dsTcbFlags;
+
+typedef struct _Lib3dsTcb {
+    Lib3dsIntd frame;
+    Lib3dsWord flags;
+    Lib3dsFloat tens;
+    Lib3dsFloat cont;
+    Lib3dsFloat bias;
+    Lib3dsFloat ease_to;
+    Lib3dsFloat ease_from;
+} Lib3dsTcb;
+
+extern LIB3DSAPI void lib3ds_tcb(Lib3dsTcb *p, Lib3dsTcb *pc, Lib3dsTcb *c,
+  Lib3dsTcb *nc, Lib3dsTcb *n, Lib3dsFloat *ksm, Lib3dsFloat *ksp,
+  Lib3dsFloat *kdm, Lib3dsFloat *kdp);
+extern LIB3DSAPI Lib3dsBool lib3ds_tcb_read(Lib3dsTcb *tcb, Lib3dsIo *io);
+extern LIB3DSAPI Lib3dsBool lib3ds_tcb_write(Lib3dsTcb *tcb, Lib3dsIo *io);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/src/3dengfx/libs/lib3ds/tracks.c b/src/3dengfx/libs/lib3ds/tracks.c
new file mode 100644 (file)
index 0000000..c33089d
--- /dev/null
@@ -0,0 +1,1548 @@
+/*
+ * The 3D Studio File Format Library
+ * Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
+ * All rights reserved.
+ *
+ * This program is  free  software;  you can redistribute it and/or modify it
+ * under the terms of the  GNU Lesser General Public License  as published by 
+ * the  Free Software Foundation;  either version 2.1 of the License,  or (at 
+ * your option) any later version.
+ *
+ * This  program  is  distributed in  the  hope that it will  be useful,  but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public  
+ * License for more details.
+ *
+ * You should  have received  a copy of the GNU Lesser General Public License
+ * along with  this program;  if not, write to the  Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: tracks.c,v 1.14 2004/11/20 09:00:38 efalk Exp $
+ */
+#define LIB3DS_EXPORT
+#include <lib3ds/tracks.h>
+#include <lib3ds/io.h>
+#include <lib3ds/chunk.h>
+#include <lib3ds/float.h>
+#include <lib3ds/vector.h>
+#include <lib3ds/quat.h>
+#include <lib3ds/node.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#ifdef WITH_DMALLOC
+#include <dmalloc.h>
+#endif
+
+
+/*!
+ * \defgroup tracks Keyframing Tracks
+ *
+ * \author J.E. Hoffmann <je-h@gmx.net>
+ */
+
+
+/*!
+ * \ingroup tracks 
+ */
+Lib3dsBoolKey*
+lib3ds_bool_key_new()
+{
+  Lib3dsBoolKey* k;
+  k=(Lib3dsBoolKey*)calloc(sizeof(Lib3dsBoolKey), 1);
+  return(k);
+}
+
+
+/*!
+ * \ingroup tracks 
+ */
+void
+lib3ds_bool_key_free(Lib3dsBoolKey *key)
+{
+  ASSERT(key);
+  free(key);
+}
+
+
+/*!
+ * \ingroup tracks 
+ */
+void
+lib3ds_bool_track_free_keys(Lib3dsBoolTrack *track)
+{
+  Lib3dsBoolKey *p,*q;
+
+  ASSERT(track);
+  for (p=track->keyL; p; p=q) {
+    q=p->next;
+    lib3ds_bool_key_free(p);
+  }
+}
+
+
+/*!
+ * \ingroup tracks 
+ */
+void
+lib3ds_bool_track_insert(Lib3dsBoolTrack *track, Lib3dsBoolKey *key)
+{
+  ASSERT(track);
+  ASSERT(key);
+  ASSERT(!key->next);
+
+  if (!track->keyL) {
+    track->keyL=key;
+    key->next=0;
+  }
+  else {
+    Lib3dsBoolKey *k,*p;
+
+    for (p=0,k=track->keyL; k!=0; p=k, k=k->next) {
+      if (k->tcb.frame>key->tcb.frame) {
+        break;
+      }
+    }
+    if (!p) {
+      key->next=track->keyL;
+      track->keyL=key;
+    }
+    else {
+      key->next=k;
+      p->next=key;
+    }
+    if (k && (key->tcb.frame==k->tcb.frame)) {
+      key->next=k->next;
+      lib3ds_bool_key_free(k);
+    }
+  }
+}
+
+
+/*!
+ * \ingroup tracks 
+ */
+void
+lib3ds_bool_track_remove(Lib3dsBoolTrack *track, Lib3dsIntd frame)
+{
+  Lib3dsBoolKey *k,*p;
+  
+  ASSERT(track);
+  if (!track->keyL) {
+    return;
+  }
+  for (p=0,k=track->keyL; k!=0; p=k, k=k->next) {
+    if (k->tcb.frame==frame) {
+      if (!p) {
+        track->keyL=track->keyL->next;
+      }
+      else {
+        p->next=k->next;
+      }
+      lib3ds_bool_key_free(k);
+      break;
+    }
+  }
+}
+
+
+/*!
+ * \ingroup tracks 
+ */
+void
+lib3ds_bool_track_eval(Lib3dsBoolTrack *track, Lib3dsBool *p, Lib3dsFloat t)
+{
+  Lib3dsBoolKey *k;
+  Lib3dsBool result;
+
+  ASSERT(p);
+  if (!track->keyL) {
+    *p=LIB3DS_FALSE;
+    return;
+  }
+  if (!track->keyL->next) {
+    *p = LIB3DS_TRUE;
+    return;
+  }
+
+  result=LIB3DS_FALSE;
+  k=track->keyL;
+  while ((t<(Lib3dsFloat)k->tcb.frame) && (t>=(Lib3dsFloat)k->next->tcb.frame)) {
+    if (result) {
+      result=LIB3DS_FALSE;
+    }
+    else {
+      result=LIB3DS_TRUE;
+    }
+    if (!k->next) {
+      if (track->flags&LIB3DS_REPEAT) {
+        t-=(Lib3dsFloat)k->tcb.frame;
+        k=track->keyL;
+      }
+      else {
+        break;
+      }
+    }
+    else {
+      k=k->next;
+    }
+  }
+  *p=result;
+}
+
+
+/*!
+ * \ingroup tracks 
+ */
+Lib3dsBool
+lib3ds_bool_track_read(Lib3dsBoolTrack *track, Lib3dsIo *io)
+{
+  int keys;
+  int i;
+  Lib3dsBoolKey *k;
+
+  track->flags=lib3ds_io_read_word(io);
+  lib3ds_io_read_dword(io);
+  lib3ds_io_read_dword(io);
+  keys=lib3ds_io_read_intd(io);
+
+  for (i=0; i<keys; ++i) {
+    k=lib3ds_bool_key_new();
+    if (!lib3ds_tcb_read(&k->tcb, io)) {
+      return(LIB3DS_FALSE);
+    }
+    lib3ds_bool_track_insert(track, k);
+  }
+  
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+ * \ingroup tracks 
+ */
+Lib3dsBool
+lib3ds_bool_track_write(Lib3dsBoolTrack *track, Lib3dsIo *io)
+{
+  Lib3dsBoolKey *k;
+  Lib3dsDword num=0;
+  for (k=track->keyL; k; k=k->next) {
+    ++num;
+  }
+  lib3ds_io_write_word(io, (Lib3dsWord)track->flags);
+  lib3ds_io_write_dword(io, 0);
+  lib3ds_io_write_dword(io, 0);
+  lib3ds_io_write_dword(io, num);
+
+  for (k=track->keyL; k; k=k->next) {
+    if (!lib3ds_tcb_write(&k->tcb,io)) {
+      return(LIB3DS_FALSE);
+    }
+  }
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+ * \ingroup tracks 
+ */
+Lib3dsLin1Key*
+lib3ds_lin1_key_new()
+{
+  Lib3dsLin1Key* k;
+  k=(Lib3dsLin1Key*)calloc(sizeof(Lib3dsLin1Key), 1);
+  return(k);
+}
+
+
+/*!
+ * \ingroup tracks 
+ */
+void
+lib3ds_lin1_key_free(Lib3dsLin1Key *key)
+{
+  ASSERT(key);
+  free(key);
+}
+
+
+/*!
+ * \ingroup tracks 
+ */
+void
+lib3ds_lin1_track_free_keys(Lib3dsLin1Track *track)
+{
+  Lib3dsLin1Key *p,*q;
+
+  ASSERT(track);
+  for (p=track->keyL; p; p=q) {
+    q=p->next;
+    lib3ds_lin1_key_free(p);
+  }
+}
+
+
+/*!
+ * \ingroup tracks 
+ */
+void
+lib3ds_lin1_key_setup(Lib3dsLin1Key *p, Lib3dsLin1Key *cp, Lib3dsLin1Key *c,
+  Lib3dsLin1Key *cn, Lib3dsLin1Key *n)
+{
+  Lib3dsFloat np,nn;
+  Lib3dsFloat ksm,ksp,kdm,kdp;
+  
+  ASSERT(c);
+  if (!cp) {
+    cp=c;
+  }
+  if (!cn) {
+    cn=c;
+  }
+  if (!p && !n) {
+    c->ds=0;
+    c->dd=0;
+    return;
+  }
+
+  if (n && p) {
+    lib3ds_tcb(&p->tcb, &cp->tcb, &c->tcb, &cn->tcb, &n->tcb, &ksm, &ksp, &kdm, &kdp);
+    np = c->value - p->value; 
+    nn = n->value - c->value; 
+
+    c->ds=ksm*np + ksp*nn;
+    c->dd=kdm*np + kdp*nn;
+  }
+  else {
+    if (p) {
+      np = c->value - p->value;
+      c->ds = np;
+      c->dd = np;
+    }
+    if (n) {
+      nn = n->value - c->value; 
+      c->ds = nn;
+      c->dd = nn;
+    }
+  }
+}
+
+
+/*!
+ * \ingroup tracks 
+ */
+void
+lib3ds_lin1_track_setup(Lib3dsLin1Track *track)
+{
+  Lib3dsLin1Key *pp,*pc,*pn,*pl;
+
+  ASSERT(track);
+  pc=track->keyL;
+  if (!pc) {
+    return;
+  }
+  if (!pc->next) {
+    pc->ds=0;
+    pc->dd=0;
+    return;
+  }
+
+  if (track->flags&LIB3DS_SMOOTH) {
+    for (pl=track->keyL; pl->next->next; pl=pl->next);
+    lib3ds_lin1_key_setup(pl, pl->next, pc, 0, pc->next);
+ }
+ else {
+   lib3ds_lin1_key_setup(0, 0, pc, 0, pc->next);
+ }
+  for (;;) {
+    pp=pc;
+    pc=pc->next;
+    pn=pc->next;
+    if (!pn) {
+      break;
+    }
+    lib3ds_lin1_key_setup(pp, 0, pc, 0, pn);
+  }
+
+  if (track->flags&LIB3DS_SMOOTH) {
+    lib3ds_lin1_key_setup(pp, 0, pc, track->keyL, track->keyL->next);
+  }
+  else {
+    lib3ds_lin1_key_setup(pp, 0, pc, 0, 0);
+  }
+}
+
+
+/*!
+ * \ingroup tracks 
+ */
+void
+lib3ds_lin1_track_insert(Lib3dsLin1Track *track, Lib3dsLin1Key *key)
+{
+  ASSERT(track);
+  ASSERT(key);
+  ASSERT(!key->next);
+
+  if (!track->keyL) {
+    track->keyL=key;
+    key->next=0;
+  }
+  else {
+    Lib3dsLin1Key *k,*p;
+
+    for (p=0,k=track->keyL; k!=0; p=k, k=k->next) {
+      if (k->tcb.frame>key->tcb.frame) {
+        break;
+      }
+    }
+    if (!p) {
+      key->next=track->keyL;
+      track->keyL=key;
+    }
+    else {
+      key->next=k;
+      p->next=key;
+    }
+    if (k && (key->tcb.frame==k->tcb.frame)) {
+      key->next=k->next;
+      lib3ds_lin1_key_free(k);
+    }
+  }
+}
+
+
+/*!
+ * \ingroup tracks 
+ */
+void
+lib3ds_lin1_track_remove(Lib3dsLin1Track *track, Lib3dsIntd frame)
+{
+  Lib3dsLin1Key *k,*p;
+  
+  ASSERT(track);
+  if (!track->keyL) {
+    return;
+  }
+  for (p=0,k=track->keyL; k!=0; p=k, k=k->next) {
+    if (k->tcb.frame==frame) {
+      if (!p) {
+        track->keyL=track->keyL->next;
+      }
+      else {
+        p->next=k->next;
+      }
+      lib3ds_lin1_key_free(k);
+      break;
+    }
+  }
+}
+
+
+/*!
+ * \ingroup tracks 
+ */
+void
+lib3ds_lin1_track_eval(Lib3dsLin1Track *track, Lib3dsFloat *p, Lib3dsFloat t)
+{
+  Lib3dsLin1Key *k;
+  Lib3dsFloat nt;
+  Lib3dsFloat u;
+
+  ASSERT(p);
+  if (!track->keyL) {
+    *p=0;
+    return;
+  }
+  if (!track->keyL->next) {
+    *p = track->keyL->value;
+    return;
+  }
+
+  for (k=track->keyL; k->next!=0; k=k->next) {
+    if ((t>=(Lib3dsFloat)k->tcb.frame) && (t<(Lib3dsFloat)k->next->tcb.frame)) {
+      break;
+    }
+  }
+  if (!k->next) {
+    if (track->flags&LIB3DS_REPEAT) {
+      nt=(Lib3dsFloat)fmod(t, k->tcb.frame);
+      for (k=track->keyL; k->next!=0; k=k->next) {
+        if ((nt>=(Lib3dsFloat)k->tcb.frame) && (nt<(Lib3dsFloat)k->next->tcb.frame)) {
+          break;
+        }
+      }
+      ASSERT(k->next);
+    }
+    else {
+      *p = k->value;
+      return;
+    }
+  }
+  else {
+    nt=t;
+  }
+  u=nt - (Lib3dsFloat)k->tcb.frame;
+  u/=(Lib3dsFloat)(k->next->tcb.frame - k->tcb.frame);
+
+  *p = lib3ds_float_cubic(
+    k->value,
+    k->dd,
+    k->next->ds,
+    k->next->value,
+    u
+  );
+}
+
+
+/*!
+ * \ingroup tracks 
+ */
+Lib3dsBool
+lib3ds_lin1_track_read(Lib3dsLin1Track *track, Lib3dsIo *io)
+{
+  int keys;
+  int i;
+  Lib3dsLin1Key *k;
+
+  track->flags=lib3ds_io_read_word(io);
+  lib3ds_io_read_dword(io);
+  lib3ds_io_read_dword(io);
+  keys=lib3ds_io_read_intd(io);
+
+  for (i=0; i<keys; ++i) {
+    k=lib3ds_lin1_key_new();
+    if (!lib3ds_tcb_read(&k->tcb, io)) {
+      return(LIB3DS_FALSE);
+    }
+    k->value=lib3ds_io_read_float(io);
+    lib3ds_lin1_track_insert(track, k);
+  }
+  lib3ds_lin1_track_setup(track);
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+ * \ingroup tracks 
+ */
+Lib3dsBool
+lib3ds_lin1_track_write(Lib3dsLin1Track *track, Lib3dsIo *io)
+{
+  Lib3dsLin1Key *k;
+  Lib3dsDword num=0;
+  for (k=track->keyL; k; k=k->next) {
+    ++num;
+  }
+  lib3ds_io_write_word(io, (Lib3dsWord)track->flags);
+  lib3ds_io_write_dword(io, 0);
+  lib3ds_io_write_dword(io, 0);
+  lib3ds_io_write_dword(io, num);
+
+  for (k=track->keyL; k; k=k->next) {
+    if (!lib3ds_tcb_write(&k->tcb,io)) {
+      return(LIB3DS_FALSE);
+    }
+    lib3ds_io_write_float(io, k->value);
+  }
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+ * Create and return one keyframe in a Lin3 track.  All values are
+ * initialized to zero.
+ *
+ * \ingroup tracks 
+ */
+Lib3dsLin3Key*
+lib3ds_lin3_key_new()
+{
+  Lib3dsLin3Key* k;
+  k=(Lib3dsLin3Key*)calloc(sizeof(Lib3dsLin3Key), 1);
+  return(k);
+}
+
+
+/*!
+ * Free a Lin3 keyframe.
+ *
+ * \ingroup tracks 
+ */
+void
+lib3ds_lin3_key_free(Lib3dsLin3Key *key)
+{
+  ASSERT(key);
+  free(key);
+}
+
+
+/*!
+ * Free all keyframes in a Lin3 track.
+ *
+ * \ingroup tracks 
+ */
+void
+lib3ds_lin3_track_free_keys(Lib3dsLin3Track *track)
+{
+  Lib3dsLin3Key *p,*q;
+
+  ASSERT(track);
+  for (p=track->keyL; p; p=q) {
+    q=p->next;
+    lib3ds_lin3_key_free(p);
+  }
+}
+
+
+/*!
+ * \ingroup tracks 
+ */
+void
+lib3ds_lin3_key_setup(Lib3dsLin3Key *p, Lib3dsLin3Key *cp, Lib3dsLin3Key *c,
+  Lib3dsLin3Key *cn, Lib3dsLin3Key *n)
+{
+  Lib3dsVector np,nn;
+  Lib3dsFloat ksm,ksp,kdm,kdp;
+  int i;
+  
+  ASSERT(c);
+  if (!cp) {
+    cp=c;
+  }
+  if (!cn) {
+    cn=c;
+  }
+  if (!p && !n) {
+    lib3ds_vector_zero(c->ds);
+    lib3ds_vector_zero(c->dd);
+    return;
+  }
+
+  if (n && p) {
+    lib3ds_tcb(&p->tcb, &cp->tcb, &c->tcb, &cn->tcb, &n->tcb, &ksm, &ksp, &kdm, &kdp);
+    lib3ds_vector_sub(np, c->value, p->value); 
+    lib3ds_vector_sub(nn, n->value, c->value); 
+
+    for(i=0; i<3; ++i) {
+      c->ds[i]=ksm*np[i] + ksp*nn[i];
+      c->dd[i]=kdm*np[i] + kdp*nn[i];
+    }
+  }
+  else {
+    if (p) {
+      lib3ds_vector_sub(np, c->value, p->value);
+      lib3ds_vector_copy(c->ds, np);
+      lib3ds_vector_copy(c->dd, np);
+    }
+    if (n) {
+      lib3ds_vector_sub(nn, n->value, c->value); 
+      lib3ds_vector_copy(c->ds, nn);
+      lib3ds_vector_copy(c->dd, nn);
+    }
+  }
+}
+
+
+/*!
+ * \ingroup tracks 
+ */
+void
+lib3ds_lin3_track_setup(Lib3dsLin3Track *track)
+{
+  Lib3dsLin3Key *pp,*pc,*pn,*pl;
+
+  ASSERT(track);
+  pc=track->keyL;
+  if (!pc) {
+    return;
+  }
+  if (!pc->next) {
+    lib3ds_vector_zero(pc->ds);
+    lib3ds_vector_zero(pc->dd);
+    return;
+  }
+
+  if (track->flags&LIB3DS_SMOOTH) {
+    for (pl=track->keyL; pl->next->next; pl=pl->next);
+    lib3ds_lin3_key_setup(pl, pl->next, pc, 0, pc->next);
+ }
+ else {
+   lib3ds_lin3_key_setup(0, 0, pc, 0, pc->next);
+ }
+  for (;;) {
+    pp=pc;
+    pc=pc->next;
+    pn=pc->next;
+    if (!pn) {
+      break;
+    }
+    lib3ds_lin3_key_setup(pp, 0, pc, 0, pn);
+  }
+
+  if (track->flags&LIB3DS_SMOOTH) {
+    lib3ds_lin3_key_setup(pp, 0, pc, track->keyL, track->keyL->next);
+  }
+  else {
+    lib3ds_lin3_key_setup(pp, 0, pc, 0, 0);
+  }
+}
+
+
+/*!
+ * \ingroup tracks 
+ */
+void
+lib3ds_lin3_track_insert(Lib3dsLin3Track *track, Lib3dsLin3Key *key)
+{
+  ASSERT(track);
+  ASSERT(key);
+  ASSERT(!key->next);
+
+  if (!track->keyL) {
+    track->keyL=key;
+    key->next=0;
+  }
+  else {
+    Lib3dsLin3Key *k,*p;
+
+    for (p=0,k=track->keyL; k!=0; p=k, k=k->next) {
+      if (k->tcb.frame>key->tcb.frame) {
+        break;
+      }
+    }
+    if (!p) {
+      key->next=track->keyL;
+      track->keyL=key;
+    }
+    else {
+      key->next=k;
+      p->next=key;
+    }
+    if (k && (key->tcb.frame==k->tcb.frame)) {
+      key->next=k->next;
+      lib3ds_lin3_key_free(k);
+    }
+  }
+}
+
+
+/*!
+ * \ingroup tracks 
+ */
+void
+lib3ds_lin3_track_remove(Lib3dsLin3Track *track, Lib3dsIntd frame)
+{
+  Lib3dsLin3Key *k,*p;
+  
+  ASSERT(track);
+  if (!track->keyL) {
+    return;
+  }
+  for (p=0,k=track->keyL; k!=0; p=k, k=k->next) {
+    if (k->tcb.frame==frame) {
+      if (!p) {
+        track->keyL=track->keyL->next;
+      }
+      else {
+        p->next=k->next;
+      }
+      lib3ds_lin3_key_free(k);
+      break;
+    }
+  }
+}
+
+
+/*!
+ * \ingroup tracks 
+ */
+void
+lib3ds_lin3_track_eval(Lib3dsLin3Track *track, Lib3dsVector p, Lib3dsFloat t)
+{
+  Lib3dsLin3Key *k;
+  Lib3dsFloat nt;
+  Lib3dsFloat u;
+
+  if (!track->keyL) {
+    lib3ds_vector_zero(p);
+    return;
+  }
+  if (!track->keyL->next) {
+      lib3ds_vector_copy(p, track->keyL->value);
+    return;
+  }
+
+  for (k=track->keyL; k->next!=0; k=k->next) {
+    if ((t>=(Lib3dsFloat)k->tcb.frame) && (t<(Lib3dsFloat)k->next->tcb.frame)) {
+      break;
+    }
+  }
+  if (!k->next) {
+    if (track->flags&LIB3DS_REPEAT) {
+      nt=(Lib3dsFloat)fmod(t, k->tcb.frame);
+      for (k=track->keyL; k->next!=0; k=k->next) {
+        if ((nt>=(Lib3dsFloat)k->tcb.frame) && (nt<(Lib3dsFloat)k->next->tcb.frame)) {
+          break;
+        }
+      }
+      ASSERT(k->next);
+    }
+    else {
+      lib3ds_vector_copy(p, k->value);
+      return;
+    }
+  }
+  else {
+    nt=t;
+  }
+  u=nt - (Lib3dsFloat)k->tcb.frame;
+  u/=(Lib3dsFloat)(k->next->tcb.frame - k->tcb.frame);
+  
+  lib3ds_vector_cubic(
+    p,
+    k->value,
+    k->dd,
+    k->next->ds,
+    k->next->value,
+    u
+  );
+}
+
+
+/*!
+ * \ingroup tracks 
+ */
+Lib3dsBool
+lib3ds_lin3_track_read(Lib3dsLin3Track *track, Lib3dsIo *io)
+{
+  int keys;
+  int i,j;
+  Lib3dsLin3Key *k;
+
+  track->flags=lib3ds_io_read_word(io);
+  lib3ds_io_read_dword(io);
+  lib3ds_io_read_dword(io);
+  keys=lib3ds_io_read_intd(io);
+
+  for (i=0; i<keys; ++i) {
+    k=lib3ds_lin3_key_new();
+    if (!lib3ds_tcb_read(&k->tcb, io)) {
+      return(LIB3DS_FALSE);
+    }
+    for (j=0; j<3; ++j) {
+      k->value[j]=lib3ds_io_read_float(io);
+    }
+    lib3ds_lin3_track_insert(track, k);
+  }
+  lib3ds_lin3_track_setup(track);
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+ * \ingroup tracks 
+ */
+Lib3dsBool
+lib3ds_lin3_track_write(Lib3dsLin3Track *track, Lib3dsIo *io)
+{
+  Lib3dsLin3Key *k;
+  Lib3dsDword num=0;
+  for (k=track->keyL; k; k=k->next) {
+    ++num;
+  }
+  lib3ds_io_write_word(io, (Lib3dsWord)track->flags);
+  lib3ds_io_write_dword(io, 0);
+  lib3ds_io_write_dword(io, 0);
+  lib3ds_io_write_dword(io, num);
+
+  for (k=track->keyL; k; k=k->next) {
+    if (!lib3ds_tcb_write(&k->tcb,io)) {
+      return(LIB3DS_FALSE);
+    }
+    lib3ds_io_write_vector(io, k->value);
+  }
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+ * \ingroup tracks 
+ */
+Lib3dsQuatKey*
+lib3ds_quat_key_new()
+{
+  Lib3dsQuatKey* k;
+  k=(Lib3dsQuatKey*)calloc(sizeof(Lib3dsQuatKey), 1);
+  return(k);
+}
+
+
+/*!
+ * \ingroup tracks 
+ */
+void
+lib3ds_quat_key_free(Lib3dsQuatKey *key)
+{
+  ASSERT(key);
+  free(key);
+}
+
+
+/*!
+ * \ingroup tracks 
+ */
+void
+lib3ds_quat_track_free_keys(Lib3dsQuatTrack *track)
+{
+  Lib3dsQuatKey *p,*q;
+
+  ASSERT(track);
+  for (p=track->keyL; p; p=q) {
+    q=p->next;
+    lib3ds_quat_key_free(p);
+  }
+}
+
+
+/*!
+ * \ingroup tracks 
+ */
+void
+lib3ds_quat_key_setup(Lib3dsQuatKey *p, Lib3dsQuatKey *cp, Lib3dsQuatKey *c,
+  Lib3dsQuatKey *cn, Lib3dsQuatKey *n)
+{
+  Lib3dsFloat ksm,ksp,kdm,kdp;
+  Lib3dsQuat q,qp,qn,qa,qb;
+  int i;
+  
+  ASSERT(c);
+  if (!cp) {
+    cp=c;
+  }
+  if (!cn) {
+    cn=c;
+  }
+  if (!p || !n) {
+    lib3ds_quat_copy(c->ds, c->q);
+    lib3ds_quat_copy(c->dd, c->q);
+    return;
+  }
+
+  if (p) {
+    if (p->angle>LIB3DS_TWOPI-LIB3DS_EPSILON) {
+      lib3ds_quat_axis_angle(qp, p->axis, 0.0f);
+      lib3ds_quat_ln(qp);
+    }
+    else {
+      lib3ds_quat_copy(q, p->q);
+      if (lib3ds_quat_dot(q,c->q)<0) lib3ds_quat_neg(q);
+      lib3ds_quat_ln_dif(qp, c->q, q);
+    }
+  }
+  if (n) {
+    if (n->angle>LIB3DS_TWOPI-LIB3DS_EPSILON) {
+      lib3ds_quat_axis_angle(qn, n->axis, 0.0f);
+      lib3ds_quat_ln(qn);
+    }
+    else {
+      lib3ds_quat_copy(q, n->q);
+      if (lib3ds_quat_dot(q,c->q)<0) lib3ds_quat_neg(q);
+      lib3ds_quat_ln_dif(qn, c->q, q);
+    }
+  }
+
+  if (n && p) {
+    lib3ds_tcb(&p->tcb, &cp->tcb, &c->tcb, &cn->tcb, &n->tcb, &ksm, &ksp, &kdm, &kdp);
+    for(i=0; i<4; i++) {
+      qa[i]=-0.5f*(kdm*qn[i]+kdp*qp[i]);
+      qb[i]=-0.5f*(ksm*qn[i]+ksp*qp[i]);
+    }
+    lib3ds_quat_exp(qa);
+    lib3ds_quat_exp(qb);
+    
+    lib3ds_quat_mul(c->ds, c->q, qa);
+    lib3ds_quat_mul(c->dd, c->q, qb);
+  }
+  else {
+    if (p) {
+      lib3ds_quat_exp(qp);
+      lib3ds_quat_mul(c->ds, c->q, qp);
+      lib3ds_quat_mul(c->dd, c->q, qp);
+    }
+    if (n) {
+      lib3ds_quat_exp(qn);
+      lib3ds_quat_mul(c->ds, c->q, qn);
+      lib3ds_quat_mul(c->dd, c->q, qn);
+    }
+  }
+}
+
+
+/*!
+ * \ingroup tracks 
+ */
+void
+lib3ds_quat_track_setup(Lib3dsQuatTrack *track)
+{
+  Lib3dsQuatKey *pp,*pc,*pn,*pl;
+  Lib3dsQuat q;
+
+  ASSERT(track);
+  for (pp=0,pc=track->keyL; pc; pp=pc,pc=pc->next) {
+    lib3ds_quat_axis_angle(q, pc->axis, pc->angle);
+    if (pp) {
+      lib3ds_quat_mul(pc->q, q, pp->q);
+    }
+    else {
+      lib3ds_quat_copy(pc->q, q);
+    }
+  }
+
+  pc=track->keyL;
+  if (!pc) {
+    return;
+  }
+  if (!pc->next) {
+    lib3ds_quat_copy(pc->ds, pc->q);
+    lib3ds_quat_copy(pc->dd, pc->q);
+    return;
+  }
+
+  if (track->flags&LIB3DS_SMOOTH) {
+    for (pl=track->keyL; pl->next->next; pl=pl->next);
+    lib3ds_quat_key_setup(pl, pl->next, pc, 0, pc->next);
+ }
+  else {
+    lib3ds_quat_key_setup(0, 0, pc, 0, pc->next);
+  }
+  for (;;) {
+    pp=pc;
+    pc=pc->next;
+    pn=pc->next;
+    if (!pn) {
+      break;
+    }
+    lib3ds_quat_key_setup(pp, 0, pc, 0, pn);
+  }
+
+  if (track->flags&LIB3DS_SMOOTH) {
+    lib3ds_quat_key_setup(pp, 0, pc, track->keyL, track->keyL->next);
+  }
+  else {
+    lib3ds_quat_key_setup(pp, 0, pc, 0, 0);
+  }
+}
+
+
+/*!
+ * \ingroup tracks 
+ */
+void
+lib3ds_quat_track_insert(Lib3dsQuatTrack *track, Lib3dsQuatKey *key)
+{
+  ASSERT(track);
+  ASSERT(key);
+  ASSERT(!key->next);
+
+  if (!track->keyL) {
+    track->keyL=key;
+    key->next=0;
+  }
+  else {
+    Lib3dsQuatKey *k,*p;
+
+    for (p=0,k=track->keyL; k!=0; p=k, k=k->next) {
+      if (k->tcb.frame>key->tcb.frame) {
+        break;
+      }
+    }
+    if (!p) {
+      key->next=track->keyL;
+      track->keyL=key;
+    }
+    else {
+      key->next=k;
+      p->next=key;
+    }
+    if (k && (key->tcb.frame==k->tcb.frame)) {
+      key->next=k->next;
+      lib3ds_quat_key_free(k);
+    }
+  }
+}
+
+
+/*!
+ * \ingroup tracks 
+ */
+void
+lib3ds_quat_track_remove(Lib3dsQuatTrack *track, Lib3dsIntd frame)
+{
+  Lib3dsQuatKey *k,*p;
+  
+  ASSERT(track);
+  if (!track->keyL) {
+    return;
+  }
+  for (p=0,k=track->keyL; k!=0; p=k, k=k->next) {
+    if (k->tcb.frame==frame) {
+      if (!p) {
+        track->keyL=track->keyL->next;
+      }
+      else {
+        p->next=k->next;
+      }
+      lib3ds_quat_key_free(k);
+      break;
+    }
+  }
+}
+
+
+/*!
+ * \ingroup tracks 
+ */
+void
+lib3ds_quat_track_eval(Lib3dsQuatTrack *track, Lib3dsQuat q, Lib3dsFloat t)
+{
+  Lib3dsQuatKey *k;
+  Lib3dsFloat nt;
+  Lib3dsFloat u;
+
+  if (!track->keyL) {
+    lib3ds_quat_identity(q);
+    return;
+  }
+  if (!track->keyL->next) {
+    lib3ds_quat_copy(q, track->keyL->q);
+    return;
+  }
+
+  for (k=track->keyL; k->next!=0; k=k->next) {
+    if ((t>=k->tcb.frame) && (t<k->next->tcb.frame)) {
+      break;
+    }
+  }
+  if (!k->next) {
+    if (track->flags&LIB3DS_REPEAT) {
+      nt=(Lib3dsFloat)fmod(t, k->tcb.frame);
+      for (k=track->keyL; k->next!=0; k=k->next) {
+        if ((nt>=k->tcb.frame) && (nt<k->next->tcb.frame)) {
+          break;
+        }
+      }
+      ASSERT(k->next);
+    }
+    else {
+      lib3ds_quat_copy(q, k->q);
+      return;
+    }
+  }
+  else {
+    nt=t;
+  }
+  u=nt - k->tcb.frame;
+  u/=(k->next->tcb.frame - k->tcb.frame);
+
+  lib3ds_quat_squad(
+    q,
+    k->q,
+    k->dd,
+    k->next->ds,
+    k->next->q,
+    u
+  );
+}
+
+
+/*!
+ * \ingroup tracks 
+ */
+Lib3dsBool
+lib3ds_quat_track_read(Lib3dsQuatTrack *track, Lib3dsIo *io)
+{
+  int keys;
+  int i,j;
+  Lib3dsQuatKey *p,*k;
+
+  track->flags=lib3ds_io_read_word(io);
+  lib3ds_io_read_dword(io);
+  lib3ds_io_read_dword(io);
+  keys=lib3ds_io_read_intd(io);
+
+  for (p=0,i=0; i<keys; p=k,++i) {
+    k=lib3ds_quat_key_new();
+    if (!lib3ds_tcb_read(&k->tcb, io)) {
+      return(LIB3DS_FALSE);
+    }
+    k->angle=lib3ds_io_read_float(io);
+    for (j=0; j<3; ++j) {
+      k->axis[j]=lib3ds_io_read_float(io);
+    }
+    lib3ds_quat_track_insert(track, k);
+  }
+  lib3ds_quat_track_setup(track);
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+ * \ingroup tracks 
+ */
+Lib3dsBool
+lib3ds_quat_track_write(Lib3dsQuatTrack *track, Lib3dsIo *io)
+{
+  Lib3dsQuatKey *k;
+  Lib3dsDword num=0;
+  for (k=track->keyL; k; k=k->next) {
+    ++num;
+  }
+  lib3ds_io_write_word(io, (Lib3dsWord)track->flags);
+  lib3ds_io_write_dword(io, 0);
+  lib3ds_io_write_dword(io, 0);
+  lib3ds_io_write_dword(io, num);
+
+  for (k=track->keyL; k; k=k->next) {
+    if (!lib3ds_tcb_write(&k->tcb,io)) {
+      return(LIB3DS_FALSE);
+    }
+    lib3ds_io_write_float(io, k->angle);
+    lib3ds_io_write_vector(io, k->axis);
+  }
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+ * \ingroup tracks 
+ */
+Lib3dsMorphKey*
+lib3ds_morph_key_new()
+{
+  Lib3dsMorphKey* k;
+  k=(Lib3dsMorphKey*)calloc(sizeof(Lib3dsMorphKey), 1);
+  return(k);
+}
+
+
+/*!
+ * \ingroup tracks 
+ */
+void
+lib3ds_morph_key_free(Lib3dsMorphKey *key)
+{
+  ASSERT(key);
+  free(key);
+}
+
+
+/*!
+ * \ingroup tracks 
+ */
+void
+lib3ds_morph_track_free_keys(Lib3dsMorphTrack *track)
+{
+  Lib3dsMorphKey *p,*q;
+
+  ASSERT(track);
+  for (p=track->keyL; p; p=q) {
+    q=p->next;
+    lib3ds_morph_key_free(p);
+  }
+}
+
+
+/*!
+ * \ingroup tracks 
+ */
+void
+lib3ds_morph_track_insert(Lib3dsMorphTrack *track, Lib3dsMorphKey *key)
+{
+  ASSERT(track);
+  ASSERT(key);
+  ASSERT(!key->next);
+
+  if (!track->keyL) {
+    track->keyL=key;
+    key->next=0;
+  }
+  else {
+    Lib3dsMorphKey *k,*p;
+
+    for (p=0,k=track->keyL; k!=0; p=k, k=k->next) {
+      if (k->tcb.frame>key->tcb.frame) {
+        break;
+      }
+    }
+    if (!p) {
+      key->next=track->keyL;
+      track->keyL=key;
+    }
+    else {
+      key->next=k;
+      p->next=key;
+    }
+    if (k && (key->tcb.frame==k->tcb.frame)) {
+      key->next=k->next;
+      lib3ds_morph_key_free(k);
+    }
+  }
+}
+
+
+/*!
+ * \ingroup tracks 
+ */
+void
+lib3ds_morph_track_remove(Lib3dsMorphTrack *track, Lib3dsIntd frame)
+{
+  Lib3dsMorphKey *k,*p;
+  
+  ASSERT(track);
+  if (!track->keyL) {
+    return;
+  }
+  for (p=0,k=track->keyL; k!=0; p=k, k=k->next) {
+    if (k->tcb.frame==frame) {
+      if (!p) {
+        track->keyL=track->keyL->next;
+      }
+      else {
+        p->next=k->next;
+      }
+      lib3ds_morph_key_free(k);
+      break;
+    }
+  }
+}
+
+
+/*!
+ * \ingroup tracks 
+ */
+void
+lib3ds_morph_track_eval(Lib3dsMorphTrack *track, char *p, Lib3dsFloat t)
+{
+  Lib3dsMorphKey *k;
+  char* result;
+
+  ASSERT(p);
+  if (!track->keyL) {
+    strcpy(p,"");
+    return;
+  }
+  if (!track->keyL->next) {
+    strcpy(p,track->keyL->name);
+    return;
+  }
+
+
+  /* TODO: this function finds the mesh frame that corresponds to this
+   * timeframe.  It would be better to actually interpolate the mesh.
+   */
+
+  result=0;
+
+  for(k = track->keyL;
+      k->next != NULL && t >= k->next->tcb.frame;
+      k = k->next);
+
+  result=k->name;
+
+  if (result) {
+    strcpy(p,result);
+  }
+  else {
+    strcpy(p,"");
+  }
+}
+
+
+/*!
+ * \ingroup tracks
+ */
+Lib3dsBool
+lib3ds_morph_track_read(Lib3dsMorphTrack *track, Lib3dsIo *io)
+{
+  /* This function was written by Stephane Denis on 5-18-04 */
+    int i;
+    Lib3dsMorphKey *k, *pk = 0;
+    int keys;
+    track->flags=lib3ds_io_read_word(io);
+    lib3ds_io_read_dword(io);
+    lib3ds_io_read_dword(io);
+    keys=lib3ds_io_read_intd(io);
+
+    for (i=0; i<keys; ++i) {
+        k=lib3ds_morph_key_new();
+        if (!lib3ds_tcb_read(&k->tcb, io)) {
+            return(LIB3DS_FALSE);
+        }
+        if (!lib3ds_io_read_string(io, k->name, 11)) {
+            return(LIB3DS_FALSE);
+        }
+        if (!track->keyL)
+            track->keyL = k;
+        else
+            pk->next = k;
+        pk = k;
+    }
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+ * \ingroup tracks 
+ */
+Lib3dsBool
+lib3ds_morph_track_write(Lib3dsMorphTrack *track, Lib3dsIo *io)
+{
+  /* FIXME: */
+  ASSERT(0);
+  return(LIB3DS_FALSE);
+}
+
+
+
+void
+tcb_dump(Lib3dsTcb *tcb)
+{
+  printf("  tcb: frame=%d, flags=%04x, tens=%g, cont=%g, ",
+    (int)tcb->frame, tcb->flags, tcb->tens, tcb->cont);
+  printf("bias=%g, ease_to=%g, ease_from=%g\n",
+    tcb->bias, tcb->ease_to, tcb->ease_from);
+}
+
+
+void
+lib3ds_boolTrack_dump(Lib3dsBoolTrack *track)
+{
+  Lib3dsBoolKey *key;
+  printf("flags: %08x, keys:\n", (unsigned int)track->flags);
+  for( key = track->keyL; key != NULL; key = key->next)
+  {
+    tcb_dump(&key->tcb);
+  }
+}
+
+
+void
+lib3ds_lin1Track_dump(Lib3dsLin1Track *track)
+{
+  Lib3dsLin1Key *key;
+  printf("flags: %08x, keys:\n", (unsigned int)track->flags);
+  for( key = track->keyL; key != NULL; key = key->next)
+  {
+    tcb_dump(&key->tcb);
+    printf("    value = %g, dd=%g, ds=%g\n",
+      key->value, key->dd, key->ds);
+  }
+}
+
+
+void
+lib3ds_lin3Track_dump(Lib3dsLin3Track *track)
+{
+  Lib3dsLin3Key *key;
+  printf("flags: %08x, keys:\n", (unsigned int)track->flags);
+  for( key = track->keyL; key != NULL; key = key->next)
+  {
+    tcb_dump(&key->tcb);
+    printf("    value = %g,%g,%g, dd=%g,%g,%g, ds=%g,%g,%g\n",
+      key->value[0], key->value[1], key->value[2],
+      key->dd[0], key->dd[1], key->dd[2],
+      key->ds[0], key->ds[1], key->ds[2]);
+  }
+}
+
+
+void
+lib3ds_quatTrack_dump(Lib3dsQuatTrack *track)
+{
+  Lib3dsQuatKey *key;
+  printf("flags: %08x, keys:\n", (unsigned int)track->flags);
+  for( key = track->keyL; key != NULL; key = key->next)
+  {
+    tcb_dump(&key->tcb);
+    printf("    axis = %g,%g,%g, angle=%g, q=%g,%g,%g,%g\n",
+      key->axis[0], key->axis[1], key->axis[2], key->angle,
+      key->q[0], key->q[1], key->q[2], key->q[3]);
+    printf("    dd = %g,%g,%g,%g, ds=%g,%g,%g,%g\n",
+      key->dd[0], key->dd[1], key->dd[2], key->dd[3],
+      key->ds[0], key->ds[1], key->ds[2], key->ds[3]);
+  }
+}
+
+
+void
+lib3ds_morphTrack_dump(Lib3dsMorphTrack *track)
+{
+  Lib3dsMorphKey *key;
+  printf("flags: %08x, keys:\n", (unsigned int)track->flags);
+  for( key = track->keyL; key != NULL; key = key->next)
+  {
+    tcb_dump(&key->tcb);
+    printf("    name = %s\n", key->name);
+  }
+}
+
+
+
+void
+lib3ds_dump_tracks(Lib3dsNode *node)
+{
+  switch( node->type ) {
+    case LIB3DS_AMBIENT_NODE:
+      printf("ambient: ");
+      lib3ds_lin3Track_dump(&node->data.ambient.col_track);
+      break;
+    case LIB3DS_OBJECT_NODE:
+      printf("pos: ");
+      lib3ds_lin3Track_dump(&node->data.object.pos_track);
+      printf("rot: ");
+      lib3ds_quatTrack_dump(&node->data.object.rot_track);
+      printf("scl: ");
+      lib3ds_lin3Track_dump(&node->data.object.scl_track);
+      printf("morph: ");
+      lib3ds_morphTrack_dump(&node->data.object.morph_track);
+      printf("hide: ");
+      lib3ds_boolTrack_dump(&node->data.object.hide_track);
+      break;
+    case LIB3DS_CAMERA_NODE:
+      printf("pos: ");
+      lib3ds_lin3Track_dump(&node->data.camera.pos_track);
+      printf("fov: ");
+      lib3ds_lin1Track_dump(&node->data.camera.fov_track);
+      printf("roll: ");
+      lib3ds_lin1Track_dump(&node->data.camera.roll_track);
+      break;
+    case LIB3DS_TARGET_NODE:
+      printf("pos: ");
+      lib3ds_lin3Track_dump(&node->data.target.pos_track);
+      break;
+    case LIB3DS_LIGHT_NODE:
+      printf("pos: ");
+      lib3ds_lin3Track_dump(&node->data.light.pos_track);
+      printf("col: ");
+      lib3ds_lin3Track_dump(&node->data.light.col_track);
+      printf("hotspot: ");
+      lib3ds_lin1Track_dump(&node->data.light.hotspot_track);
+      printf("falloff: ");
+      lib3ds_lin1Track_dump(&node->data.light.falloff_track);
+      printf("roll: ");
+      lib3ds_lin1Track_dump(&node->data.light.roll_track);
+      break;
+    case LIB3DS_SPOT_NODE:
+      printf("pos: ");
+      lib3ds_lin3Track_dump(&node->data.spot.pos_track);
+      break;
+
+       default:
+         break;
+  }
+}
diff --git a/src/3dengfx/libs/lib3ds/tracks.h b/src/3dengfx/libs/lib3ds/tracks.h
new file mode 100644 (file)
index 0000000..5f10df5
--- /dev/null
@@ -0,0 +1,209 @@
+/* -*- c -*- */
+#ifndef INCLUDED_LIB3DS_TRACKS_H
+#define INCLUDED_LIB3DS_TRACKS_H
+/*
+ * The 3D Studio File Format Library
+ * Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
+ * All rights reserved.
+ *
+ * This program is  free  software;  you can redistribute it and/or modify it
+ * under the terms of the  GNU Lesser General Public License  as published by 
+ * the  Free Software Foundation;  either version 2.1 of the License,  or (at 
+ * your option) any later version.
+ *
+ * This  program  is  distributed in  the  hope that it will  be useful,  but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public  
+ * License for more details.
+ *
+ * You should  have received  a copy of the GNU Lesser General Public License
+ * along with  this program;  if not, write to the  Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: tracks.h,v 1.9 2004/12/31 16:17:15 reed Exp $
+ */
+
+#ifndef INCLUDED_LIB3DS_TCB_H
+#include <lib3ds/tcb.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*!
+ * Track flags
+ * \ingroup tracks
+ */
+typedef enum {
+  LIB3DS_REPEAT    =0x0001,
+  LIB3DS_SMOOTH    =0x0002,
+  LIB3DS_LOCK_X    =0x0008,
+  LIB3DS_LOCK_Y    =0x0010,
+  LIB3DS_LOCK_Z    =0x0020,
+  LIB3DS_UNLINK_X  =0x0100,
+  LIB3DS_UNLINK_Y  =0x0200,
+  LIB3DS_UNLINK_Z  =0x0400
+} Lib3dsTrackFlags;
+
+/*!
+ * Boolean track key
+ * \ingroup tracks
+ */
+struct _Lib3dsBoolKey {
+    Lib3dsTcb tcb;
+    Lib3dsBoolKey *next;
+};
+
+/*!
+ * Boolean track
+ * \ingroup tracks
+ */
+struct _Lib3dsBoolTrack {
+    Lib3dsDword flags;
+    Lib3dsBoolKey *keyL;
+};
+
+/*!
+ * Floating-point track key
+ * \ingroup tracks
+ */
+struct _Lib3dsLin1Key {
+    Lib3dsTcb tcb;
+    Lib3dsLin1Key *next;
+    Lib3dsFloat value;
+    Lib3dsFloat dd;
+    Lib3dsFloat ds;
+};
+  
+/*!
+ * Floating-point track
+ * \ingroup tracks
+ */
+struct _Lib3dsLin1Track {
+    Lib3dsDword flags;
+    Lib3dsLin1Key *keyL;
+};
+
+/*!
+ * Vector track key
+ * \ingroup tracks
+ */
+struct _Lib3dsLin3Key {
+    Lib3dsTcb tcb;
+    Lib3dsLin3Key *next;  
+    Lib3dsVector value;
+    Lib3dsVector dd;
+    Lib3dsVector ds;
+};
+  
+/*!
+ * Vector track
+ * \ingroup tracks
+ */
+struct _Lib3dsLin3Track {
+    Lib3dsDword flags;
+    Lib3dsLin3Key *keyL;
+};
+
+/*!
+ * Rotation track key
+ * \ingroup tracks
+ */
+struct _Lib3dsQuatKey {
+    Lib3dsTcb tcb;
+    Lib3dsQuatKey *next;  
+    Lib3dsVector axis;
+    Lib3dsFloat angle;
+    Lib3dsQuat q;
+    Lib3dsQuat dd;
+    Lib3dsQuat ds;
+};
+  
+/*!
+ * Rotation track 
+ * \ingroup tracks
+ */
+struct _Lib3dsQuatTrack {
+    Lib3dsDword flags;
+    Lib3dsQuatKey *keyL;
+};
+
+/*!
+ * Morph track key
+ * \ingroup tracks
+ */
+struct _Lib3dsMorphKey {
+    Lib3dsTcb tcb;
+    Lib3dsMorphKey *next;  
+    char name[64];
+};
+  
+/*!
+ * Morph track
+ * \ingroup tracks
+ */
+struct _Lib3dsMorphTrack {
+    Lib3dsDword flags;
+    Lib3dsMorphKey *keyL;
+};
+
+extern LIB3DSAPI Lib3dsBoolKey* lib3ds_bool_key_new();
+extern LIB3DSAPI void lib3ds_bool_key_free(Lib3dsBoolKey* key);
+extern LIB3DSAPI void lib3ds_bool_track_free_keys(Lib3dsBoolTrack *track);
+extern LIB3DSAPI void lib3ds_bool_track_insert(Lib3dsBoolTrack *track, Lib3dsBoolKey* key);
+extern LIB3DSAPI void lib3ds_bool_track_remove(Lib3dsBoolTrack *track, Lib3dsIntd frame);
+extern LIB3DSAPI void lib3ds_bool_track_eval(Lib3dsBoolTrack *track, Lib3dsBool *p, Lib3dsFloat t);
+extern LIB3DSAPI Lib3dsBool lib3ds_bool_track_read(Lib3dsBoolTrack *track, Lib3dsIo *io);
+extern LIB3DSAPI Lib3dsBool lib3ds_bool_track_write(Lib3dsBoolTrack *track, Lib3dsIo *io);
+
+extern LIB3DSAPI Lib3dsLin1Key* lib3ds_lin1_key_new();
+extern LIB3DSAPI void lib3ds_lin1_key_free(Lib3dsLin1Key* key);
+extern LIB3DSAPI void lib3ds_lin1_track_free_keys(Lib3dsLin1Track *track);
+extern LIB3DSAPI void lib3ds_lin1_key_setup(Lib3dsLin1Key *p, Lib3dsLin1Key *cp, Lib3dsLin1Key *c,
+  Lib3dsLin1Key *cn, Lib3dsLin1Key *n);
+extern LIB3DSAPI void lib3ds_lin1_track_setup(Lib3dsLin1Track *track);
+extern LIB3DSAPI void lib3ds_lin1_track_insert(Lib3dsLin1Track *track, Lib3dsLin1Key *key);
+extern LIB3DSAPI void lib3ds_lin1_track_remove(Lib3dsLin1Track *track, Lib3dsIntd frame);
+extern LIB3DSAPI void lib3ds_lin1_track_eval(Lib3dsLin1Track *track, Lib3dsFloat *p, Lib3dsFloat t);
+extern LIB3DSAPI Lib3dsBool lib3ds_lin1_track_read(Lib3dsLin1Track *track, Lib3dsIo *io);
+extern LIB3DSAPI Lib3dsBool lib3ds_lin1_track_write(Lib3dsLin1Track *track, Lib3dsIo *io);
+
+extern LIB3DSAPI Lib3dsLin3Key* lib3ds_lin3_key_new();
+extern LIB3DSAPI void lib3ds_lin3_key_free(Lib3dsLin3Key* key);
+extern LIB3DSAPI void lib3ds_lin3_track_free_keys(Lib3dsLin3Track *track);
+extern LIB3DSAPI void lib3ds_lin3_key_setup(Lib3dsLin3Key *p, Lib3dsLin3Key *cp, Lib3dsLin3Key *c,
+  Lib3dsLin3Key *cn, Lib3dsLin3Key *n);
+extern LIB3DSAPI void lib3ds_lin3_track_setup(Lib3dsLin3Track *track);
+extern LIB3DSAPI void lib3ds_lin3_track_insert(Lib3dsLin3Track *track, Lib3dsLin3Key *key);
+extern LIB3DSAPI void lib3ds_lin3_track_remove(Lib3dsLin3Track *track, Lib3dsIntd frame);
+extern LIB3DSAPI void lib3ds_lin3_track_eval(Lib3dsLin3Track *track, Lib3dsVector p, Lib3dsFloat t);
+extern LIB3DSAPI Lib3dsBool lib3ds_lin3_track_read(Lib3dsLin3Track *track, Lib3dsIo *io);
+extern LIB3DSAPI Lib3dsBool lib3ds_lin3_track_write(Lib3dsLin3Track *track, Lib3dsIo *io);
+
+extern LIB3DSAPI Lib3dsQuatKey* lib3ds_quat_key_new();
+extern LIB3DSAPI void lib3ds_quat_key_free(Lib3dsQuatKey* key);
+extern LIB3DSAPI void lib3ds_quat_track_free_keys(Lib3dsQuatTrack *track);
+extern LIB3DSAPI void lib3ds_quat_key_setup(Lib3dsQuatKey *p, Lib3dsQuatKey *cp, Lib3dsQuatKey *c,
+  Lib3dsQuatKey *cn, Lib3dsQuatKey *n);
+extern LIB3DSAPI void lib3ds_quat_track_setup(Lib3dsQuatTrack *track);
+extern LIB3DSAPI void lib3ds_quat_track_insert(Lib3dsQuatTrack *track, Lib3dsQuatKey *key);
+extern LIB3DSAPI void lib3ds_quat_track_remove(Lib3dsQuatTrack *track, Lib3dsIntd frame);
+extern LIB3DSAPI void lib3ds_quat_track_eval(Lib3dsQuatTrack *track, Lib3dsQuat p, Lib3dsFloat t);
+extern LIB3DSAPI Lib3dsBool lib3ds_quat_track_read(Lib3dsQuatTrack *track, Lib3dsIo *io);
+extern LIB3DSAPI Lib3dsBool lib3ds_quat_track_write(Lib3dsQuatTrack *track, Lib3dsIo *io);
+
+extern LIB3DSAPI Lib3dsMorphKey* lib3ds_morph_key_new();
+extern LIB3DSAPI void lib3ds_morph_key_free(Lib3dsMorphKey* key);
+extern LIB3DSAPI void lib3ds_morph_track_free_keys(Lib3dsMorphTrack *track);
+extern LIB3DSAPI void lib3ds_morph_track_insert(Lib3dsMorphTrack *track, Lib3dsMorphKey *key);
+extern LIB3DSAPI void lib3ds_morph_track_remove(Lib3dsMorphTrack *track, Lib3dsIntd frame);
+extern LIB3DSAPI void lib3ds_morph_track_eval(Lib3dsMorphTrack *track, char *p, Lib3dsFloat t);
+extern LIB3DSAPI Lib3dsBool lib3ds_morph_track_read(Lib3dsMorphTrack *track, Lib3dsIo *io);
+extern LIB3DSAPI Lib3dsBool lib3ds_morph_track_write(Lib3dsMorphTrack *track, Lib3dsIo *io);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/src/3dengfx/libs/lib3ds/types.h b/src/3dengfx/libs/lib3ds/types.h
new file mode 100644 (file)
index 0000000..5b6f008
--- /dev/null
@@ -0,0 +1,148 @@
+/* -*- c -*- */
+#ifndef INCLUDED_LIB3DS_TYPES_H
+#define INCLUDED_LIB3DS_TYPES_H
+/*
+ * The 3D Studio File Format Library
+ * Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
+ * All rights reserved.
+ *
+ * This program is  free  software;  you can redistribute it and/or modify it
+ * under the terms of the  GNU Lesser General Public License  as published by 
+ * the  Free Software Foundation;  either version 2.1 of the License,  or (at 
+ * your option) any later version.
+ *
+ * This  program  is  distributed in  the  hope that it will  be useful,  but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public  
+ * License for more details.
+ *
+ * You should  have received  a copy of the GNU Lesser General Public License
+ * along with  this program;  if not, write to the  Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: types.h,v 1.18 2005/01/11 16:12:52 madmac Exp $
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined (UBUILD_SHARED) && defined(_WIN32) && (!defined(__GNUC__))
+#ifdef LIB3DS_EXPORT
+#define LIB3DSAPI __declspec(dllexport)
+#else               
+#define LIB3DSAPI __declspec(dllimport)
+#endif           
+#else
+#define LIB3DSAPI
+#endif
+
+#define LIB3DS_TRUE 1
+#define LIB3DS_FALSE 0
+
+typedef int Lib3dsBool;
+typedef unsigned char Lib3dsByte;
+typedef unsigned short int Lib3dsWord;
+typedef unsigned long Lib3dsDword;
+typedef signed char Lib3dsIntb;
+typedef signed short int Lib3dsIntw;
+typedef signed long Lib3dsIntd;
+typedef float Lib3dsFloat;
+typedef double Lib3dsDouble;
+
+typedef float Lib3dsVector[3];
+typedef float Lib3dsTexel[2];
+typedef float Lib3dsQuat[4];
+typedef float Lib3dsMatrix[4][4];
+typedef float Lib3dsRgb[3];
+typedef float Lib3dsRgba[4];
+
+#define LIB3DS_EPSILON (1e-8)
+#define LIB3DS_PI 3.14159265358979323846
+#define LIB3DS_TWOPI (2.0*LIB3DS_PI)
+#define LIB3DS_HALFPI (LIB3DS_PI/2.0)
+#define LIB3DS_RAD_TO_DEG(x) ((180.0/LIB3DS_PI)*(x))
+#define LIB3DS_DEG_TO_RAD(x) ((LIB3DS_PI/180.0)*(x))
+  
+#ifndef INCLUDED_STDIO_H
+#define INCLUDED_STDIO_H
+#include <stdio.h>
+#endif
+
+#ifdef _DEBUG
+  #ifndef ASSERT
+  #include <assert.h>
+  #define ASSERT(__expr) assert(__expr)
+  #endif
+  #define LIB3DS_ERROR_LOG \
+    {printf("\t***LIB3DS_ERROR_LOG*** %s : %d\n", __FILE__, __LINE__);}
+#else 
+  #ifndef ASSERT
+  #define ASSERT(__expr)
+  #endif
+  #define LIB3DS_ERROR_LOG
+#endif
+
+typedef struct _Lib3dsIo Lib3dsIo;
+typedef struct _Lib3dsFile Lib3dsFile;
+typedef struct _Lib3dsBackground Lib3dsBackground;
+typedef struct _Lib3dsAtmosphere Lib3dsAtmosphere;
+typedef struct _Lib3dsShadow Lib3dsShadow;
+typedef struct _Lib3dsViewport Lib3dsViewport;
+typedef struct _Lib3dsMaterial Lib3dsMaterial;
+typedef struct _Lib3dsFace Lib3dsFace; 
+typedef struct _Lib3dsBoxMap Lib3dsBoxMap; 
+typedef struct _Lib3dsMapData Lib3dsMapData; 
+typedef struct _Lib3dsMesh Lib3dsMesh;
+typedef struct _Lib3dsCamera Lib3dsCamera;
+typedef struct _Lib3dsLight Lib3dsLight;
+typedef struct _Lib3dsBoolKey Lib3dsBoolKey;
+typedef struct _Lib3dsBoolTrack Lib3dsBoolTrack;
+typedef struct _Lib3dsLin1Key Lib3dsLin1Key;
+typedef struct _Lib3dsLin1Track Lib3dsLin1Track;
+typedef struct _Lib3dsLin3Key Lib3dsLin3Key;
+typedef struct _Lib3dsLin3Track Lib3dsLin3Track;
+typedef struct _Lib3dsQuatKey Lib3dsQuatKey;
+typedef struct _Lib3dsQuatTrack Lib3dsQuatTrack;
+typedef struct _Lib3dsMorphKey Lib3dsMorphKey;
+typedef struct _Lib3dsMorphTrack Lib3dsMorphTrack;
+
+typedef enum _Lib3dsNodeTypes {
+  LIB3DS_UNKNOWN_NODE =0,
+  LIB3DS_AMBIENT_NODE =1,
+  LIB3DS_OBJECT_NODE  =2,
+  LIB3DS_CAMERA_NODE  =3,
+  LIB3DS_TARGET_NODE  =4,
+  LIB3DS_LIGHT_NODE   =5,
+  LIB3DS_SPOT_NODE    =6
+} Lib3dsNodeTypes;
+
+typedef struct _Lib3dsNode Lib3dsNode;
+
+typedef union _Lib3dsUserData {
+    void *p;
+    Lib3dsIntd i;
+    Lib3dsDword d;
+    Lib3dsFloat f;
+    Lib3dsMaterial *material;
+    Lib3dsMesh *mesh;
+    Lib3dsCamera *camera;
+    Lib3dsLight *light;
+    Lib3dsNode *node;
+} Lib3dsUserData;
+
+#ifndef        LIB3DS_EXPORT
+       /* The purpose of this variable is to force a recompile of any code
+        * that links to the lib3ds library whenever there is an incompatible
+        * change in the header files.  It should be sufficient to include
+        * any lib3ds header file in any source file to satisfy this dependency.
+        *
+        * This variable will be updated any time there is an incompatible change
+        * in the lib3ds data structures.
+        */
+//     int lib3ds_version1_3;
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/3dengfx/libs/lib3ds/vector.c b/src/3dengfx/libs/lib3ds/vector.c
new file mode 100644 (file)
index 0000000..32922d7
--- /dev/null
@@ -0,0 +1,377 @@
+/*
+ * The 3D Studio File Format Library
+ * Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
+ * All rights reserved.
+ *
+ * This program is  free  software;  you can redistribute it and/or modify it
+ * under the terms of the  GNU Lesser General Public License  as published by 
+ * the  Free Software Foundation;  either version 2.1 of the License,  or (at 
+ * your option) any later version.
+ *
+ * This  program  is  distributed in  the  hope that it will  be useful,  but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public  
+ * License for more details.
+ *
+ * You should  have received  a copy of the GNU Lesser General Public License
+ * along with  this program;  if not, write to the  Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: vector.c,v 1.9 2004/11/16 07:41:44 efalk Exp $
+ */
+#define LIB3DS_EXPORT
+#include <lib3ds/vector.h>
+#include <math.h>
+
+
+/*!
+ * \defgroup vector Vector Mathematics
+ *
+ * \author J.E. Hoffmann <je-h@gmx.net>
+ */
+/*!
+ * \typedef Lib3dsVector
+ *   \ingroup vector
+ */
+
+
+/*!
+ * Clear a vector to zero.
+ *
+ * \param c Vector to clear.
+ *
+ * \ingroup vector
+ */
+void
+lib3ds_vector_zero(Lib3dsVector c)
+{
+  int i;
+  for (i=0; i<3; ++i) {
+    c[i]=0.0f;
+  }
+}
+
+
+/*!
+ * Copy a vector.
+ *
+ * \param dest Destination vector.
+ * \param src Source vector.
+ *
+ * \ingroup vector
+ */
+void
+lib3ds_vector_copy(Lib3dsVector dest, Lib3dsVector src)
+{
+  int i;
+  for (i=0; i<3; ++i) {
+    dest[i]=src[i];
+  }
+}
+
+
+/*!
+ * Negate a vector.
+ *
+ * \param c Vector to negate.
+ *
+ * \ingroup vector
+ */
+void
+lib3ds_vector_neg(Lib3dsVector c)
+{
+  int i;
+  for (i=0; i<3; ++i) {
+    c[i]=-c[i];
+  }
+}
+
+
+/*!
+ * Add two vectors.
+ *
+ * \param c Result.
+ * \param a First addend.
+ * \param b Second addend.
+ *
+ * \ingroup vector
+ */
+void
+lib3ds_vector_add(Lib3dsVector c, Lib3dsVector a, Lib3dsVector b)
+{
+  int i;
+  for (i=0; i<3; ++i) {
+    c[i]=a[i]+b[i];
+  }
+}
+
+
+/*!
+ * Subtract two vectors.
+ *
+ * \param c Result.
+ * \param a Addend.
+ * \param b Minuend.
+ *
+ * \ingroup vector
+ */
+void
+lib3ds_vector_sub(Lib3dsVector c, Lib3dsVector a, Lib3dsVector b)
+{
+  int i;
+  for (i=0; i<3; ++i) {
+    c[i]=a[i]-b[i];
+  }
+}
+
+
+/*!
+ * Multiply a vector by a scalar.
+ *
+ * \param c Vector to be multiplied.
+ * \param k Scalar.
+ *
+ * \ingroup vector
+ */
+void
+lib3ds_vector_scalar(Lib3dsVector c, Lib3dsFloat k)
+{
+  int i;
+  for (i=0; i<3; ++i) {
+    c[i]*=k;
+  }
+}
+
+
+/*!
+ * Compute cross product.
+ *
+ * \param c Result.
+ * \param a First vector.
+ * \param b Second vector.
+ *
+ * \ingroup vector
+ */
+void
+lib3ds_vector_cross(Lib3dsVector c, Lib3dsVector a, Lib3dsVector b)
+{
+  c[0]=a[1]*b[2] - a[2]*b[1];
+  c[1]=a[2]*b[0] - a[0]*b[2];
+  c[2]=a[0]*b[1] - a[1]*b[0];
+}
+
+
+/*!
+ * Compute dot product.
+ *
+ * \param a First vector.
+ * \param b Second vector.
+ *
+ * \return Dot product.
+ *
+ * \ingroup vector
+ */
+Lib3dsFloat
+lib3ds_vector_dot(Lib3dsVector a, Lib3dsVector b)
+{
+  return(a[0]*b[0] + a[1]*b[1] + a[2]*b[2]);
+}
+
+
+/*!
+ * Compute square of vector.
+ *
+ * Computes x*x + y*y + z*z.
+ *
+ * \param c Vector to square.
+ *
+ * \return Square of vector.
+ *
+ * \ingroup vector
+ */
+Lib3dsFloat
+lib3ds_vector_squared(Lib3dsVector c)
+{
+  return(c[0]*c[0] + c[1]*c[1] + c[2]*c[2]);
+}
+
+
+/*!
+ * Compute length of vector.
+ *
+ * Computes |c| = sqrt(x*x + y*y + z*z)
+ *
+ * \param c Vector to compute.
+ *
+ * \return Length of vector.
+ *
+ * \ingroup vector
+ */
+Lib3dsFloat
+lib3ds_vector_length(Lib3dsVector c)
+{
+  return((Lib3dsFloat)sqrt(c[0]*c[0] + c[1]*c[1] + c[2]*c[2]));
+}
+
+
+/*!
+ * Normalize a vector.
+ *
+ * Scales a vector so that its length is 1.0.
+ *
+ * \param c Vector to normalize.
+ *
+ * \ingroup vector
+ */
+void
+lib3ds_vector_normalize(Lib3dsVector c)
+{
+  Lib3dsFloat l,m;
+
+  l=(Lib3dsFloat)sqrt(c[0]*c[0] + c[1]*c[1] + c[2]*c[2]);
+  if (fabs(l)<LIB3DS_EPSILON) {
+    if ((c[0]>=c[1]) && (c[0]>=c[2])) {
+      c[0]=1.0f;
+      c[1]=c[2]=0.0f;
+    }
+    else
+    if (c[1]>=c[2]) {
+      c[1]=1.0f;
+      c[0]=c[2]=0.0f;
+    }
+    else {
+      c[2]=1.0f;
+      c[0]=c[1]=0.0f;
+    }
+  }
+  else {
+    m=1.0f/l;
+    c[0]*=m;
+    c[1]*=m;
+    c[2]*=m;
+  }
+}
+
+
+/*!
+ * Compute a vector normal to two line segments.
+ *
+ * Computes the normal vector to the lines b-a and b-c.
+ *
+ * \param n Returned normal vector.
+ * \param a Endpoint of first line.
+ * \param b Base point of both lines.
+ * \param c Endpoint of second line.
+ *
+ * \ingroup vector
+ */
+void
+lib3ds_vector_normal(Lib3dsVector n, Lib3dsVector a, Lib3dsVector b, Lib3dsVector c)
+{
+  Lib3dsVector p,q;
+
+  lib3ds_vector_sub(p,c,b);
+  lib3ds_vector_sub(q,a,b);
+  lib3ds_vector_cross(n,p,q);
+  lib3ds_vector_normalize(n);
+}
+
+
+/*!
+ * Multiply a point by a transformation matrix.
+ *
+ * Applies the given transformation matrix to the given point.  With some
+ * transformation matrices, a vector may also be transformed.
+ *
+ * \param c Result.
+ * \param m Transformation matrix.
+ * \param a Input point.
+ *
+ * \ingroup vector
+ */
+void
+lib3ds_vector_transform(Lib3dsVector c, Lib3dsMatrix m, Lib3dsVector a)
+{
+  c[0]= m[0][0]*a[0] + m[1][0]*a[1] + m[2][0]*a[2] + m[3][0];
+  c[1]= m[0][1]*a[0] + m[1][1]*a[1] + m[2][1]*a[2] + m[3][1];
+  c[2]= m[0][2]*a[0] + m[1][2]*a[1] + m[2][2]*a[2] + m[3][2];
+}
+
+
+/*!
+ * Compute a point on a cubic spline.
+ *
+ * Computes a point on a parametric Bezier spline.
+ *
+ * \param c Result.
+ * \param a First endpoint of the spline.
+ * \param p First tangent vector of the spline.
+ * \param q Second tangent vector of the spline.
+ * \param b Second endpoint of the spline.
+ * \param t Spline parameter [0. 1.]
+ *
+ * \ingroup vector
+ */
+void
+lib3ds_vector_cubic(Lib3dsVector c, Lib3dsVector a, Lib3dsVector p, Lib3dsVector q,
+  Lib3dsVector b, Lib3dsFloat t)
+{
+  Lib3dsDouble x,y,z,w;   
+
+  x=2*t*t*t - 3*t*t + 1;
+  y=-2*t*t*t + 3*t*t;
+  z=t*t*t - 2*t*t + t;
+  w=t*t*t - t*t;
+  c[0]=(Lib3dsFloat)(x*a[0] + y*b[0] + z*p[0] + w*q[0]);
+  c[1]=(Lib3dsFloat)(x*a[1] + y*b[1] + z*p[1] + w*q[1]);
+  c[2]=(Lib3dsFloat)(x*a[2] + y*b[2] + z*p[2] + w*q[2]);
+}
+
+
+/*!
+ * c[i] = min(c[i], a[i]);
+ *
+ * Computes minimum values of x,y,z independently.
+ *
+ * \ingroup vector
+ */
+void 
+lib3ds_vector_min(Lib3dsVector c, Lib3dsVector a)
+{
+  int i;
+  for (i=0; i<3; ++i) {
+    if (a[i]<c[i]) {
+      c[i] = a[i];
+    }
+  }
+}
+
+
+/*!
+ * c[i] = max(c[i], a[i]);
+ *
+ * Computes maximum values of x,y,z independently.
+ *
+ * \ingroup vector
+ */
+void 
+lib3ds_vector_max(Lib3dsVector c, Lib3dsVector a)
+{
+  int i;
+  for (i=0; i<3; ++i) {
+    if (a[i]>c[i]) {
+      c[i] = a[i];
+    }
+  }
+}
+
+
+/*!
+ * \ingroup vector
+ */
+void
+lib3ds_vector_dump(Lib3dsVector c)
+{
+  fprintf(stderr, "%f %f %f\n", c[0], c[1], c[2]);
+}
+
diff --git a/src/3dengfx/libs/lib3ds/vector.h b/src/3dengfx/libs/lib3ds/vector.h
new file mode 100644 (file)
index 0000000..bc829b6
--- /dev/null
@@ -0,0 +1,58 @@
+/* -*- c -*- */
+#ifndef INCLUDED_LIB3DS_VECTOR_H
+#define INCLUDED_LIB3DS_VECTOR_H
+/*
+ * The 3D Studio File Format Library
+ * Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
+ * All rights reserved.
+ *
+ * This program is  free  software;  you can redistribute it and/or modify it
+ * under the terms of the  GNU Lesser General Public License  as published by 
+ * the  Free Software Foundation;  either version 2.1 of the License,  or (at 
+ * your option) any later version.
+ *
+ * This  program  is  distributed in  the  hope that it will  be useful,  but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public  
+ * License for more details.
+ *
+ * You should  have received  a copy of the GNU Lesser General Public License
+ * along with  this program;  if not, write to the  Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: vector.h,v 1.6 2004/12/31 16:17:15 reed Exp $
+ */
+
+#ifndef INCLUDED_LIB3DS_TYPES_H
+#include <lib3ds/types.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern LIB3DSAPI void lib3ds_vector_zero(Lib3dsVector c);
+extern LIB3DSAPI void lib3ds_vector_copy(Lib3dsVector dest, Lib3dsVector src);
+extern LIB3DSAPI void lib3ds_vector_neg(Lib3dsVector c);
+extern LIB3DSAPI void lib3ds_vector_add(Lib3dsVector c, Lib3dsVector a, Lib3dsVector b);
+extern LIB3DSAPI void lib3ds_vector_sub(Lib3dsVector c, Lib3dsVector a, Lib3dsVector b);
+extern LIB3DSAPI void lib3ds_vector_scalar(Lib3dsVector c, Lib3dsFloat k);
+extern LIB3DSAPI void lib3ds_vector_cross(Lib3dsVector c, Lib3dsVector a, Lib3dsVector b);
+extern LIB3DSAPI Lib3dsFloat lib3ds_vector_dot(Lib3dsVector a, Lib3dsVector b);
+extern LIB3DSAPI Lib3dsFloat lib3ds_vector_squared(Lib3dsVector c);
+extern LIB3DSAPI Lib3dsFloat lib3ds_vector_length(Lib3dsVector c);
+extern LIB3DSAPI void lib3ds_vector_normalize(Lib3dsVector c);
+extern LIB3DSAPI void lib3ds_vector_normal(Lib3dsVector n, Lib3dsVector a,
+  Lib3dsVector b, Lib3dsVector c);
+extern LIB3DSAPI void lib3ds_vector_transform(Lib3dsVector c, Lib3dsMatrix m, Lib3dsVector a);
+extern LIB3DSAPI void lib3ds_vector_cubic(Lib3dsVector c, Lib3dsVector a, Lib3dsVector p,
+  Lib3dsVector q, Lib3dsVector b, Lib3dsFloat t);
+extern LIB3DSAPI void lib3ds_vector_min(Lib3dsVector c, Lib3dsVector a);
+extern LIB3DSAPI void lib3ds_vector_max(Lib3dsVector c, Lib3dsVector a);
+extern LIB3DSAPI void lib3ds_vector_dump(Lib3dsVector c);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/src/3dengfx/libs/lib3ds/viewport.c b/src/3dengfx/libs/lib3ds/viewport.c
new file mode 100644 (file)
index 0000000..9a5a45b
--- /dev/null
@@ -0,0 +1,424 @@
+/*
+ * The 3D Studio File Format Library
+ * Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
+ * All rights reserved.
+ *
+ * This program is  free  software;  you can redistribute it and/or modify it
+ * under the terms of the  GNU Lesser General Public License  as published by 
+ * the  Free Software Foundation;  either version 2.1 of the License,  or (at 
+ * your option) any later version.
+ *
+ * This  program  is  distributed in  the  hope that it will  be useful,  but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public  
+ * License for more details.
+ *
+ * You should  have received  a copy of the GNU Lesser General Public License
+ * along with  this program;  if not, write to the  Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: viewport.c,v 1.7 2004/11/16 07:40:56 efalk Exp $
+ */
+#define LIB3DS_EXPORT
+#include <lib3ds/viewport.h>
+#include <lib3ds/chunk.h>
+#include <lib3ds/io.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+/*!
+ * \defgroup viewport Viewport and default view settings
+ *
+ * \author J.E. Hoffmann <je-h@gmx.net>
+ */
+
+
+/*!
+ * \ingroup viewport 
+ */
+Lib3dsBool
+lib3ds_viewport_read(Lib3dsViewport *viewport, Lib3dsIo *io)
+{
+  Lib3dsChunk c;
+  Lib3dsWord chunk;
+
+  if (!lib3ds_chunk_read_start(&c, 0, io)) {
+    return(LIB3DS_FALSE);
+  }
+  
+  switch (c.chunk) {
+    case LIB3DS_VIEWPORT_LAYOUT:
+      {
+        int cur=0;
+        viewport->layout.style=lib3ds_io_read_word(io);
+        viewport->layout.active=lib3ds_io_read_intw(io);
+        lib3ds_io_read_intw(io);
+        viewport->layout.swap=lib3ds_io_read_intw(io);
+        lib3ds_io_read_intw(io);
+        viewport->layout.swap_prior=lib3ds_io_read_intw(io);
+        viewport->layout.swap_view=lib3ds_io_read_intw(io);
+        lib3ds_chunk_read_tell(&c, io);
+        while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) {
+          switch (chunk) {
+            case LIB3DS_VIEWPORT_SIZE:
+              {
+                viewport->layout.position[0]=lib3ds_io_read_word(io);
+                viewport->layout.position[1]=lib3ds_io_read_word(io);
+                viewport->layout.size[0]=lib3ds_io_read_word(io);
+                viewport->layout.size[1]=lib3ds_io_read_word(io);
+              }
+              break;
+            case LIB3DS_VIEWPORT_DATA_3:
+              {
+                lib3ds_viewport_set_views(viewport,cur+1);
+                lib3ds_io_read_intw(io);
+                viewport->layout.viewL[cur].axis_lock=lib3ds_io_read_word(io);
+                viewport->layout.viewL[cur].position[0]=lib3ds_io_read_intw(io);
+                viewport->layout.viewL[cur].position[1]=lib3ds_io_read_intw(io);
+                viewport->layout.viewL[cur].size[0]=lib3ds_io_read_intw(io);
+                viewport->layout.viewL[cur].size[1]=lib3ds_io_read_intw(io);
+                viewport->layout.viewL[cur].type=lib3ds_io_read_word(io);
+                viewport->layout.viewL[cur].zoom=lib3ds_io_read_float(io);
+                lib3ds_io_read_vector(io, viewport->layout.viewL[cur].center);
+                viewport->layout.viewL[cur].horiz_angle=lib3ds_io_read_float(io);
+                viewport->layout.viewL[cur].vert_angle=lib3ds_io_read_float(io);
+                lib3ds_io_read(io, (unsigned char*)viewport->layout.viewL[cur].camera, 11);
+                ++cur;
+              }
+              break;
+            case LIB3DS_VIEWPORT_DATA:
+              /* 3DS R2 & R3 chunk
+                 unsupported */
+              break;
+            default:
+              lib3ds_chunk_unknown(chunk);
+          }
+        }
+      }
+      break;
+    case LIB3DS_DEFAULT_VIEW:
+      {
+        memset(&viewport->default_view,0,sizeof(Lib3dsDefaultView));
+        while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) {
+          switch (chunk) {
+            case LIB3DS_VIEW_TOP:
+              {
+                viewport->default_view.type=LIB3DS_VIEW_TYPE_TOP;
+                lib3ds_io_read_vector(io, viewport->default_view.position);
+                viewport->default_view.width=lib3ds_io_read_float(io);
+              }
+              break;
+            case LIB3DS_VIEW_BOTTOM:
+              {
+                viewport->default_view.type=LIB3DS_VIEW_TYPE_BOTTOM;
+                lib3ds_io_read_vector(io, viewport->default_view.position);
+                viewport->default_view.width=lib3ds_io_read_float(io);
+              }
+              break;
+            case LIB3DS_VIEW_LEFT:
+              {
+                viewport->default_view.type=LIB3DS_VIEW_TYPE_LEFT;
+                lib3ds_io_read_vector(io, viewport->default_view.position);
+                viewport->default_view.width=lib3ds_io_read_float(io);
+              }
+              break;
+            case LIB3DS_VIEW_RIGHT:
+              {
+                viewport->default_view.type=LIB3DS_VIEW_TYPE_RIGHT;
+                lib3ds_io_read_vector(io, viewport->default_view.position);
+                viewport->default_view.width=lib3ds_io_read_float(io);
+              }
+              break;
+            case LIB3DS_VIEW_FRONT:
+              {
+                viewport->default_view.type=LIB3DS_VIEW_TYPE_FRONT;
+                lib3ds_io_read_vector(io, viewport->default_view.position);
+                viewport->default_view.width=lib3ds_io_read_float(io);
+              }
+              break;
+            case LIB3DS_VIEW_BACK:
+              {
+                viewport->default_view.type=LIB3DS_VIEW_TYPE_BACK;
+                lib3ds_io_read_vector(io, viewport->default_view.position);
+                viewport->default_view.width=lib3ds_io_read_float(io);
+              }
+              break;
+            case LIB3DS_VIEW_USER:
+              {
+                viewport->default_view.type=LIB3DS_VIEW_TYPE_USER;
+                lib3ds_io_read_vector(io, viewport->default_view.position);
+                viewport->default_view.width=lib3ds_io_read_float(io);
+                viewport->default_view.horiz_angle=lib3ds_io_read_float(io);
+                viewport->default_view.vert_angle=lib3ds_io_read_float(io);
+                viewport->default_view.roll_angle=lib3ds_io_read_float(io);
+              }
+              break;
+            case LIB3DS_VIEW_CAMERA:
+              {
+                viewport->default_view.type=LIB3DS_VIEW_TYPE_CAMERA;
+                lib3ds_io_read(io, (unsigned char*)viewport->default_view.camera, 11);
+              }
+              break;
+            default:
+              lib3ds_chunk_unknown(chunk);
+          }
+        }
+      }
+      break;
+  }
+
+  lib3ds_chunk_read_end(&c, io);
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+ * \ingroup viewport 
+ */
+void
+lib3ds_viewport_set_views(Lib3dsViewport *viewport, Lib3dsDword views)
+{
+  ASSERT(viewport);
+  if (viewport->layout.views) {
+    if (views) {
+      viewport->layout.views=views;
+      viewport->layout.viewL=(Lib3dsView*)realloc(viewport->layout.viewL, sizeof(Lib3dsView)*views);
+    }
+    else {
+      free(viewport->layout.viewL);
+      viewport->layout.views=0;
+      viewport->layout.viewL=0;
+    }
+  }
+  else {
+    if (views) {
+      viewport->layout.views=views;
+      viewport->layout.viewL=(Lib3dsView*)calloc(sizeof(Lib3dsView),views);
+    }
+  }
+}
+
+
+/*!
+ * \ingroup viewport 
+ */
+Lib3dsBool
+lib3ds_viewport_write(Lib3dsViewport *viewport, Lib3dsIo *io)
+{
+  if (viewport->layout.views) {
+    Lib3dsChunk c;
+    unsigned i;
+
+    c.chunk=LIB3DS_VIEWPORT_LAYOUT;
+    if (!lib3ds_chunk_write_start(&c,io)) {
+      return(LIB3DS_FALSE);
+    }
+
+    lib3ds_io_write_word(io, viewport->layout.style);
+    lib3ds_io_write_intw(io, viewport->layout.active);
+    lib3ds_io_write_intw(io, 0);
+    lib3ds_io_write_intw(io, viewport->layout.swap);
+    lib3ds_io_write_intw(io, 0);
+    lib3ds_io_write_intw(io, viewport->layout.swap_prior);
+    lib3ds_io_write_intw(io, viewport->layout.swap_view);
+    
+    {
+      Lib3dsChunk c;
+      c.chunk=LIB3DS_VIEWPORT_SIZE;
+      c.size=14;
+      lib3ds_chunk_write(&c,io);
+      lib3ds_io_write_intw(io, viewport->layout.position[0]);
+      lib3ds_io_write_intw(io, viewport->layout.position[1]);
+      lib3ds_io_write_intw(io, viewport->layout.size[0]);
+      lib3ds_io_write_intw(io, viewport->layout.size[1]);
+    }
+
+    for (i=0; i<viewport->layout.views; ++i) {
+      Lib3dsChunk c;
+      c.chunk=LIB3DS_VIEWPORT_DATA_3;
+      c.size=55;
+      lib3ds_chunk_write(&c,io);
+
+      lib3ds_io_write_intw(io, 0);
+      lib3ds_io_write_word(io, viewport->layout.viewL[i].axis_lock);
+      lib3ds_io_write_intw(io, viewport->layout.viewL[i].position[0]);
+      lib3ds_io_write_intw(io, viewport->layout.viewL[i].position[1]);
+      lib3ds_io_write_intw(io, viewport->layout.viewL[i].size[0]);
+      lib3ds_io_write_intw(io, viewport->layout.viewL[i].size[1]);
+      lib3ds_io_write_word(io, viewport->layout.viewL[i].type);
+      lib3ds_io_write_float(io, viewport->layout.viewL[i].zoom);
+      lib3ds_io_write_vector(io, viewport->layout.viewL[i].center);
+      lib3ds_io_write_float(io, viewport->layout.viewL[i].horiz_angle);
+      lib3ds_io_write_float(io, viewport->layout.viewL[i].vert_angle);
+      lib3ds_io_write(io, (unsigned char*)viewport->layout.viewL[i].camera,11);
+    }
+
+    if (!lib3ds_chunk_write_end(&c,io)) {
+      return(LIB3DS_FALSE);
+    }
+  }
+
+  if (viewport->default_view.type) {
+    Lib3dsChunk c;
+
+    c.chunk=LIB3DS_DEFAULT_VIEW;
+    if (!lib3ds_chunk_write_start(&c,io)) {
+      return(LIB3DS_FALSE);
+    }
+
+    switch (viewport->default_view.type) {
+      case LIB3DS_VIEW_TYPE_TOP:
+        {
+          Lib3dsChunk c;
+          c.chunk=LIB3DS_VIEW_TOP;
+          c.size=22;
+          lib3ds_chunk_write(&c,io);
+          lib3ds_io_write_vector(io, viewport->default_view.position);
+          lib3ds_io_write_float(io, viewport->default_view.width);
+        }
+        break;
+      case LIB3DS_VIEW_TYPE_BOTTOM:
+        {
+          Lib3dsChunk c;
+          c.chunk=LIB3DS_VIEW_BOTTOM;
+          c.size=22;
+          lib3ds_chunk_write(&c,io);
+          lib3ds_io_write_vector(io, viewport->default_view.position);
+          lib3ds_io_write_float(io, viewport->default_view.width);
+        }
+        break;
+      case LIB3DS_VIEW_TYPE_LEFT:
+        {
+          Lib3dsChunk c;
+          c.chunk=LIB3DS_VIEW_LEFT;
+          c.size=22;
+          lib3ds_chunk_write(&c,io);
+          lib3ds_io_write_vector(io, viewport->default_view.position);
+          lib3ds_io_write_float(io, viewport->default_view.width);
+        }
+        break;
+      case LIB3DS_VIEW_TYPE_RIGHT:
+        {
+          Lib3dsChunk c;
+          c.chunk=LIB3DS_VIEW_RIGHT;
+          c.size=22;
+          lib3ds_chunk_write(&c,io);
+          lib3ds_io_write_vector(io, viewport->default_view.position);
+          lib3ds_io_write_float(io, viewport->default_view.width);
+        }
+        break;
+      case LIB3DS_VIEW_TYPE_FRONT:
+        {
+          Lib3dsChunk c;
+          c.chunk=LIB3DS_VIEW_FRONT;
+          c.size=22;
+          lib3ds_chunk_write(&c,io);
+          lib3ds_io_write_vector(io, viewport->default_view.position);
+          lib3ds_io_write_float(io, viewport->default_view.width);
+        }
+        break;
+      case LIB3DS_VIEW_TYPE_BACK:
+        {
+          Lib3dsChunk c;
+          c.chunk=LIB3DS_VIEW_BACK;
+          c.size=22;
+          lib3ds_chunk_write(&c,io);
+          lib3ds_io_write_vector(io, viewport->default_view.position);
+          lib3ds_io_write_float(io, viewport->default_view.width);
+        }
+        break;
+      case LIB3DS_VIEW_TYPE_USER:
+        {
+          Lib3dsChunk c;
+          c.chunk=LIB3DS_VIEW_USER;
+          c.size=34;
+          lib3ds_chunk_write(&c,io);
+          lib3ds_io_write_vector(io, viewport->default_view.position);
+          lib3ds_io_write_float(io, viewport->default_view.width);
+          lib3ds_io_write_float(io, viewport->default_view.horiz_angle);
+          lib3ds_io_write_float(io, viewport->default_view.vert_angle);
+          lib3ds_io_write_float(io, viewport->default_view.roll_angle);
+        }
+        break;
+      case LIB3DS_VIEW_TYPE_CAMERA:
+        {
+          Lib3dsChunk c;
+          c.chunk=LIB3DS_VIEW_CAMERA;
+          c.size=17;
+          lib3ds_chunk_write(&c, io);
+          lib3ds_io_write(io, (unsigned char*)viewport->default_view.camera, 11);
+        }
+        break;
+    }
+
+    if (!lib3ds_chunk_write_end(&c, io)) {
+      return(LIB3DS_FALSE);
+    }
+  }
+  return(LIB3DS_TRUE);
+}
+
+
+/*!
+ * Dump viewport.
+ *
+ * \param viewport The viewport to be dumped.
+ *
+ * \ingroup node
+ */
+void
+lib3ds_viewport_dump(Lib3dsViewport *vp)
+{
+  Lib3dsView   *view;
+  int          i;
+  ASSERT(vp);
+
+  printf("  viewport:\n");
+  printf("    layout:\n");
+  printf("      style:       %d\n", vp->layout.style);
+  printf("      active:      %d\n", vp->layout.active);
+  printf("      swap:        %d\n", vp->layout.swap);
+  printf("      swap_prior:  %d\n", vp->layout.swap_prior);
+  printf("      position:    %d,%d\n",
+       vp->layout.position[0], vp->layout.position[1]);
+  printf("      size:        %d,%d\n", vp->layout.size[0], vp->layout.size[1]);
+  printf("      views:       %ld\n", vp->layout.views);
+  if (vp->layout.views > 0 && vp->layout.viewL != NULL) {
+    for(i=0, view=vp->layout.viewL; i < vp->layout.views; ++i, ++view) {
+      printf("        view %d:\n", i);
+      printf("          type:         %d\n", view->type);
+      printf("          axis_lock:    %d\n", view->axis_lock);
+      printf("          position:     (%d,%d)\n",
+        view->position[0], view->position[1]);
+      printf("          size:         (%d,%d)\n", view->size[0], view->size[1]);
+      printf("          zoom:         %g\n", view->zoom);
+      printf("          center:       (%g,%g,%g)\n",
+        view->center[0], view->center[1], view->center[2]);
+      printf("          horiz_angle:  %g\n", view->horiz_angle);
+      printf("          vert_angle:   %g\n", view->vert_angle);
+      printf("          camera:       %s\n", view->camera);
+    }
+  }
+
+  printf("    default_view:\n");
+  printf("     type:         %d\n", vp->default_view.type);
+  printf("     position:     (%g,%g,%g)\n",
+    vp->default_view.position[0],
+    vp->default_view.position[1],
+    vp->default_view.position[2]);
+  printf("     width:        %g\n", vp->default_view.width);
+  printf("     horiz_angle:  %g\n", vp->default_view.horiz_angle);
+  printf("     vert_angle:   %g\n", vp->default_view.vert_angle);
+  printf("     roll_angle:   %g\n", vp->default_view.roll_angle);
+  printf("     camera:       %s\n", vp->default_view.camera);
+}
+
+
+/*!
+
+\typedef Lib3dsViewport
+  \ingroup viewport
+  \sa _Lib3dsViewport
+
+*/
diff --git a/src/3dengfx/libs/lib3ds/viewport.h b/src/3dengfx/libs/lib3ds/viewport.h
new file mode 100644 (file)
index 0000000..e9981c6
--- /dev/null
@@ -0,0 +1,137 @@
+/* -*- c -*- */
+#ifndef INCLUDED_LIB3DS_VIEWPORT_H
+#define INCLUDED_LIB3DS_VIEWPORT_H
+/*
+ * The 3D Studio File Format Library
+ * Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
+ * All rights reserved.
+ *
+ * This program is  free  software;  you can redistribute it and/or modify it
+ * under the terms of the  GNU Lesser General Public License  as published by 
+ * the  Free Software Foundation;  either version 2.1 of the License,  or (at 
+ * your option) any later version.
+ *
+ * This  program  is  distributed in  the  hope that it will  be useful,  but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public  
+ * License for more details.
+ *
+ * You should  have received  a copy of the GNU Lesser General Public License
+ * along with  this program;  if not, write to the  Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: viewport.h,v 1.6 2004/12/31 16:17:15 reed Exp $
+ */
+
+#ifndef INCLUDED_LIB3DS_TYPES_H
+#include <lib3ds/types.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*!
+ * Layout view types
+ * \ingroup viewport
+ */
+typedef enum _Lib3dsViewType {
+  LIB3DS_VIEW_TYPE_NOT_USED  =0,
+  LIB3DS_VIEW_TYPE_TOP       =1,
+  LIB3DS_VIEW_TYPE_BOTTOM    =2,
+  LIB3DS_VIEW_TYPE_LEFT      =3,
+  LIB3DS_VIEW_TYPE_RIGHT     =4,
+  LIB3DS_VIEW_TYPE_FRONT     =5,
+  LIB3DS_VIEW_TYPE_BACK      =6,
+  LIB3DS_VIEW_TYPE_USER      =7,
+  LIB3DS_VIEW_TYPE_SPOTLIGHT =18,
+  LIB3DS_VIEW_TYPE_CAMERA    =65535
+} Lib3dsViewType;
+
+/*!
+ * Layout view settings
+ * \ingroup viewport
+ */
+typedef struct _Lib3dsView {
+    Lib3dsWord type;
+    Lib3dsWord axis_lock;
+    Lib3dsIntw position[2];
+    Lib3dsIntw size[2];
+    Lib3dsFloat zoom;
+    Lib3dsVector center;
+    Lib3dsFloat horiz_angle;
+    Lib3dsFloat vert_angle;
+    char camera[11];
+} Lib3dsView;
+
+/*!
+ * Layout styles
+ * \ingroup viewport
+ */
+typedef enum _Lib3dsLayoutStyle {
+  LIB3DS_LAYOUT_SINGLE                  =0,
+  LIB3DS_LAYOUT_TWO_PANE_VERT_SPLIT     =1,
+  LIB3DS_LAYOUT_TWO_PANE_HORIZ_SPLIT    =2,
+  LIB3DS_LAYOUT_FOUR_PANE               =3,
+  LIB3DS_LAYOUT_THREE_PANE_LEFT_SPLIT   =4,
+  LIB3DS_LAYOUT_THREE_PANE_BOTTOM_SPLIT =5,
+  LIB3DS_LAYOUT_THREE_PANE_RIGHT_SPLIT  =6,
+  LIB3DS_LAYOUT_THREE_PANE_TOP_SPLIT    =7,
+  LIB3DS_LAYOUT_THREE_PANE_VERT_SPLIT   =8,
+  LIB3DS_LAYOUT_THREE_PANE_HORIZ_SPLIT  =9,
+  LIB3DS_LAYOUT_FOUR_PANE_LEFT_SPLIT    =10,
+  LIB3DS_LAYOUT_FOUR_PANE_RIGHT_SPLIT   =11
+} Lib3dsLayoutStyle;
+
+/*!
+ * Viewport layout settings
+ * \ingroup viewport
+ */
+typedef struct _Lib3dsLayout {
+    Lib3dsWord style;
+    Lib3dsIntw active;
+    Lib3dsIntw swap;
+    Lib3dsIntw swap_prior;
+    Lib3dsIntw swap_view;
+    Lib3dsWord position[2];
+    Lib3dsWord size[2];
+    Lib3dsDword views;
+    Lib3dsView *viewL;
+} Lib3dsLayout;
+
+/*!
+ * Default view settings
+ * \ingroup viewport
+ */
+typedef struct _Lib3dsDefaultView {
+    Lib3dsWord type;
+    Lib3dsVector position;
+    Lib3dsFloat width;
+    Lib3dsFloat horiz_angle;
+    Lib3dsFloat vert_angle;
+    Lib3dsFloat roll_angle;
+    char camera[64];
+} Lib3dsDefaultView;
+
+/*!
+ * Viewport and default view settings
+ * \ingroup viewport
+ */
+struct _Lib3dsViewport {
+    Lib3dsLayout layout;
+    Lib3dsDefaultView default_view;
+};
+
+extern LIB3DSAPI Lib3dsBool lib3ds_viewport_read(Lib3dsViewport *viewport, Lib3dsIo *io);
+extern LIB3DSAPI void lib3ds_viewport_set_views(Lib3dsViewport *viewport, Lib3dsDword views);
+extern LIB3DSAPI Lib3dsBool lib3ds_viewport_write(Lib3dsViewport *viewport, Lib3dsIo *io);
+extern LIB3DSAPI void lib3ds_viewport_dump(Lib3dsViewport *viewport);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+
+
+
diff --git a/src/3dengfx/src/3dengfx/3dengfx.hpp b/src/3dengfx/src/3dengfx/3dengfx.hpp
new file mode 100644 (file)
index 0000000..09aa084
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+This file is part of the 3dengfx, realtime visualization system.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#ifndef _3DENGFX_HPP_
+#define _3DENGFX_HPP_
+
+#include "../3dengfx_config.h"
+#include "3denginefx.hpp"
+#include "camera.hpp"
+#include "ggen.hpp"
+#include "light.hpp"
+#include "material.hpp"
+#include "object.hpp"
+#include "rend_curve.hpp"
+#include "texman.hpp"
+#include "textures.hpp"
+#include "sceneloader.hpp"
+#include "gfxprog.hpp"
+#include "sdrman.hpp"
+#include "psys.hpp"
+#include "scfield.hpp"
+#include "fxwt/fxwt.hpp"
+#include "common/timer.h"
+#include "common/locator.h"
+#include "dsys/demosys.hpp"
+
+#endif // _3DENGFX_HPP_
diff --git a/src/3dengfx/src/3dengfx/3denginefx.cpp b/src/3dengfx/src/3dengfx/3denginefx.cpp
new file mode 100644 (file)
index 0000000..899031c
--- /dev/null
@@ -0,0 +1,1272 @@
+/*
+This file is part of the 3dengfx, realtime visualization system.
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+3dengfx is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+3dengfx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with 3dengfx; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* main 3dengfx state control, and low level OpenGL interaction
+ *
+ * Author: John Tsiombikas 2004
+ */
+
+#include "3dengfx_config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <iostream>
+#include <list>
+#include "opengl.h"
+#include "fxwt/fxwt.hpp"
+#include "fxwt/init.hpp"
+#include "fxwt/gfx_library.h"
+#include "3denginefx.hpp"
+#include "texman.hpp"
+#include "sdrman.hpp"
+#include "camera.hpp"
+#include "gfx/3dgeom.hpp"
+#include "gfxprog.hpp"
+#include "gfx/image.h"
+#include "common/config_parser.h"
+#include "common/err_msg.h"
+#include "dsys/dsys.hpp"
+
+using std::cout;
+using std::cerr;
+using std::endl;
+using std::string;
+
+#ifdef SINGLE_PRECISION_MATH
+#define GL_SCALAR_TYPE GL_FLOAT
+#else
+#define GL_SCALAR_TYPE GL_DOUBLE
+#endif // SINGLE_PRECISION_MATH
+
+
+void (*load_matrix_gl)(const Matrix4x4 &mat);
+
+namespace glext {
+#ifdef SINGLE_PRECISION_MATH
+       PFNGLLOADTRANSPOSEMATRIXFARBPROC glLoadTransposeMatrix;
+#else
+       PFNGLLOADTRANSPOSEMATRIXDARBPROC glLoadTransposeMatrix;
+#endif // SINGLE_PRECISION_MATH
+
+       PFNGLACTIVETEXTUREARBPROC glActiveTexture;
+       PFNGLCLIENTACTIVETEXTUREARBPROC glClientActiveTexture;
+
+       PFNGLBINDBUFFERARBPROC glBindBuffer;
+       PFNGLBUFFERDATAARBPROC glBufferData;
+       PFNGLDELETEBUFFERSARBPROC glDeleteBuffers;
+       PFNGLISBUFFERARBPROC glIsBuffer;
+       PFNGLMAPBUFFERARBPROC glMapBuffer;
+       PFNGLUNMAPBUFFERARBPROC glUnmapBuffer;
+       PFNGLGENBUFFERSARBPROC glGenBuffers;
+
+       // fragment/vertex program extensions
+       PFNGLBINDPROGRAMARBPROC glBindProgram;
+       PFNGLGENPROGRAMSARBPROC glGenPrograms;
+       PFNGLDELETEPROGRAMSARBPROC glDeletePrograms;
+       PFNGLPROGRAMSTRINGARBPROC glProgramString;
+
+       // point parameters
+       PFNGLPOINTPARAMETERFARBPROC glPointParameterf;
+       PFNGLPOINTPARAMETERFVARBPROC glPointParameterfv;
+
+       // --- OpenGL 2.0 Shading Language ---
+       
+       // - objects
+       PFNGLDELETEOBJECTARBPROC glDeleteObject;
+       PFNGLATTACHOBJECTARBPROC glAttachObject;
+       PFNGLDETACHOBJECTARBPROC glDetachObject;
+       PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameteriv;
+       PFNGLGETINFOLOGARBPROC glGetInfoLog;
+
+       // - program objects
+       PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObject;
+       PFNGLLINKPROGRAMARBPROC glLinkProgram;
+       PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObject;
+
+       // - shader objects
+       PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObject;
+       PFNGLSHADERSOURCEARBPROC glShaderSource;
+       PFNGLCOMPILESHADERARBPROC glCompileShader;
+
+       // - uniforms
+       PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocation;
+       PFNGLGETACTIVEUNIFORMARBPROC glGetActiveUniform;
+       PFNGLUNIFORM1IARBPROC glUniform1i;
+       PFNGLUNIFORM1FARBPROC glUniform1f;
+       PFNGLUNIFORM2FARBPROC glUniform2f;
+       PFNGLUNIFORM3FARBPROC glUniform3f;
+       PFNGLUNIFORM4FARBPROC glUniform4f;
+       PFNGLUNIFORMMATRIX3FVARBPROC glUniformMatrix3fv;
+       PFNGLUNIFORMMATRIX4FVARBPROC glUniformMatrix4fv;
+}
+
+using namespace glext;
+
+static const char *gl_error_string[] = {
+       "GL_INVALID_ENUM",              // 0x500
+       "GL_INVALID_VALUE",             // 0x501
+       "GL_INVALID_OPERATION", // 0x502
+       "GL_STACK_OVERFLOW",    // 0x503
+       "GL_STACK_UNDERFLOW",   // 0x504
+       "GL_OUT_OF_MEMORY",             // 0x505
+       "GL_NO_ERROR",                  // 0x0
+       "[INVALID ERROR NUMBER]"
+};
+
+///////////////// local 3d engine state block ///////////////////
+static bool gc_valid;
+static GraphicsInitParameters gparams;
+static Matrix4x4 tex_matrix[8];
+static int coord_index[MAX_TEXTURES];
+static PrimitiveType primitive_type;
+static StencilOp stencil_fail, stencil_pass, stencil_pzfail;
+static int stencil_ref;
+static bool mipmapping = true;
+static TextureDim ttype[8];    // the type of each texture bound to each texunit (1D/2D/3D/CUBE)
+
+namespace engfx_state {
+       SysCaps sys_caps;
+       Matrix4x4 world_matrix;
+       Matrix4x4 view_matrix, inv_view_matrix;
+       const Camera *view_mat_camera;
+       Matrix4x4 proj_matrix;
+       const Light *bump_light;
+       int light_count;
+}
+
+using namespace engfx_state;
+
+GraphicsInitParameters *load_graphics_context_config(const char *fname) {
+       static GraphicsInitParameters gip;      
+       gip.x = 640;
+       gip.y = 480;
+       gip.bpp = 16;
+       gip.depth_bits = 16;
+       gip.stencil_bits = 8;
+       gip.dont_care_flags = 0;
+
+       if(load_config_file(fname) == -1) {
+               error("%s: could not load config file", __func__);
+               return 0;
+       }
+       
+       const ConfigOption *cfgopt;
+       while((cfgopt = get_next_option())) {
+               
+               if(!strcmp(cfgopt->option, "fullscreen")) {
+                       if(!strcmp(cfgopt->str_value, "true")) {
+                               gip.fullscreen = true;
+                       } else if(!strcmp(cfgopt->str_value, "false")) {
+                               gip.fullscreen = false;
+                       } else {
+                               error("%s: error parsing config file %s", __func__, fname);
+                               return 0;
+                       }
+               } else if(!strcmp(cfgopt->option, "resolution")) {
+                       if(!isdigit(cfgopt->str_value[0])) {
+                               error("%s: error parsing config file %s", __func__, fname);
+                               return 0;
+                       }
+                       gip.x = atoi(cfgopt->str_value);
+                       
+                       char *ptr = cfgopt->str_value;
+                       while(*ptr && *ptr != 'x') *ptr++;
+                       if(!*ptr || !*(ptr+1) || !isdigit(*(ptr+1))) {
+                               error("%s: error parsing config file %s", __func__, fname);
+                               return 0;
+                       }
+                       
+                       gip.y = atoi(ptr + 1);
+               } else if(!strcmp(cfgopt->option, "bpp")) {
+                       if(cfgopt->flags & CFGOPT_INT) {
+                               gip.bpp = cfgopt->int_value;
+                       } else if(!strcmp(cfgopt->str_value, "dontcare")) {
+                               gip.bpp = 32;
+                               gip.dont_care_flags |= DONT_CARE_BPP;
+                       } else {
+                               error("%s: error parsing config file %s", __func__, fname);
+                               return 0;
+                       }                       
+               } else if(!strcmp(cfgopt->option, "zbuffer")) {
+                       if(cfgopt->flags & CFGOPT_INT) {
+                               gip.depth_bits = cfgopt->int_value;
+                       } else if(!strcmp(cfgopt->str_value, "dontcare")) {
+                               gip.depth_bits = 32;
+                               gip.dont_care_flags |= DONT_CARE_DEPTH;
+                       } else {
+                               error("%s: error parsing config file %s", __func__, fname);
+                               return 0;
+                       }
+               } else if(!strcmp(cfgopt->option, "stencil")) {
+                       if(cfgopt->flags & CFGOPT_INT) {
+                               gip.stencil_bits = cfgopt->int_value;
+                       } else if(!strcmp(cfgopt->str_value, "dontcare")) {
+                               gip.stencil_bits = 8;
+                               gip.dont_care_flags |= DONT_CARE_STENCIL;
+                       } else {
+                               error("%s: error parsing config file %s", __func__, fname);
+                               return 0;
+                       }
+               }
+       }
+       
+       destroy_config_parser();
+       
+       return &gip;            
+}
+
+/* ---- get_system_capabilities() ----
+ * Retrieves information on the graphics subsystem capabilities
+ * and returns a SysCaps structure describing them
+ */
+SysCaps get_system_capabilities() {
+       static bool first_call = true;
+       
+       if(!first_call) {
+               return sys_caps;
+       }
+       first_call = false;
+       
+       // get extensions & vendor strings
+       const char *tmp_str = (const char*)glGetString(GL_EXTENSIONS);
+       if(!tmp_str) {
+               error("%s: glGetString() failed, possibly no valid GL context", __func__);
+               exit(-1);
+       }
+       char *ext_str = new char[strlen(tmp_str) + 1];
+       strcpy(ext_str, tmp_str);
+       
+       char *cptr = ext_str;   
+       while(*cptr) {
+               if(*cptr == ' ') *cptr = '\n';
+               cptr++;
+       }
+
+       set_verbosity(2);
+       info("Supported extensions:\n-------------\n%s", ext_str);
+       set_verbosity(3);
+               
+       info("Rendering System Information:");
+
+       const char *vendor = (const char*)glGetString(GL_VENDOR);
+       info("  Vendor: %s", vendor);
+       info("Renderer: %s", glGetString(GL_RENDERER));
+       info(" Version: %s", glGetString(GL_VERSION));
+       info("(note: the list of extensions is logged seperately at \"gl_ext.log\")");
+
+       // fill the SysCaps structure
+       //SysCaps sys_caps;
+       sys_caps.load_transpose = (bool)strstr(ext_str, "GL_ARB_transpose_matrix");
+       sys_caps.gen_mipmaps = (bool)strstr(ext_str, "GL_SGIS_generate_mipmap");
+       sys_caps.tex_combine_ops = (bool)strstr(ext_str, "GL_ARB_texture_env_combine");
+       sys_caps.bump_dot3 = (bool)strstr(ext_str, "GL_ARB_texture_env_dot3");
+       sys_caps.bump_env = (bool)strstr(ext_str, "GL_ATI_envmap_bumpmap");
+       sys_caps.vertex_buffers = (bool)strstr(ext_str, "GL_ARB_vertex_buffer_object");
+       sys_caps.depth_texture = (bool)strstr(ext_str, "GL_ARB_depth_texture");
+       sys_caps.shadow_mapping = (bool)strstr(ext_str, "GL_ARB_shadow");
+       sys_caps.point_sprites = (bool)strstr(ext_str, "GL_ARB_point_sprite");
+       sys_caps.point_params = (bool)strstr(ext_str, "GL_ARB_point_parameters");
+       glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &sys_caps.max_texture_units);
+       sys_caps.non_power_of_two_textures = (bool)strstr(ext_str, "GL_ARB_texture_non_power_of_two");
+       glGetIntegerv(GL_MAX_LIGHTS, &sys_caps.max_lights);
+       
+       sys_caps.prog.asm_vertex = (bool)strstr(ext_str, "GL_ARB_vertex_program");
+       sys_caps.prog.asm_pixel = (bool)strstr(ext_str, "GL_ARB_fragment_program");
+       sys_caps.prog.glslang = (bool)strstr(ext_str, "GL_ARB_shading_language_100");
+       sys_caps.prog.shader_obj = (bool)strstr(ext_str, "GL_ARB_shader_objects");
+       sys_caps.prog.glsl_vertex = (bool)strstr(ext_str, "GL_ARB_vertex_shader");
+       sys_caps.prog.glsl_pixel = (bool)strstr(ext_str, "GL_ARB_fragment_shader");
+
+       delete [] ext_str;
+       
+       // also log these things
+       info("-------------------");
+       info("System Capabilities");
+       info("-------------------");
+       info("Load transposed matrices: %s", sys_caps.load_transpose ? "yes" : "no");
+       info("Auto-generate mipmaps (SGIS): %s", sys_caps.gen_mipmaps ? "yes" : "no");
+       info("Custom texture combination operations: %s", sys_caps.tex_combine_ops ? "yes" : "no");
+       info("Diffuse bump mapping (dot3): %s", sys_caps.bump_dot3 ? "yes" : "no");
+       info("Specular bump mapping (env-bump): %s", sys_caps.bump_env ? "yes" : "no");
+       info("Video memory vertex/index buffers: %s", sys_caps.vertex_buffers ? "yes" : "no");
+       info("Depth texture: %s", sys_caps.depth_texture ? "yes" : "no");
+       info("Shadow mapping: %s", sys_caps.shadow_mapping ? "yes" : "no");
+       info("Programmable vertex processing (asm): %s", sys_caps.prog.asm_vertex ? "yes" : "no");
+       info("Programmable pixel processing (asm): %s", sys_caps.prog.asm_pixel ? "yes" : "no");
+       info("OpenGL 2.0 shading language: %s", sys_caps.prog.glslang ? "yes" : "no");
+       info("Programmable vertex processing (glsl): %s", sys_caps.prog.glsl_vertex ? "yes" : "no");
+       info("Programmable pixel processing (glsl): %s", sys_caps.prog.glsl_pixel ? "yes" : "no");
+       info("Point sprites: %s", sys_caps.point_sprites ? "yes" : "no");
+       info("Point parameters: %s", sys_caps.point_params ? "yes" : "no");
+       info("Non power of 2 textures: %s", sys_caps.non_power_of_two_textures ? "yes" : "no");
+       info("Texture units: %d", sys_caps.max_texture_units);
+       info("Max lights: %d", sys_caps.max_lights);
+
+       if(!sys_caps.point_sprites && !sys_caps.point_params) {
+               warning("no point sprites support, falling back to billboards which *may* degrade particle system performance");
+       }
+
+       return sys_caps;
+}
+
+const char *get_glerror_string(GLenum error) {
+       if(!error) return gl_error_string[0x506];
+       if(error < 0x500 || error > 0x505) error = 0x507;
+       return gl_error_string[error - 0x500];
+}
+
+/* load_matrix_transpose_arb() & load_matrix_transpose_manual()
+ * --------------------------------------------------------
+ * two functions to handle the transformation matrix loading
+ * to OpenGL by either transposing the Matrix4x4 data or using
+ * the transposed-loading extension (use through function pointer
+ * LoadMatrixGL which is set during initialization to the correct one)
+ */
+void load_matrix_transpose_arb(const Matrix4x4 &mat) {
+       glLoadTransposeMatrix(mat.opengl_matrix());
+}
+
+void load_matrix_transpose_manual(const Matrix4x4 &mat) {
+#ifdef SINGLE_PRECISION_MATH
+       glLoadMatrixf(mat.transposed().opengl_matrix());
+#else
+       glLoadMatrixd(mat.transposed().opengl_matrix());
+#endif // SINGLE_PRECISION_MATH
+}
+
+
+//////////////// 3D Engine Initialization ////////////////
+
+static const char *signame(int sig) {
+       switch(sig) {
+       case SIGSEGV:
+               return "segmentation fault (SIGSEGV)";
+       case SIGILL:
+               return "illegal instruction (SIGILL)";
+       case SIGTERM:
+               return "termination signal (SIGTERM)";
+       case SIGFPE:
+               return "floating point exception (SIGFPE)";
+       case SIGINT:
+               return "interrupt signal (SIGINT)";
+       default:
+               return "unknown";
+       }
+       return "can't happen";
+}
+
+static void signal_handler(int sig) {
+       error("It seems this is the end... caught %s, exiting...", signame(sig));
+       destroy_graphics_context();
+       exit(EXIT_FAILURE);
+}
+
+/* ---- create_graphics_context() ----
+ * initializes the graphics subsystem according to the init parameters
+ */
+bool create_graphics_context(const GraphicsInitParameters &gip) {
+       
+       gparams = gip;
+
+       remove(get_log_filename());
+
+       if(!fxwt::init_graphics(&gparams)) {
+               return false;
+       }
+
+       signal(SIGSEGV, signal_handler);
+       signal(SIGILL, signal_handler);
+       signal(SIGTERM, signal_handler);
+       signal(SIGFPE, signal_handler);
+       signal(SIGINT, signal_handler);
+
+#if GFX_LIBRARY == GTK
+       fxwt::init();
+       dsys::init();
+       return true;
+#else
+       if(!start_gl()) return false;
+       fxwt::init();
+       dsys::init();
+       return true;
+#endif // GTK
+}
+
+/*
+ * short graphics context creation
+ * creates a graphics context (windowed or fullscreen)
+ * given only the wanted resolution and a fullscreen flag.
+ */
+bool create_graphics_context(int x, int y, bool fullscreen)
+{
+       GraphicsInitParameters gip;
+       gip.x = x;
+       gip.y = y;
+       gip.bpp = 32;
+       gip.depth_bits = 32;
+       gip.fullscreen = fullscreen;
+       gip.stencil_bits = 8;
+       gip.dont_care_flags = DONT_CARE_DEPTH | DONT_CARE_STENCIL | DONT_CARE_BPP;
+
+       return create_graphics_context(gip);
+}
+
+/* OpenGL startup after initialization */
+bool start_gl() {
+       SysCaps sys_caps = get_system_capabilities();
+
+       glext::glActiveTexture = (PFNGLACTIVETEXTUREARBPROC)glGetProcAddress("glActiveTextureARB");
+       glext::glClientActiveTexture = (PFNGLCLIENTACTIVETEXTUREARBPROC)glGetProcAddress("glClientActiveTextureARB");
+       
+       if(!glext::glActiveTexture || !glext::glClientActiveTexture) {
+               warning("No multitexturing support.");
+               sys_caps.multitex = false;
+       }
+
+       if(sys_caps.load_transpose) {
+#ifdef SINGLE_PRECISION_MATH
+               glLoadTransposeMatrix = (PFNGLLOADTRANSPOSEMATRIXFARBPROC)glGetProcAddress("glLoadTransposeMatrixfARB");
+#else
+               glLoadTransposeMatrix = (PFNGLLOADTRANSPOSEMATRIXDARBPROC)glGetProcAddress("glLoadTransposeMatrixdARB");
+#endif // SINGLE_PRECISION_MATH
+               
+               load_matrix_gl = load_matrix_transpose_arb;
+       } else {
+               load_matrix_gl = load_matrix_transpose_manual;
+       }
+
+       if(sys_caps.vertex_buffers) {
+               glBindBuffer = (PFNGLBINDBUFFERARBPROC)glGetProcAddress("glBindBufferARB");
+               glBufferData = (PFNGLBUFFERDATAARBPROC)glGetProcAddress("glBufferDataARB");
+               glDeleteBuffers = (PFNGLDELETEBUFFERSARBPROC)glGetProcAddress("glDeleteBuffersARB");
+               glIsBuffer = (PFNGLISBUFFERARBPROC)glGetProcAddress("glIsBufferARB");
+               glMapBuffer = (PFNGLMAPBUFFERARBPROC)glGetProcAddress("glMapBufferARB");
+               glUnmapBuffer = (PFNGLUNMAPBUFFERARBPROC)glGetProcAddress("glUnmapBufferARB");
+               glGenBuffers = (PFNGLGENBUFFERSARBPROC)glGetProcAddress("glGenBuffersARB");
+       }
+
+       if(sys_caps.prog.asm_vertex || sys_caps.prog.asm_pixel) {
+               glBindProgram = (PFNGLBINDPROGRAMARBPROC)glGetProcAddress("glBindProgramARB");
+               glGenPrograms = (PFNGLGENPROGRAMSARBPROC)glGetProcAddress("glGenProgramsARB");
+               glDeletePrograms = (PFNGLDELETEPROGRAMSARBPROC)glGetProcAddress("glDeleteProgramsARB");
+               glProgramString = (PFNGLPROGRAMSTRINGARBPROC)glGetProcAddress("glProgramStringARB");
+       }
+
+       if(sys_caps.prog.shader_obj) {
+               glDeleteObject = (PFNGLDELETEOBJECTARBPROC)glGetProcAddress("glDeleteObjectARB");
+               glAttachObject = (PFNGLATTACHOBJECTARBPROC)glGetProcAddress("glAttachObjectARB");
+               glDetachObject = (PFNGLDETACHOBJECTARBPROC)glGetProcAddress("glDetachObjectARB");
+               glGetObjectParameteriv = (PFNGLGETOBJECTPARAMETERIVARBPROC)glGetProcAddress("glGetObjectParameterivARB");
+               glGetInfoLog = (PFNGLGETINFOLOGARBPROC)glGetProcAddress("glGetInfoLogARB");
+               
+               glCreateProgramObject = (PFNGLCREATEPROGRAMOBJECTARBPROC)glGetProcAddress("glCreateProgramObjectARB");
+               glLinkProgram = (PFNGLLINKPROGRAMARBPROC)glGetProcAddress("glLinkProgramARB");
+               glUseProgramObject = (PFNGLUSEPROGRAMOBJECTARBPROC)glGetProcAddress("glUseProgramObjectARB");
+
+               glCreateShaderObject = (PFNGLCREATESHADEROBJECTARBPROC)glGetProcAddress("glCreateShaderObjectARB");
+               glShaderSource = (PFNGLSHADERSOURCEARBPROC)glGetProcAddress("glShaderSourceARB");
+               glCompileShader = (PFNGLCOMPILESHADERARBPROC)glGetProcAddress("glCompileShaderARB");
+               
+               glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONARBPROC)glGetProcAddress("glGetUniformLocationARB");
+               glGetActiveUniform = (PFNGLGETACTIVEUNIFORMARBPROC)glGetProcAddress("glGetActiveUniformARB");
+               glUniform1i = (PFNGLUNIFORM1IARBPROC)glGetProcAddress("glUniform1iARB");
+               glUniform1f = (PFNGLUNIFORM1FARBPROC)glGetProcAddress("glUniform1fARB");
+               glUniform2f = (PFNGLUNIFORM2FARBPROC)glGetProcAddress("glUniform2fARB");
+               glUniform3f = (PFNGLUNIFORM3FARBPROC)glGetProcAddress("glUniform3fARB");
+               glUniform4f = (PFNGLUNIFORM4FARBPROC)glGetProcAddress("glUniform4fARB");
+               glUniformMatrix3fv = (PFNGLUNIFORMMATRIX3FVARBPROC)glGetProcAddress("glUniformMatrix3fvARB");
+               glUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVARBPROC)glGetProcAddress("glUniformMatrix4fvARB");
+       }
+       
+       if(sys_caps.point_params) {
+               glext::glPointParameterf = (PFNGLPOINTPARAMETERFARBPROC)glGetProcAddress("glPointParameterfARB");
+               glext::glPointParameterfv = (PFNGLPOINTPARAMETERFVARBPROC)glGetProcAddress("glPointParameterfvARB");
+
+               if(!glext::glPointParameterfv) {
+                       error("error loading glPointParameterfv");
+                       return false;
+               }
+               if(!glext::glPointParameterf) {
+                       error("error loading glPointParameterf");
+                       return false;
+               }
+       }
+
+       gc_valid = true;
+       
+       set_default_states();
+       return true;
+}
+
+void destroy_graphics_context() {
+       static bool destroy_called_again = false;
+
+       if(destroy_called_again) {
+               warning("Multiple destroy_graphics_context() calls");
+               return;
+       } else {
+               destroy_called_again = true;
+       }
+
+       dsys::clean_up();
+       if(!gc_valid) return;
+       gc_valid = false;
+       info("3d engine shutting down...");
+       destroy_textures();
+       destroy_shaders();
+       fxwt::destroy_graphics();
+}
+
+void set_default_states() {
+       set_primitive_type(TRIANGLE_LIST);
+       set_front_face(ORDER_CW);
+       set_backface_culling(true);
+       set_zbuffering(true);
+       set_lighting(true);
+       set_auto_normalize(false);
+       
+       glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
+       glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
+       
+       set_matrix(XFORM_WORLD, Matrix4x4());
+       set_matrix(XFORM_VIEW, Matrix4x4());
+       set_matrix(XFORM_PROJECTION, create_projection_matrix(quarter_pi, 1.333333f, 1.0f, 1000.0f));
+       
+       memset(coord_index, 0, MAX_TEXTURES * sizeof(int));
+
+       for(int i=0; i<8; i++) {
+               ttype[i] = TEX_2D;
+       }
+
+       if(sys_caps.point_params) {
+               glext::glPointParameterf(GL_POINT_SIZE_MIN_ARB, 1.0);
+               glext::glPointParameterf(GL_POINT_SIZE_MAX_ARB, 256.0);
+
+               float quadratic[] = {0.0f, 0.0f, 0.01f};
+               glext::glPointParameterfv(GL_POINT_DISTANCE_ATTENUATION_ARB, quadratic);
+       }
+}
+
+const GraphicsInitParameters *get_graphics_init_parameters() {
+       return &gparams;
+}
+
+void clear(const Color &color) {
+       glClearColor(color.r, color.g, color.b, color.a);
+       glClear(GL_COLOR_BUFFER_BIT);
+}
+
+void clear_zbuffer(scalar_t zval) {
+       glClearDepth(zval);
+       glClear(GL_DEPTH_BUFFER_BIT);
+}
+
+void clear_stencil(unsigned char sval) {
+       glClearStencil(sval);
+       glClear(GL_STENCIL_BUFFER_BIT);
+}
+
+void clear_zbuffer_stencil(scalar_t zval, unsigned char sval) {
+       glClearDepth(zval);
+       glClearStencil(sval);
+       glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+}
+
+void flip() {
+       glFlush();
+       glFinish();
+       fxwt::swap_buffers();
+}
+
+void load_xform_matrices() {
+       for(int i=0; i<sys_caps.max_texture_units; i++) {
+               select_texture_unit(i);
+               glMatrixMode(GL_TEXTURE);
+               load_matrix_gl(tex_matrix[i]);
+       }
+       
+       glMatrixMode(GL_PROJECTION);
+       load_matrix_gl(proj_matrix);
+       
+       Matrix4x4 modelview = view_matrix * world_matrix;
+       glMatrixMode(GL_MODELVIEW);
+       load_matrix_gl(modelview);
+}
+
+#define BUFFER_OFFSET(i) ((char *)NULL + (i))
+
+void draw(const VertexArray &varray) {
+       load_xform_matrices();
+
+       bool use_vbo = !varray.get_dynamic() && sys_caps.vertex_buffers;
+       
+       glEnableClientState(GL_VERTEX_ARRAY);
+       glEnableClientState(GL_COLOR_ARRAY);
+       glEnableClientState(GL_NORMAL_ARRAY);
+       
+       if(use_vbo) {
+               Vertex v;
+               glBindBuffer(GL_ARRAY_BUFFER_ARB, varray.get_buffer_object());
+               glVertexPointer(3, GL_SCALAR_TYPE, sizeof(Vertex), (void*)((char*)&v.pos - (char*)&v));
+               glNormalPointer(GL_SCALAR_TYPE, sizeof(Vertex), (void*)((char*)&v.normal - (char*)&v));
+               glColorPointer(4, GL_SCALAR_TYPE, sizeof(Vertex), (void*)((char*)&v.color - (char*)&v));
+
+               for(int i=0; i<MAX_TEXTURES; i++) {
+                       select_texture_unit(i);
+                       glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+                       int dim = ttype[i] == TEX_1D ? 1 : (ttype[i] == TEX_3D || ttype[i] == TEX_CUBE ? 3 : 2);
+                       glTexCoordPointer(dim, GL_SCALAR_TYPE, sizeof(Vertex), (void*)((char*)&v.tex[coord_index[i]] - (char*)&v));
+               }
+
+               glBindBuffer(GL_ARRAY_BUFFER_ARB, 0);
+       } else {
+               glVertexPointer(3, GL_SCALAR_TYPE, sizeof(Vertex), &varray.get_data()->pos);
+               glNormalPointer(GL_SCALAR_TYPE, sizeof(Vertex), &varray.get_data()->normal);
+               glColorPointer(4, GL_SCALAR_TYPE, sizeof(Vertex), &varray.get_data()->color);
+
+               for(int i=0; i<MAX_TEXTURES; i++) {
+                       select_texture_unit(i);
+                       glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+                       int dim = ttype[i] == TEX_1D ? 1 : (ttype[i] == TEX_3D || ttype[i] == TEX_CUBE ? 3 : 2);
+                       glTexCoordPointer(dim, GL_SCALAR_TYPE, sizeof(Vertex), &varray.get_data()->tex[coord_index[i]]);
+               }
+       }
+       
+       glDrawArrays(primitive_type, 0, varray.get_count());
+       
+       glDisableClientState(GL_VERTEX_ARRAY);
+       glDisableClientState(GL_COLOR_ARRAY);
+       glDisableClientState(GL_NORMAL_ARRAY);
+       
+       for(int i=0; i<MAX_TEXTURES; i++) {
+               select_texture_unit(i);
+               glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+       }
+}
+
+void draw(const VertexArray &varray, const IndexArray &iarray) {
+       load_xform_matrices();
+       
+       bool use_vbo = !varray.get_dynamic() && sys_caps.vertex_buffers;
+       bool use_ibo = false;//!iarray.get_dynamic() && sys_caps.vertex_buffers;
+       
+       glEnableClientState(GL_VERTEX_ARRAY);
+       glEnableClientState(GL_COLOR_ARRAY);
+       glEnableClientState(GL_NORMAL_ARRAY);
+       
+       if(use_vbo) {
+               Vertex v;
+               glBindBuffer(GL_ARRAY_BUFFER_ARB, varray.get_buffer_object());
+               glVertexPointer(3, GL_SCALAR_TYPE, sizeof(Vertex), (void*)((char*)&v.pos - (char*)&v));
+               glNormalPointer(GL_SCALAR_TYPE, sizeof(Vertex), (void*)((char*)&v.normal - (char*)&v));
+               glColorPointer(4, GL_SCALAR_TYPE, sizeof(Vertex), (void*)((char*)&v.color - (char*)&v));
+
+               for(int i=0; i<MAX_TEXTURES; i++) {
+                       select_texture_unit(i);
+                       glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+                       int dim = ttype[i] == TEX_1D ? 1 : (ttype[i] == TEX_3D || ttype[i] == TEX_CUBE ? 3 : 2);
+                       glTexCoordPointer(dim, GL_SCALAR_TYPE, sizeof(Vertex), (void*)((char*)&v.tex[coord_index[i]] - (char*)&v));
+               }
+
+               glBindBuffer(GL_ARRAY_BUFFER_ARB, 0);
+       } else {
+               glVertexPointer(3, GL_SCALAR_TYPE, sizeof(Vertex), &varray.get_data()->pos);
+               glNormalPointer(GL_SCALAR_TYPE, sizeof(Vertex), &varray.get_data()->normal);
+               glColorPointer(4, GL_SCALAR_TYPE, sizeof(Vertex), &varray.get_data()->color);
+
+               for(int i=0; i<MAX_TEXTURES; i++) {
+                       select_texture_unit(i);
+                       glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+                       int dim = ttype[i] == TEX_1D ? 1 : (ttype[i] == TEX_3D || ttype[i] == TEX_CUBE ? 3 : 2);
+                       glTexCoordPointer(dim, GL_SCALAR_TYPE, sizeof(Vertex), &varray.get_data()->tex[coord_index[i]]);
+               }
+       }
+
+       if(use_ibo) {
+               glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, iarray.get_buffer_object());
+               glDrawElements(primitive_type, iarray.get_count(), GL_UNSIGNED_INT, 0);
+               glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
+       } else {
+               glDrawElements(primitive_type, iarray.get_count(), GL_UNSIGNED_INT, iarray.get_data());
+       }
+       
+       glDisableClientState(GL_VERTEX_ARRAY);
+       glDisableClientState(GL_COLOR_ARRAY);
+       glDisableClientState(GL_NORMAL_ARRAY);
+       
+       for(int i=0; i<MAX_TEXTURES; i++) {
+               select_texture_unit(i);
+               glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+       }
+}
+
+
+/* draw_line(start_vertex, end_vertex, start_width, end_width)
+ * Draws a line as a cylindrically billboarded elongated quad.
+ */
+void draw_line(const Vertex &v1, const Vertex &v2, scalar_t w1, scalar_t w2, const Color &col) {
+       if(w2 < 0.0) w2 = w1;
+
+       Vector3 p1 = v1.pos;
+       Vector3 p2 = v2.pos;
+
+       Vector3 cam_pos = Vector3(0,0,0).transformed(inv_view_matrix);
+       
+       Vector3 vec = p2 - p1;
+       scalar_t len = vec.length();
+       
+       Basis basis;
+       basis.k = -(cam_pos - ((p2 + p1) / 2)).normalized();
+       basis.j = vec / len;
+       basis.i = cross_product(basis.j, basis.k).normalized();
+       basis.k = cross_product(basis.i, basis.j).normalized();
+
+       world_matrix.set_translation(p1);
+       world_matrix = world_matrix * Matrix4x4(basis.create_rotation_matrix());
+       load_xform_matrices();
+
+       Vertex quad[] = {
+               Vertex(Vector3(-w1, 0, 0), v1.tex[0].u, 0.0, col),
+               Vertex(Vector3(-w2, len, 0), v2.tex[0].u, 0.0, col),
+               Vertex(Vector3(w2, len, 0), v2.tex[0].u, 1.0, col),
+               Vertex(Vector3(w1, 0, 0), v1.tex[0].u, 1.0, col)
+       };
+
+       set_lighting(false);
+       set_primitive_type(QUAD_LIST);
+       draw(VertexArray(quad, 4));
+       set_primitive_type(TRIANGLE_LIST);
+       set_lighting(true);
+}
+
+void draw_point(const Vertex &pt, scalar_t size) {
+
+       Vector3 p = pt.pos;
+       
+       Vector3 cam_pos = Vector3(0,0,0).transformed(inv_view_matrix);
+
+       Basis basis;
+       basis.k = -(cam_pos - p).normalized();
+       basis.j = Vector3(0, 1, 0);
+       basis.i = cross_product(basis.j, basis.k);
+       basis.j = cross_product(basis.k, basis.i);
+
+       world_matrix.set_translation(p);
+       world_matrix = world_matrix * Matrix4x4(basis.create_rotation_matrix());
+       load_xform_matrices();
+
+       Vertex quad[] = {
+               Vertex(Vector3(-size, -size, 0), 0.0, 0.0, pt.color),
+               Vertex(Vector3(-size, size, 0), 0.0, 1.0, pt.color),
+               Vertex(Vector3(size, size, 0), 1.0, 1.0, pt.color),
+               Vertex(Vector3(size, -size, 0), 1.0, 0.0, pt.color)
+       };
+
+       set_lighting(false);
+       set_primitive_type(QUAD_LIST);
+       draw(VertexArray(quad, 4));
+       set_primitive_type(TRIANGLE_LIST);
+       set_lighting(true);
+
+}
+
+
+void draw_scr_quad(const Vector2 &corner1, const Vector2 &corner2, const Color &color, bool reset_xform) {
+       if(reset_xform) {
+               glMatrixMode(GL_MODELVIEW);
+               glPushMatrix();
+               glLoadIdentity();
+       }
+
+       glMatrixMode(GL_PROJECTION);
+       glPushMatrix();
+       glLoadIdentity();
+       glOrtho(0.0, 1.0, 1.0, 0.0, 0.0, 1.0);
+
+       glDisable(GL_LIGHTING);
+
+       glBegin(GL_QUADS);
+       glColor4f(color.r, color.g, color.b, color.a);
+       glTexCoord2f(0.0f, 1.0f);
+       glVertex3f(corner1.x, corner1.y, -0.5);
+       glTexCoord2f(1.0f, 1.0f);
+       glVertex3f(corner2.x, corner1.y, -0.5);
+       glTexCoord2f(1.0f, 0.0f);
+       glVertex3f(corner2.x, corner2.y, -0.5);
+       glTexCoord2f(0.0f, 0.0f);
+       glVertex3f(corner1.x, corner2.y, -0.5);
+       glEnd();
+
+       glEnable(GL_LIGHTING);
+
+       glPopMatrix();
+
+       if(reset_xform) {
+               glMatrixMode(GL_MODELVIEW);
+               glPopMatrix();
+       }
+}
+
+int get_texture_unit_count() {
+       return sys_caps.max_texture_units;
+}
+
+//////////////////// render states /////////////////////
+
+void set_primitive_type(PrimitiveType pt) {
+       primitive_type = pt;
+}
+
+void set_backface_culling(bool enable) {
+       if(enable) {
+               glEnable(GL_CULL_FACE);
+       } else {
+               glDisable(GL_CULL_FACE);
+       }
+}
+
+void set_front_face(FaceOrder order) {
+       glFrontFace(order);
+}
+
+void set_auto_normalize(bool enable) {
+       if(enable) {
+               glEnable(GL_NORMALIZE);
+       } else {
+               glDisable(GL_NORMALIZE);
+       }
+}
+
+void set_color_write(bool red, bool green, bool blue, bool alpha) {
+       glColorMask(red, green, blue, alpha);
+}
+
+void set_wireframe(bool enable) {
+       //set_primitive_type(enable ? LINE_LIST : TRIANGLE_LIST);
+       glPolygonMode(GL_FRONT_AND_BACK, enable ? GL_LINE : GL_FILL);
+}
+       
+
+///////////////// blending states ///////////////
+
+void set_alpha_blending(bool enable) {
+       if(enable) {
+               glEnable(GL_BLEND);
+       } else {
+               glDisable(GL_BLEND);
+       }
+}
+
+void set_blend_func(BlendingFactor src, BlendingFactor dest) {
+       glBlendFunc(src, dest);
+}
+
+///////////////// zbuffer states ////////////////
+
+void set_zbuffering(bool enable) {
+       if(enable) {
+               glEnable(GL_DEPTH_TEST);
+       } else {
+               glDisable(GL_DEPTH_TEST);
+       }
+}
+
+void set_zwrite(bool enable) {
+       glDepthMask(enable);
+}
+
+void set_zfunc(CmpFunc func) {
+       glDepthFunc(func);
+}
+
+/////////////// stencil states //////////////////
+void set_stencil_buffering(bool enable) {
+       if(enable) {
+               glEnable(GL_STENCIL_TEST);
+       } else {
+               glDisable(GL_STENCIL_TEST);
+       }
+}
+
+void set_stencil_pass_op(StencilOp sop) {
+       stencil_pass = sop;
+       glStencilOp(stencil_fail, stencil_pzfail, stencil_pass);
+}
+
+void set_stencil_fail_op(StencilOp sop) {
+       stencil_fail = sop;
+       glStencilOp(stencil_fail, stencil_pzfail, stencil_pass);
+}
+
+void set_stencil_pass_zfail_op(StencilOp sop) {
+       stencil_pzfail = sop;
+       glStencilOp(stencil_fail, stencil_pzfail, stencil_pass);
+}
+
+void set_stencil_op(StencilOp fail, StencilOp spass_zfail, StencilOp pass) {
+       stencil_fail = fail;
+       stencil_pzfail = spass_zfail;
+       stencil_pass = pass;
+       glStencilOp(stencil_fail, stencil_pzfail, stencil_pass);
+}
+
+void set_stencil_func(CmpFunc func) {
+       glStencilFunc(func, stencil_ref, 0xffffffff);
+}
+
+void set_stencil_reference(unsigned int ref) {
+       stencil_ref = ref;
+}
+
+///////////// texture & material states //////////////
+
+void set_point_sprites(bool enable) {
+       if(sys_caps.point_sprites) {
+               if(enable) {
+                       glEnable(GL_POINT_SPRITE_ARB);
+               } else {
+                       glDisable(GL_POINT_SPRITE_ARB);
+               }
+       }
+}
+
+void set_texture_filtering(int tex_unit, TextureFilteringType tex_filter) {
+       
+       int min_filter;
+       
+       switch(tex_filter) {
+       case POINT_SAMPLING:
+               min_filter = mipmapping ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST;
+               glTexParameteri(ttype[tex_unit], GL_TEXTURE_MIN_FILTER, min_filter);
+               glTexParameteri(ttype[tex_unit], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+               break;
+               
+       case BILINEAR_FILTERING:
+               min_filter = mipmapping ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
+               glTexParameteri(ttype[tex_unit], GL_TEXTURE_MIN_FILTER, min_filter);
+               glTexParameteri(ttype[tex_unit], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+               break;
+               
+       case TRILINEAR_FILTERING:
+       default:
+               min_filter = mipmapping ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
+               glTexParameteri(ttype[tex_unit], GL_TEXTURE_MIN_FILTER, min_filter);
+               glTexParameteri(ttype[tex_unit], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+               break;
+       }
+}
+
+void set_texture_addressing(int tex_unit, TextureAddressing uaddr, TextureAddressing vaddr) {
+       glTexParameteri(ttype[tex_unit], GL_TEXTURE_WRAP_S, uaddr);
+       glTexParameteri(ttype[tex_unit], GL_TEXTURE_WRAP_T, vaddr);
+}
+
+void set_texture_border_color(int tex_unit, const Color &color) {
+       float col[] = {color.r, color.g, color.b, color.a};
+       glTexParameterfv(ttype[tex_unit], GL_TEXTURE_BORDER_COLOR, col);
+}
+
+void set_texture(int tex_unit, const Texture *tex) {
+       select_texture_unit(tex_unit);
+       glBindTexture(tex->get_type(), tex->tex_id);
+       ttype[tex_unit] = tex->get_type();
+}
+
+void set_mip_mapping(bool enable) {
+       mipmapping = enable;
+}
+
+void set_material(const Material &mat) {
+       mat.set_glmaterial();
+}
+
+void use_vertex_colors(bool enable) {
+       if(enable) {
+               glEnable(GL_COLOR_MATERIAL);
+       } else {
+               glDisable(GL_COLOR_MATERIAL);
+       }
+}
+
+
+void set_render_target(Texture *tex, CubeMapFace cube_map_face) {
+       static std::stack<Texture*> rt_stack;
+       static std::stack<CubeMapFace> face_stack;
+       
+       Texture *prev = rt_stack.empty() ? 0 : rt_stack.top();
+       CubeMapFace prev_face = CUBE_MAP_PX; // just to get rid of the uninitialized var warning
+       if(!face_stack.empty()) prev_face = face_stack.top();
+
+       if(tex == prev) return;
+
+       if(prev) {
+               set_texture(0, prev);
+               glCopyTexSubImage2D(prev->get_type() == TEX_CUBE ? prev_face : GL_TEXTURE_2D, 0, 0, 0, 0, 0, prev->width, prev->height);
+       }
+       
+       if(!tex) {
+               rt_stack.pop();
+               if(prev->get_type() == TEX_CUBE) {
+                       face_stack.pop();
+
+                       if(rt_stack.empty()) {
+                               set_viewport(0, 0, gparams.x, gparams.y);
+                       } else {
+                               set_viewport(0, 0, rt_stack.top()->width, rt_stack.top()->height);
+                       }
+               }
+       } else {
+               if(tex->get_type() == TEX_CUBE) {
+                       set_viewport(0, 0, tex->width, tex->height);
+               }
+
+               rt_stack.push(tex);
+               if(tex->get_type() == TEX_CUBE) face_stack.push(cube_map_face);
+       }
+}
+
+void copy_texture(Texture *tex, bool full_screen) {
+       if(!tex) return;
+
+       int width = full_screen ? get_graphics_init_parameters()->x : tex->width;
+       int height = full_screen ? get_graphics_init_parameters()->y : tex->height;
+
+       set_texture(0, tex);
+       glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, width, height);
+}
+
+// multitexturing interface
+
+void select_texture_unit(int tex_unit) {
+       if(sys_caps.multitex) {
+               glext::glActiveTexture(GL_TEXTURE0 + tex_unit);
+               glext::glClientActiveTexture(GL_TEXTURE0 + tex_unit);
+       }
+}
+
+void enable_texture_unit(int tex_unit) {
+       if(!tex_unit || (sys_caps.multitex && tex_unit < sys_caps.max_texture_units)) {
+               select_texture_unit(tex_unit);
+               glEnable(ttype[tex_unit]);
+       }
+}
+
+void disable_texture_unit(int tex_unit) {
+       if(!tex_unit || (sys_caps.multitex && tex_unit < sys_caps.max_texture_units)) {
+               select_texture_unit(tex_unit);
+               glDisable(ttype[tex_unit]);
+       }
+}
+
+void set_texture_unit_color(int tex_unit, TextureBlendFunction op, TextureBlendArgument arg1, TextureBlendArgument arg2, TextureBlendArgument arg3) {
+       
+       select_texture_unit(tex_unit);
+       glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
+       glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, op);
+       glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, arg1);
+       glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, arg2);
+       if(arg3 != TARG_NONE) {
+               glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, arg3);
+       }
+}
+
+void set_texture_unit_alpha(int tex_unit, TextureBlendFunction op, TextureBlendArgument arg1, TextureBlendArgument arg2, TextureBlendArgument arg3) {
+       
+       select_texture_unit(tex_unit);
+       glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
+       glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, op);
+       glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, arg1);
+       glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, arg2);
+       if(arg3 != TARG_NONE) {
+               glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA, arg3);
+       }
+}
+
+void set_texture_coord_index(int tex_unit, int index) {
+       coord_index[tex_unit] = index;
+}
+
+void set_texture_constant(int tex_unit, const Color &col) {
+       float color[] = {col.r, col.g, col.b, col.a};
+       select_texture_unit(tex_unit);
+       glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
+}
+
+//void set_texture_transform_state(int sttex_unitage, TexTransformState TexXForm);
+//void set_texture_coord_generator(int stage, TexGen tgen);
+
+void set_point_sprite_coords(int tex_unit, bool enable) {
+       if(sys_caps.point_params) {
+               select_texture_unit(tex_unit);
+               glTexEnvi(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, enable ? GL_TRUE : GL_FALSE);
+       }
+}
+
+
+// programmable interface
+void set_gfx_program(GfxProg *prog) {
+       if(!sys_caps.prog.glslang) return;
+       if(prog) {
+               if(!prog->linked) {
+                       prog->link();
+                       if(!prog->linked) return;
+               }
+               glUseProgramObject(prog->prog);
+               
+               // call any registered update handlers
+               if(prog->update_handler) {
+                       prog->update_handler(prog);
+               }
+       } else {
+               glUseProgramObject(0);
+       }
+}
+
+// lighting states
+void set_lighting(bool enable) {
+       if(enable) {
+               glEnable(GL_LIGHTING);
+       } else {
+               glDisable(GL_LIGHTING);
+       }
+}
+
+void set_ambient_light(const Color &ambient_color) {
+       float col[] = {ambient_color.r, ambient_color.g, ambient_color.b, ambient_color.a};
+       glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
+}
+
+void set_shading_mode(ShadeMode mode) {
+       glShadeModel(mode);
+}
+
+void set_bump_light(const Light *light) {
+       bump_light = light;
+}
+
+// transformation matrices
+void set_matrix(TransformType xform_type, const Matrix4x4 &mat, int num) {
+       switch(xform_type) {
+       case XFORM_WORLD:
+               world_matrix = mat;
+               break;
+               
+       case XFORM_VIEW:
+               view_matrix = mat;
+               inv_view_matrix = view_matrix.inverse();
+               view_mat_camera = 0;
+               break;
+               
+       case XFORM_PROJECTION:
+               proj_matrix = mat;
+               break;
+               
+       case XFORM_TEXTURE:
+               tex_matrix[num] = mat;
+               break;
+       }
+}
+
+Matrix4x4 get_matrix(TransformType xform_type, int num) {
+       switch(xform_type) {
+       case XFORM_WORLD:
+               return world_matrix;
+               
+       case XFORM_VIEW:
+               return view_matrix;
+               
+       case XFORM_TEXTURE:
+               return tex_matrix[num];
+               
+       case XFORM_PROJECTION:
+       default:
+               return proj_matrix;
+       }
+}
+
+void set_viewport(unsigned int x, unsigned int y, unsigned int xsize, unsigned int ysize) {
+       glViewport(x, y, xsize, ysize);
+}
+
+// normalized set_viewport()
+void set_viewport_norm(float x, float y, float xsize, float ysize)
+{
+       glViewport((int) (x * gparams.x), (int)(y * gparams.y), 
+               (int) (xsize * gparams.x), int (ysize * gparams.y));
+}
+
+Matrix4x4 create_projection_matrix(scalar_t vfov, scalar_t aspect, scalar_t near_clip, scalar_t far_clip) {
+#ifdef COORD_LHS
+       scalar_t hfov = vfov * aspect;
+       scalar_t w = 1.0f / (scalar_t)tan(hfov * 0.5f);
+       scalar_t h = 1.0f / (scalar_t)tan(vfov * 0.5f);
+       scalar_t q = far_clip / (far_clip - near_clip);
+       
+       Matrix4x4 mat;
+       mat[0][0] = w;
+       mat[1][1] = h;
+       mat[2][2] = q;
+       mat[3][2] = 1.0f;
+       mat[2][3] = -q * near_clip;
+#else
+       scalar_t f = 1.0f / (scalar_t)tan(vfov * 0.5f);
+
+       Matrix4x4 mat;
+       mat[0][0] = f / aspect;
+       mat[1][1] = f;
+       mat[2][2] = (far_clip + near_clip) / (near_clip - far_clip);
+       mat[3][2] = -1.0f;
+       mat[2][3] = (2.0f * far_clip * near_clip) / (near_clip - far_clip);
+       mat[3][3] = 0;
+#endif
+       
+       return mat;
+}
+
+
+// ---- misc ----
+
+bool screen_capture(char *fname, enum image_file_format fmt) {
+       static int scr_num;
+       static const char *suffix[] = {"png", "jpg", "tga", "oug1", "oug2"};
+       int x = gparams.x;
+       int y = gparams.y;
+
+       uint32_t *pixels = new uint32_t[x * y];
+       glReadPixels(0, 0, x, y, GL_BGRA, GL_UNSIGNED_BYTE, pixels);
+       
+       if(!fname) {
+               static char fname_buf[50];
+               fname = fname_buf;
+               sprintf(fname, "3dengfx_shot%04d.%s", scr_num++, suffix[fmt]);
+       }
+
+       unsigned int flags = get_image_save_flags();
+       set_image_save_flags(flags | IMG_SAVE_INVERT);
+       int res = save_image(fname, pixels, x, y, fmt);
+       set_image_save_flags(flags);
+       
+       delete [] pixels;
+       return res != -1;
+}
diff --git a/src/3dengfx/src/3dengfx/3denginefx.hpp b/src/3dengfx/src/3dengfx/3denginefx.hpp
new file mode 100644 (file)
index 0000000..2e51f5f
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+This file is part of the 3dengfx, realtime visualization system.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+3dengfx is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+3dengfx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with 3dengfx; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* main 3dengfx state control, and low level OpenGL interaction
+ *
+ * Author: John Tsiombikas 2004
+ * Modified: John Tsiombikas 2005
+ */
+
+#ifndef _3DENGINEFX_HPP_
+#define _3DENGINEFX_HPP_
+
+#include "opengl.h"
+#include "3denginefx_types.hpp"
+#include "textures.hpp"
+#include "material.hpp"
+#include "gfx/3dgeom.hpp"
+#include "gfx/image.h"
+#include "light.hpp"
+
+class Camera;
+
+namespace engfx_state {
+       extern SysCaps sys_caps;
+       extern Matrix4x4 world_matrix, view_matrix, inv_view_matrix;
+       extern const Camera *view_mat_camera;
+       extern Matrix4x4 proj_matrix;
+       extern const Light *bump_light;
+       extern int light_count;
+}
+
+bool create_graphics_context(const GraphicsInitParameters &gip);
+bool create_graphics_context(int x, int y, bool fullscreen);
+bool start_gl();
+void destroy_graphics_context();
+void set_default_states();
+const GraphicsInitParameters *get_graphics_init_parameters();
+
+void clear(const Color &color);
+void clear_zbuffer(scalar_t zval);
+void clear_stencil(unsigned char sval);
+void clear_zbuffer_stencil(scalar_t zval, unsigned char sval);
+
+void flip();
+
+void load_xform_matrices();
+void draw(const VertexArray &varray);
+void draw(const VertexArray &varray, const IndexArray &iarray);
+void draw_line(const Vertex &v1, const Vertex &v2, scalar_t w1, scalar_t w2 = -1.0, const Color &col = 1.0);
+void draw_point(const Vertex &pt, scalar_t size);
+void draw_scr_quad(const Vector2 &corner1, const Vector2 &corner2, const Color &color = Color(1.0), bool reset_xform = true);
+
+int get_texture_unit_count();
+
+////// render states //////
+void set_primitive_type(PrimitiveType pt);
+void set_backface_culling(bool enable);
+void set_front_face(FaceOrder order);
+void set_auto_normalize(bool enable);
+//void set_billboarding(bool enable);
+void set_color_write(bool red, bool green, bool blue, bool alpha);
+void set_wireframe(bool enable);
+
+// blending states
+void set_alpha_blending(bool enable);
+void set_blend_func(BlendingFactor src, BlendingFactor dest);
+
+// zbuffer states
+void set_zbuffering(bool enable);
+void set_zwrite(bool enable);
+void set_zfunc(CmpFunc func);
+
+// set stencil buffer states
+void set_stencil_buffering(bool enable);
+void set_stencil_pass_op(StencilOp sop);
+void set_stencil_fail_op(StencilOp sop);
+void set_stencil_pass_zfail_op(StencilOp sop);
+void set_stencil_op(StencilOp fail, StencilOp spass_zfail, StencilOp pass);
+void set_stencil_func(CmpFunc func);
+void set_stencil_reference(unsigned int ref);
+
+// texture & material states
+void set_point_sprites(bool enable);
+void set_texture_filtering(int tex_unit, TextureFilteringType tex_filter);
+void set_texture_addressing(int tex_unit, TextureAddressing uaddr, TextureAddressing vaddr);
+void set_texture_border_color(int tex_unit, const Color &color);
+void set_texture(int tex_unit, const Texture *tex);
+//void set_texture_factor(unsigned int factor);
+void set_mip_mapping(bool enable);
+void set_material(const Material &mat);
+void use_vertex_colors(bool enable);
+
+void set_render_target(Texture *tex, CubeMapFace cube_map_face = CUBE_MAP_PX);
+void copy_texture(Texture *tex, bool full_screen = false);
+
+// multitexturing interface
+void select_texture_unit(int tex_unit);
+void enable_texture_unit(int tex_unit);
+void disable_texture_unit(int tex_unit);
+void set_texture_unit_color(int tex_unit, TextureBlendFunction op, TextureBlendArgument arg1, TextureBlendArgument arg2, TextureBlendArgument arg3 = TARG_NONE);
+void set_texture_unit_alpha(int tex_unit, TextureBlendFunction op, TextureBlendArgument arg1, TextureBlendArgument arg2, TextureBlendArgument arg3 = TARG_NONE);
+void set_texture_coord_index(int tex_unit, int index);
+void set_texture_constant(int tex_unit, const Color &col);
+//void set_texture_transform_state(int tex_unit, TexTransformState TexXForm);
+//void set_texture_coord_generator(int stage, TexGen tgen);
+void set_point_sprite_coords(int tex_unit, bool enable);
+
+// programmable interface
+void set_gfx_program(GfxProg *prog);
+
+// lighting states
+void set_lighting(bool enable);
+//void set_color_vertex(bool enable);
+void set_ambient_light(const Color &ambient_color);
+void set_shading_mode(ShadeMode mode);
+//void set_specular(bool enable);
+
+void set_bump_light(const Light *light);
+
+// Transformation Matrices
+void set_matrix(TransformType xform_type, const Matrix4x4 &mat, int num = 0);
+Matrix4x4 get_matrix(TransformType xform_type, int num = 0);
+
+// viewport
+void set_viewport(unsigned int x, unsigned int y, unsigned int xsize, unsigned int ysize);
+// normalized set_viewport()
+void set_viewport_norm(float x, float y, float xsize, float ysize);
+
+Matrix4x4 create_projection_matrix(scalar_t vfov, scalar_t aspect, scalar_t near, scalar_t far);
+
+// misc
+bool screen_capture(char *fname = 0, enum image_file_format fmt = IMG_FMT_TGA);
+
+
+GraphicsInitParameters *load_graphics_context_config(const char *fname);
+void engine_log(const char *log_data, const char *subsys = 0);
+SysCaps get_system_capabilities();
+const char *get_glerror_string(GLenum error);
+extern void (*load_matrix_gl)(const Matrix4x4 &mat);
+
+#endif // _3DENGINEFX_HPP_
diff --git a/src/3dengfx/src/3dengfx/3denginefx_types.hpp b/src/3dengfx/src/3dengfx/3denginefx_types.hpp
new file mode 100644 (file)
index 0000000..4fcdc31
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+This file is part of the 3dengfx, realtime visualization system.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+3dengfx is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+3dengfx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with 3dengfx; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* enumerations and data structures for the low-level 3dengfx state
+ *
+ * Author: John Tsiombikas 2004
+ */
+
+#ifndef _3DENGINEFX_TYPES_HPP_
+#define _3DENGINEFX_TYPES_HPP_
+
+#include "opengl.h"
+#include "n3dmath2/n3dmath2_types.hpp"
+
+enum ShadeMode {
+       SHADING_FLAT = GL_FLAT,
+       SHADING_GOURAUD = GL_SMOOTH
+};
+
+#ifdef COORD_LHS
+enum FaceOrder {ORDER_CW = GL_CW, ORDER_CCW = GL_CCW};
+#else
+enum FaceOrder {ORDER_CW = GL_CCW, ORDER_CCW = GL_CW};
+#endif
+
+enum PrimitiveType {
+       TRIANGLE_LIST   = GL_TRIANGLES,
+       TRIANGLE_STRIP  = GL_TRIANGLE_STRIP,
+       TRIANGLE_FAN    = GL_TRIANGLE_FAN,
+       LINE_LIST               = GL_LINES,
+       LINE_STRIP              = GL_LINE_STRIP,
+       LINE_LOOP               = GL_LINE_LOOP,
+       POINT_LIST              = GL_POINTS,
+       QUAD_LIST               = GL_QUADS,
+       QUAD_STRIP              = GL_QUAD_STRIP
+};
+
+enum BlendingFactor {
+       BLEND_ZERO                                      = GL_ZERO,
+       BLEND_ONE                                       = GL_ONE,
+       BLEND_SRC_COLOR                         = GL_SRC_COLOR,
+       BLEND_ONE_MINUS_SRC_COLOR       = GL_ONE_MINUS_SRC_COLOR,
+       BLEND_SRC_ALPHA                         = GL_SRC_ALPHA,
+       BLEND_ONE_MINUS_SRC_ALPHA       = GL_ONE_MINUS_SRC_ALPHA,
+       BLEND_ONE_MINUS_DST_COLOR       = GL_ONE_MINUS_DST_COLOR
+};
+
+enum TextureBlendFunction {
+       TOP_REPLACE                     = GL_REPLACE,
+       TOP_ADD                         = GL_ADD,
+       TOP_ADDSIGNED           = GL_ADD_SIGNED,
+       TOP_SUBTRACT            = GL_SUBTRACT,
+       TOP_MODULATE            = GL_MODULATE,
+       TOP_LERP                        = GL_INTERPOLATE,
+       TOP_DOT3                        = GL_DOT3_RGB,
+       TOP_DOT3_RGBA           = GL_DOT3_RGBA
+};
+
+enum TextureBlendArgument {
+       TARG_TEXTURE    = GL_TEXTURE,
+       TARG_CONSTANT   = GL_CONSTANT,
+       TARG_COLOR              = GL_PRIMARY_COLOR,
+       TARG_PREV               = GL_PREVIOUS,
+       TARG_NONE
+};
+
+enum CmpFunc {
+       CMP_NEVER               = GL_NEVER,
+    CMP_LESS           = GL_LESS,
+    CMP_EQUAL          = GL_EQUAL,
+    CMP_LEQUAL         = GL_LEQUAL,
+    CMP_GREATER                = GL_GREATER,
+    CMP_NOTEQUAL       = GL_NOTEQUAL,
+    CMP_GEQUAL         = GL_GEQUAL,
+    CMP_ALWAYS         = GL_ALWAYS
+};
+
+enum StencilOp {
+       SOP_KEEP                = GL_KEEP,
+    SOP_ZERO           = GL_ZERO,
+    SOP_REPLACE                = GL_REPLACE,
+    SOP_INCSAT         = GL_INCR,
+    SOP_DECSAT         = GL_DECR,
+    SOP_INVERT         = GL_INVERT,
+    SOP_INC                    = GL_INCR,      // TODO: find a way to let these wrap around
+    SOP_DEC                    = GL_DECR       //
+};
+
+enum TextureFilteringType {
+       POINT_SAMPLING,
+       BILINEAR_FILTERING, 
+       TRILINEAR_FILTERING, 
+       ANISOTROPIC_FILTERING
+};
+
+enum TextureAddressing {
+       TEXADDR_WRAP                    = GL_REPEAT,
+       //TexAddrMirror                 = D3DTADDRESS_MIRROR,
+       TEXADDR_CLAMP                   = GL_CLAMP_TO_EDGE,
+       TEXADDR_CLAMP_BORDER    = GL_CLAMP
+       //TexAddrMirrorOnce             = D3DTADDRESS_MIRRORONCE
+};
+
+enum TextureDim {
+       TEX_1D          = GL_TEXTURE_1D,
+       TEX_2D          = GL_TEXTURE_2D,
+       TEX_3D          = GL_TEXTURE_3D,
+       TEX_CUBE        = GL_TEXTURE_CUBE_MAP
+};
+
+enum CubeMapFace {
+       CUBE_MAP_PX             = GL_TEXTURE_CUBE_MAP_POSITIVE_X,
+       CUBE_MAP_NX             = GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
+       CUBE_MAP_PY             = GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
+       CUBE_MAP_NY             = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
+       CUBE_MAP_PZ             = GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
+       CUBE_MAP_NZ             = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
+};
+
+class GfxProg;
+
+#define DONT_CARE_BPP          1       // 0001
+#define DONT_CARE_DEPTH                2       // 0010
+#define DONT_CARE_STENCIL      4       // 0100
+
+struct GraphicsInitParameters {
+       int x, y;
+       int bpp;
+       int depth_bits;
+       int stencil_bits;
+       bool fullscreen;
+       unsigned short dont_care_flags;
+};
+
+struct ProgCaps {
+       bool shader_obj;
+       bool asm_pixel, asm_vertex;
+       bool glslang;
+       bool glsl_pixel, glsl_vertex;
+};
+
+struct SysCaps {
+       bool multitex;
+       bool load_transpose;
+       bool gen_mipmaps;
+       bool tex_combine_ops;
+       bool bump_dot3;
+       bool bump_env;
+       bool vertex_buffers;
+       bool depth_texture;
+       bool shadow_mapping;
+       bool point_sprites;
+       bool point_params;
+       int max_texture_units;
+       bool non_power_of_two_textures;
+       int max_lights;
+       ProgCaps prog;
+};
+
+enum TransformType {
+       XFORM_WORLD,
+       XFORM_VIEW,
+       XFORM_PROJECTION,
+       XFORM_TEXTURE
+};
+
+
+
+
+#endif // _3DENGINEFX_TYPES_HPP_
diff --git a/src/3dengfx/src/3dengfx/3dscene.cpp b/src/3dengfx/src/3dengfx/3dscene.cpp
new file mode 100644 (file)
index 0000000..de49021
--- /dev/null
@@ -0,0 +1,618 @@
+/*
+This file is part of the 3dengfx, realtime visualization system.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+3dengfx is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+3dengfx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with 3dengfx; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "3dengfx_config.h"
+
+#include <algorithm>
+#include <string>
+#include <limits.h>
+#include "3dscene.hpp"
+#include "texman.hpp"
+#include "3denginefx.hpp"
+#include "common/err_msg.h"
+#include "dsys/fx.hpp"
+
+using std::string;
+
+Scene::Scene() {
+       active_camera = 0;
+       shadows = false;
+       light_halos = false;
+       halo_size = 10.0f;
+       use_fog = false;
+
+       lights = new Light*[engfx_state::sys_caps.max_lights];
+       memset(lights, 0, engfx_state::sys_caps.max_lights * sizeof(Light*));
+       lcount = 0;
+
+       ambient_light = Color(0.0f, 0.0f, 0.0f);
+       manage_data = true;
+
+       auto_clear = true;
+       bg_color = 0;
+       scene_poly_count = 0;
+       poly_count = 0;
+
+       // setup the cube-map cameras
+       for(int i=0; i<6; i++) {
+               cubic_cam[i] = new TargetCamera;
+               cubic_cam[i]->set_fov(half_pi);
+               cubic_cam[i]->set_aspect(1.0);
+               cubic_cam[i]->flip(false, true, false);
+       }
+       cubic_cam[CUBE_MAP_INDEX_PY]->set_up_vector(Vector3(0, 0, -1));
+       cubic_cam[CUBE_MAP_INDEX_NY]->set_up_vector(Vector3(0, 0, 1));
+
+       first_render = true;
+       frame_count = 0;
+}
+
+Scene::~Scene() {
+       for(int i=0; i>6; i++) {
+               delete cubic_cam[i];
+       }
+
+       if(manage_data) {
+               std::list<Object*>::iterator obj = objects.begin();
+               while(obj != objects.end()) {
+                       delete *obj++;
+               }
+
+               std::list<Camera*>::iterator cam = cameras.begin();
+               while(cam != cameras.end()) {
+                       delete *cam++;
+               }
+
+               for(int i=0; i<engfx_state::sys_caps.max_lights; i++) {
+                       delete lights[i];
+               }
+
+               std::list<Curve*>::iterator citer = curves.begin();
+               while(citer != curves.end()) {
+                       delete *citer++;
+               }
+
+               std::list<ParticleSystem*>::iterator piter = psys.begin();
+               while(piter != psys.end()) {
+                       delete *piter++;
+               }
+       }
+
+       delete [] lights;
+}
+
+void Scene::set_poly_count(unsigned long pcount) {
+       scene_poly_count = pcount;
+}
+
+unsigned long Scene::get_poly_count() const {
+       return scene_poly_count;
+}
+
+unsigned long Scene::get_frame_poly_count() const {
+       return poly_count;
+}
+
+void Scene::add_camera(Camera *cam) {
+       cameras.push_back(cam);
+       if(!active_camera) active_camera = cam;
+}
+
+void Scene::add_light(Light *light) {
+       if(lcount >= engfx_state::sys_caps.max_lights) return;
+       lights[lcount++] = light;
+}
+
+void Scene::add_object(Object *obj) {
+       if(obj->get_material_ptr()->alpha < 1.0f - small_number) {
+        objects.push_back(obj);
+       } else {
+               objects.push_front(obj);
+       }
+}
+
+void Scene::add_curve(Curve *curve) {
+       curves.push_back(curve);
+}
+
+void Scene::add_particle_sys(ParticleSystem *p) {
+       psys.push_back(p);
+}
+
+/* adds a cubemapped skycube, by creating a cube with the correct
+ * texture coordinates to map into the cubemap texture.
+ */
+void Scene::add_skycube(scalar_t size, Texture *cubemap) {
+       Object *obj = new ObjCube(size, 4);
+       obj->get_mesh_ptr()->invert_winding();
+
+       // generate appropriate texture coordinates
+       unsigned int vcount = obj->get_vertex_count();
+       Vertex *vptr = obj->get_mod_vertex_data();
+
+       for(unsigned int i=0; i<vcount; i++) {
+               Vector3 vpos = vptr->pos.normalized();
+               (vptr++)->tex[0] = TexCoord(vpos.x, -vpos.y, vpos.z);
+       }
+
+       // setup material parameters
+       Material *mat = obj->get_material_ptr();
+       mat->ambient_color = mat->diffuse_color = mat->specular_color = 0.0;
+       mat->emissive_color = 1.0;
+       mat->set_texture(cubemap, TEXTYPE_DIFFUSE);
+
+       obj->set_texture_addressing(TEXADDR_CLAMP);
+
+       add_object(obj);
+}
+
+bool Scene::remove_light(const Light *light) {
+       int idx;
+       for(idx = 0; idx < lcount; idx++) {
+               if(light == lights[idx]) {
+                       break;
+               }
+       }
+
+       if(idx < lcount) {
+               lights[idx] = 0;
+               for(int i=idx; i<lcount-1; i++) {
+                       lights[i] = lights[i + 1];
+               }
+               return true;
+       }
+       
+       return false;
+}
+
+bool Scene::remove_object(const Object *obj) {
+       std::list<Object*>::iterator iter = find(objects.begin(), objects.end(), obj);
+       if(iter != objects.end()) {
+               objects.erase(iter);
+               return true;
+       }
+       return false;
+}
+
+bool Scene::remove_particle_sys(const ParticleSystem *p) {
+       std::list<ParticleSystem*>::iterator iter = find(psys.begin(), psys.end(), p);
+       if(iter != psys.end()) {
+               psys.erase(iter);
+               return true;
+       }
+       return false;
+}
+
+Camera *Scene::get_camera(const char *name) {
+       std::list<Camera *>::iterator iter = cameras.begin();
+       while(iter != cameras.end()) {
+               if(!strcmp((*iter)->name.c_str(), name)) return *iter;
+               iter++;
+       }
+       return 0;
+}
+
+Light *Scene::get_light(const char *name) {
+       for(int i=0; i<lcount; i++) {
+               if(lights[i] && !strcmp(lights[i]->name.c_str(), name)) return lights[i];
+       }
+       return 0;
+}
+
+Object *Scene::get_object(const char *name) {
+       std::list<Object *>::iterator iter = objects.begin();
+       while(iter != objects.end()) {
+               if(!strcmp((*iter)->name.c_str(), name)) return *iter;
+               iter++;
+       }
+       return 0;
+}
+
+Curve *Scene::get_curve(const char *name) {
+       std::list<Curve *>::iterator iter = curves.begin();
+       while(iter != curves.end()) {
+               if(!strcmp((*iter)->name.c_str(), name)) return *iter;
+               iter++;
+       }
+       return 0;
+}
+
+ParticleSystem *Scene::get_particle_sys(const char *name) {
+       std::list<ParticleSystem*>::iterator iter = psys.begin();
+       while(iter != psys.end()) {
+               if(!strcmp((*iter)->name.c_str(), name)) return *iter;
+               iter++;
+       }
+       return 0;
+}
+
+XFormNode *Scene::get_node(const char *name) {
+       XFormNode *node;
+
+       if((node = get_object(name))) return node;
+       if((node = get_light(name))) return node;
+       if((node = get_camera(name))) return node;
+       
+       return 0;
+}
+
+std::list<Object*> *Scene::get_object_list() {
+       return &objects;
+}
+
+std::list<Camera*> *Scene::get_camera_list() {
+       return &cameras;
+}
+
+void Scene::set_active_camera(const Camera *cam) {
+       active_camera = cam;
+}
+
+Camera *Scene::get_active_camera() const {
+       return const_cast<Camera*>(active_camera);
+}
+
+void Scene::set_halo_drawing(bool enable) {
+       light_halos = enable;
+}
+
+void Scene::set_halo_size(float size) {
+       halo_size = size;
+}
+
+void Scene::set_ambient_light(Color ambient) {
+       ambient_light = ambient;
+}
+
+Color Scene::get_ambient_light() const {
+       return ambient_light;
+}
+
+void Scene::set_fog(bool enable, Color fog_color, float near_fog, float far_fog) {
+       use_fog = enable;
+       if(enable) {
+               this->fog_color = fog_color;
+               near_fog_range = near_fog;
+               far_fog_range = far_fog;
+       }
+}
+
+void Scene::set_auto_clear(bool enable) {
+       auto_clear = enable;
+}
+
+void Scene::set_background(const Color &bg) {
+       bg_color = bg;
+}
+
+void Scene::setup_lights(unsigned long msec) const {
+       int light_index = 0;
+       for(int i=0; i<lcount; i++) {
+               if(lights[i]) {
+                       lights[i]->set_gl_light(light_index++, msec);
+               }
+       }
+       glDisable(GL_LIGHT0 + light_index);
+}
+
+void Scene::set_shadows(bool enable) {
+       shadows = enable;
+}
+
+void Scene::render(unsigned long msec) const {
+       static int call_depth = -1;
+       call_depth++;
+       
+       bool fb_dirty = false;
+       if(!call_depth) {
+               // ---- this part is guaranteed to be executed once for each frame ----
+               poly_count = 0;         // reset the polygon counter
+               
+               ::set_ambient_light(ambient_light);
+               
+               // XXX: render_all_cube_maps() will call Scene::render() recursively as necessary.
+               fb_dirty = render_all_cube_maps(msec);
+               
+               
+               first_render = false;   // this is needed by the cubemap calculation routine
+                                                               // to support 1st frame only cubemap calculation.
+               frame_count++;  // for statistics.
+
+               // --- update particle systems (not render) ---
+               psys::set_global_time(msec);
+               std::list<ParticleSystem*>::const_iterator iter = psys.begin();
+               while(iter != psys.end()) {
+                       (*iter++)->update();
+               }
+               // TODO: also update other simulations here (see sim framework).
+       }
+
+       if(auto_clear || fb_dirty) {
+               clear(bg_color);
+               clear_zbuffer_stencil(1.0, 0);
+       }
+       
+       // set camera
+       if(!active_camera) {
+               call_depth--;
+               return;
+       }
+       active_camera->activate(msec);
+
+       // set lights
+       setup_lights(msec);
+
+       // render stuff
+       if(shadows) {
+               bool at_least_one = false;
+               for(int i=0; i<lcount; i++) {
+                       if(!lights[i]->casts_shadows()) continue;
+                       at_least_one = true;
+
+                       glDisable(GL_LIGHT0 + i);
+                       render_objects(msec);   // scene minus this shadow casting light.
+
+                       set_zwrite(false);
+                       set_lighting(false);
+                       set_color_write(false, false, false, false);
+                       set_stencil_buffering(true);
+                       set_stencil_func(CMP_ALWAYS);
+
+                       // render volume front faces
+                       set_stencil_op(SOP_KEEP, SOP_KEEP, SOP_INC);
+                       set_front_face(ORDER_CW);
+                       render_svol(i, msec);
+                       
+                       // render volume back faces
+                       set_stencil_op(SOP_KEEP, SOP_KEEP, SOP_DEC);
+                       set_front_face(ORDER_CCW);
+                       render_svol(i, msec);
+                       
+                       // restore states
+                       set_stencil_op(SOP_KEEP, SOP_KEEP, SOP_KEEP);
+                       set_front_face(ORDER_CW);
+                                               
+                       set_color_write(true, true, true, true);
+                       set_lighting(true);
+                       set_zwrite(true);
+
+                       clear_zbuffer(1.0);
+
+                       set_stencil_buffering(true);
+                       set_stencil_func(CMP_EQUAL);
+                       set_stencil_reference(0);
+
+                       glEnable(GL_LIGHT0 + i);
+
+                       render_objects(msec);
+               }
+               set_stencil_buffering(false);
+               if(!at_least_one) render_objects(msec);
+       } else {
+               render_objects(msec);
+       }
+       
+       render_particles(msec);
+
+       call_depth--;
+}
+
+void Scene::render_objects(unsigned long msec) const {
+       std::list<Object *>::const_iterator iter = objects.begin();
+       while(iter != objects.end()) {
+               Object *obj = *iter++;
+
+               RenderParams rp = obj->get_render_params();
+
+               if(!rp.hidden) {
+                       if(obj->render(msec)) {
+                               poly_count += obj->get_mesh_ptr()->get_triangle_array()->get_count();
+                       }
+               }
+       }
+}
+
+void Scene::render_particles(unsigned long msec) const {
+       std::list<ParticleSystem*>::const_iterator piter = psys.begin();
+       while(piter != psys.end()) {
+               (*piter++)->draw();
+       }
+}
+
+// TODO: optimize this...
+void Scene::render_svol(int lidx, unsigned long msec) const {
+       std::list<Object *>::const_iterator iter = objects.begin();
+       while(iter != objects.end()) {
+               Object *obj = *iter++;
+               RenderParams rp = obj->get_render_params();
+
+               if(!rp.hidden && rp.cast_shadows && obj->get_material_ptr()->alpha > 0.995) {
+                       Matrix4x4 xform = obj->get_prs(msec).get_xform_matrix();
+                       Matrix4x4 inv_xform = xform.inverse();
+
+                       Vector3 lt;
+                       bool is_dir = false;
+                       if(dynamic_cast<DirLight*>(lights[lidx])) {
+                               lt = ((DirLight*)lights[lidx])->get_direction();
+                               lt.transform(Matrix3x3(inv_xform));
+                               is_dir = true;
+                       } else {
+                               lt = lights[lidx]->get_position(msec);
+                               lt.transform(inv_xform);
+                       }
+                       
+                       TriMesh *vol = obj->get_mesh_ptr()->get_shadow_volume(lt, is_dir);
+                       set_matrix(XFORM_WORLD, xform);
+                       draw(*vol->get_vertex_array(), *vol->get_index_array());
+                       delete vol;
+               }
+       }
+}
+
+void Scene::render_cube_map(Object *obj, unsigned long msec) const {
+       Scene *non_const_this = const_cast<Scene*>(this);
+
+       Material *mat = obj->get_material_ptr();
+       Texture *tex = mat->get_texture(TEXTYPE_ENVMAP);
+
+       if(!tex || (tex && tex->get_type() != TEX_CUBE)) {
+               warning("tried to render_cube_map() on a non-cubemapped object");
+               return;
+       }
+
+       RenderParams render_params = obj->get_render_params();
+       if(render_params.hidden) return;
+
+       Vector3 obj_pos = obj->get_prs(msec).position;
+
+       non_const_this->place_cube_camera(obj_pos + obj->get_pivot());
+
+       const Camera *active_cam = get_active_camera();
+
+       obj->set_hidden(true);
+
+       for(int i=0; i<6; i++) {
+               static CubeMapFace cube_face[] = {CUBE_MAP_PX, CUBE_MAP_NX, CUBE_MAP_PY, CUBE_MAP_NY, CUBE_MAP_PZ, CUBE_MAP_NZ};
+               set_render_target(tex, cube_face[i]);
+               non_const_this->set_active_camera(cubic_cam[i]);
+               clear(bg_color);
+               clear_zbuffer_stencil(1.0, 0);
+               render(msec);
+
+               Color overlay_color = mat->specular_color * mat->env_intensity;
+               set_alpha_blending(true);
+               set_blend_func(BLEND_ZERO, BLEND_SRC_COLOR);
+               dsys::overlay(0, Vector2(0,0), Vector2(1,1), overlay_color, 0, false);
+               set_alpha_blending(false);
+               
+               set_render_target(0);
+       }
+
+       non_const_this->set_active_camera(active_cam);
+       setup_lights(msec);
+
+       obj->set_hidden(false);
+}
+
+void Scene::place_cube_camera(const Vector3 &pos) {
+       static const Vector3 targets[] = {
+               Vector3(1, 0, 0), Vector3(-1, 0, 0),    // +/- X
+               Vector3(0, 1, 0), Vector3(0, -1, 0),    // +/- Y
+               Vector3(0, 0, 1), Vector3(0, 0, -1)             // +/- Z
+       };
+
+       for(int i=0; i<6; i++) {
+               cubic_cam[i]->set_position(pos);
+               cubic_cam[i]->set_target(targets[i] + pos);
+       }
+}
+
+
+bool Scene::render_all_cube_maps(unsigned long msec) const {
+       bool did_some = false;
+       
+       std::list<Object *>::const_iterator iter = objects.begin();
+       while(iter != objects.end()) {
+               Object *obj = *iter++;
+
+               Texture *env;
+               Material *mat = obj->get_material_ptr();
+               RenderParams rp = obj->get_render_params();
+               if(rp.hidden) continue;
+
+               // if it is marked as a non-automatically updated reflection map, skip it.
+               if(!mat->auto_refl) {
+                       continue;
+               }
+
+               // if auto-reflect is set for updating every nth frame,
+               // and this is not one of them, skip it.
+               if(mat->auto_refl_upd > 1 && frame_count % mat->auto_refl_upd) {
+                       continue;
+               }
+               
+               // if auto-reflect is set to update only during the first frame,
+               // and this is not the first frame, skip it.
+               if(mat->auto_refl_upd == 0 && !first_render) {
+                       continue;
+               }
+               
+               // ... otherwise, update the reflection in the cubemap.
+               if((env = mat->get_texture(TEXTYPE_ENVMAP))) {
+                       if(env->get_type() == TEX_CUBE) {
+                               did_some = true;
+                               render_cube_map(obj, msec);
+                       }
+               }
+       }
+
+       return did_some;
+}
+
+#include "fxwt/text.hpp"
+#if defined(unix) || defined(__unix__)
+#include <unistd.h>
+#include <sys/stat.h>
+#endif // __unix__
+
+void Scene::render_sequence(unsigned long start, unsigned long end, int fps, const char *out_dir) {
+#if defined(unix) || defined(__unix__)
+       // change to the specified directory
+       char curr_dir[PATH_MAX];
+       getcwd(curr_dir, PATH_MAX);
+
+       struct stat sbuf;
+       if(stat(out_dir, &sbuf) == -1) {
+               mkdir(out_dir, 0770);
+       }       
+       
+       chdir(out_dir);
+#endif // __unix__
+
+       warning("Sequence rendering is experimental; this may make the program unresponsive while it renders, be patient.");
+
+       // render frames until we reach the end time
+       unsigned long time = start;
+       unsigned long dt = 1000 / fps;
+
+       while(time < end) {
+               render(time);
+               screen_capture();
+
+               // draw progress bar
+               scalar_t t = (scalar_t)time / (scalar_t)(end - start);
+               set_zbuffering(false);
+               set_lighting(false);
+               set_alpha_blending(true);
+               set_blend_func(BLEND_ONE_MINUS_DST_COLOR, BLEND_ZERO);
+               draw_scr_quad(Vector3(0.0, 0.49), Vector3(t, 0.51), Color(1, 1, 1));
+               set_blend_func(BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA);
+               set_alpha_blending(false);
+               set_lighting(true);
+               set_zbuffering(true);
+               
+               flip();
+               time += dt;
+       }
+
+#if defined(unix) || defined(__unix__)
+       chdir(curr_dir);
+#endif // __unix__
+}
diff --git a/src/3dengfx/src/3dengfx/3dscene.hpp b/src/3dengfx/src/3dengfx/3dscene.hpp
new file mode 100644 (file)
index 0000000..6a28a74
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+This file is part of the 3dengfx, realtime visualization system.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+3dengfx is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+3dengfx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with 3dengfx; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#ifndef _3DSCENE_HPP_
+#define _3DSCENE_HPP_
+
+#include <list>
+#include "camera.hpp"
+#include "light.hpp"
+#include "object.hpp"
+#include "psys.hpp"
+#include "gfx/curves.hpp"
+
+struct ShadowVolume {
+       TriMesh *shadow_mesh;
+       const Light *light;
+};
+
+class Scene {
+private:
+       Light **lights;
+       int lcount, max_lights;
+
+       std::list<Camera *> cameras;
+       TargetCamera *cubic_cam[6];
+       std::list<Object*> objects;
+       std::list<ShadowVolume> static_shadow_volumes;
+       std::list<Curve*> curves;
+       std::list<ParticleSystem*> psys;
+       
+       bool manage_data;
+       const Camera *active_camera;
+       bool shadows;
+       bool light_halos;
+       float halo_size;
+       Color ambient_light;
+       bool use_fog;
+       Color fog_color;
+       float near_fog_range, far_fog_range;
+       bool auto_clear;
+       Color bg_color;
+       mutable bool first_render;
+       mutable unsigned long frame_count;
+       mutable unsigned long poly_count;
+       unsigned long scene_poly_count;
+       bool frustum_cull;
+       
+       void place_cube_camera(const Vector3 &pos);
+       bool render_all_cube_maps(unsigned long msec = XFORM_LOCAL_PRS) const;
+               
+public:
+
+       Scene();
+       ~Scene();
+
+       void set_poly_count(unsigned long pcount);
+       unsigned long get_poly_count() const;
+       unsigned long get_frame_poly_count() const;
+
+       void add_camera(Camera *cam);
+       void add_light(Light *light);
+       void add_object(Object *obj);
+       void add_static_shadow_volume(TriMesh *mesh, const Light *light);
+       void add_curve(Curve *curve);
+       void add_particle_sys(ParticleSystem *p);
+
+       void add_skycube(scalar_t size, Texture *cubemap);
+
+       bool remove_light(const Light *light);
+       bool remove_object(const Object *obj);
+       bool remove_particle_sys(const ParticleSystem *p);
+
+       Camera *get_camera(const char *name);
+       Light *get_light(const char *name);
+       Object *get_object(const char *name);
+       Curve *get_curve(const char *name);
+       ParticleSystem *get_particle_sys(const char *name);
+
+       XFormNode *get_node(const char *name);
+
+       std::list<Object*> *get_object_list();
+       std::list<Camera*> *get_camera_list();
+
+       void set_active_camera(const Camera *cam);
+       Camera *get_active_camera() const;
+
+       void set_shadows(bool enable);
+       void set_halo_drawing(bool enable);
+       void set_halo_size(float size);
+       void set_ambient_light(Color ambient);
+       Color get_ambient_light() const;
+       void set_fog(bool enable, Color fog_color = Color(0l), float near_fog = 0.0f, float far_fog = 1000.0f);
+       void set_auto_clear(bool enable);
+       void set_background(const Color &bg);
+       void set_frustum_culling(bool enable);
+
+       // render states
+       void setup_lights(unsigned long msec = XFORM_LOCAL_PRS) const;
+
+       void render(unsigned long msec = XFORM_LOCAL_PRS) const;
+       void render_objects(unsigned long msec = XFORM_LOCAL_PRS) const;
+       void render_particles(unsigned long msec = XFORM_LOCAL_PRS) const;
+       void render_svol(int lidx, unsigned long msec = XFORM_LOCAL_PRS) const;
+       void render_cube_map(Object *obj, unsigned long msec = XFORM_LOCAL_PRS) const;
+
+       void render_sequence(unsigned long start, unsigned long end, int fps = 30, const char *out_dir = "frames");
+};
+
+#endif // _3DSCENE_HPP_
diff --git a/src/3dengfx/src/3dengfx/camera.cpp b/src/3dengfx/src/3dengfx/camera.cpp
new file mode 100644 (file)
index 0000000..c35055a
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+This file is part of the 3dengfx, realtime visualization system.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+3dengfx is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+3dengfx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with 3dengfx; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "3dengfx_config.h"
+
+#include "camera.hpp"
+#include "3denginefx.hpp"
+
+Camera::Camera(const Vector3 &translation, const Quaternion &rot) 
+       : BaseCamera(translation, rot) {}
+
+Matrix4x4 Camera::get_camera_matrix(unsigned long msec) const {
+       PRS prs = get_prs(msec);
+
+       Matrix4x4 vmat = prs.rotation.inverse().get_rotation_matrix();
+       vmat.translate(-prs.position);
+
+       // TODO: this does not work...
+       Matrix4x4 flip_matrix;
+       if(flip_view.x) flip_matrix[0][0] = -1;
+       if(flip_view.y) flip_matrix[1][1] = -1;
+       if(flip_view.z) flip_matrix[2][2] = -1;
+
+       return flip_matrix * vmat;
+}
+/*
+void Camera::activate(unsigned long msec) const {
+       set_matrix(XFORM_VIEW, get_camera_matrix(msec));
+
+       Matrix4x4 proj = get_projection_matrix();
+       set_matrix(XFORM_PROJECTION, proj);
+
+       engfx_state::view_mat_camera = this;
+       const_cast<Camera*>(this)->setup_frustum(proj * engfx_state::view_matrix);
+}
+*/
+
+TargetCamera::TargetCamera(const Vector3 &trans, const Vector3 &target) : Camera(trans) {
+       set_target(target);
+}
+
+TargetCamera::~TargetCamera() {}
+
+void TargetCamera::set_target(const Vector3 &target) {
+       this->target.set_position(target);
+}
+
+Vector3 TargetCamera::get_target(unsigned long msec) const {
+       return target.get_prs(msec).position;
+}
+
+Matrix4x4 TargetCamera::get_camera_matrix(unsigned long msec) const {
+       PRS prs = get_prs(msec);
+       Vector3 targ = target.get_prs(msec).position;
+
+       Vector3 pvec = prs.position - targ;
+       pvec.transform(prs.rotation.get_rotation_matrix());
+       Vector3 pos = targ + pvec;
+
+#ifdef COORD_LHS
+       Vector3 n = (targ - pos).normalized();
+#else
+       Vector3 n = -(targ - pos).normalized();
+#endif
+       Vector3 u = cross_product(up, n).normalized();
+       Vector3 v;
+       
+       if(flip_view.y) {
+               v = cross_product(u, n);
+               set_front_face(ORDER_CCW);
+       } else {
+               v = cross_product(n, u);
+               set_front_face(ORDER_CW);
+       }
+
+       scalar_t tx = -dot_product(u, pos);
+       scalar_t ty = -dot_product(v, pos);
+       scalar_t tz = -dot_product(n, pos);
+       
+       return Matrix4x4(u.x, u.y, u.z, tx,
+                                       v.x, v.y, v.z, ty,
+                                       n.x, n.y, n.z, tz,
+                                       0.0, 0.0, 0.0, 1.0);
+}
+
+/*
+void TargetCamera::activate(unsigned long msec) const {
+       set_matrix(XFORM_VIEW, get_camera_matrix(msec));
+
+       Matrix4x4 proj = get_projection_matrix();
+       set_matrix(XFORM_PROJECTION, proj);
+
+       engfx_state::view_mat_camera = this;
+       const_cast<TargetCamera*>(this)->setup_frustum(proj * engfx_state::view_matrix);
+}
+*/
+
+void TargetCamera::zoom(scalar_t factor, unsigned long msec) {
+       Vector3 pos = get_prs(msec).position;
+       Vector3 targ = get_target(msec);
+
+       Vector3 dist_vec = (pos - targ) * factor;
+
+       set_position(targ + dist_vec, msec);
+}
+
+void TargetCamera::roll(scalar_t angle, unsigned long msec) {
+       Vector3 axis = target.get_prs(msec).position - get_prs(msec).position;
+       Quaternion q(axis.normalized(), fmod(angle, two_pi));
+       up = Vector3(0, 1, 0);
+       up.transform(q);
+}
diff --git a/src/3dengfx/src/3dengfx/camera.hpp b/src/3dengfx/src/3dengfx/camera.hpp
new file mode 100644 (file)
index 0000000..2e0fffe
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+This file is part of the 3dengfx, realtime visualization system.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+3dengfx is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+3dengfx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with 3dengfx; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#ifndef _CAMERA_HPP_
+#define _CAMERA_HPP_
+
+#include <string>
+#include "gfx/base_cam.hpp"
+
+class Camera : public BaseCamera {
+public:
+       Camera(const Vector3 &trans = Vector3(0,0,0), const Quaternion &rot = Quaternion());
+
+       virtual Matrix4x4 get_camera_matrix(unsigned long msec = XFORM_LOCAL_PRS) const;
+       
+       //virtual void activate(unsigned long msec = XFORM_LOCAL_PRS) const;
+};
+
+
+class TargetCamera : public Camera {
+public:
+       XFormNode target;
+
+       TargetCamera(const Vector3 &trans = Vector3(0,0,-10), const Vector3 &target = Vector3(0,0,0));
+       virtual ~TargetCamera();
+
+       virtual void set_target(const Vector3 &target);
+       virtual Vector3 get_target(unsigned long msec = XFORM_LOCAL_PRS) const;
+
+       virtual Matrix4x4 get_camera_matrix(unsigned long msec = XFORM_LOCAL_PRS) const;
+       
+       //virtual void activate(unsigned long msec = XFORM_LOCAL_PRS) const;
+
+       virtual void zoom(scalar_t factor, unsigned long msec = XFORM_LOCAL_PRS);
+       virtual void roll(scalar_t angle, unsigned long msec = XFORM_LOCAL_PRS);
+};
+
+#endif // _CAMERA_HPP_
diff --git a/src/3dengfx/src/3dengfx/gfxprog.cpp b/src/3dengfx/src/3dengfx/gfxprog.cpp
new file mode 100644 (file)
index 0000000..38326a4
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+This file is part of the 3dengfx, realtime visualization system.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+3dengfx is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+3dengfx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with 3dengfx; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "3dengfx_config.h"
+
+#include <iostream>
+#include <cstdio>
+#include <cstring>
+#include "gfxprog.hpp"
+#include "3denginefx.hpp"
+#include "opengl.h"
+#include "common/err_msg.h"
+
+using namespace std;
+using namespace glext;
+
+GfxProg::GfxProg(Shader vertex, Shader pixel) {
+       linked = false;
+       update_handler = 0;
+
+       prog = 0;
+       if(engfx_state::sys_caps.prog.shader_obj) {
+               prog = glCreateProgramObject();
+
+               if(vertex) add_shader(vertex);
+               if(pixel) add_shader(pixel);
+       }
+}
+
+GfxProg::~GfxProg() {
+       if(engfx_state::sys_caps.prog.shader_obj) {
+               list<Shader>::iterator iter = sdr_list.begin();
+               while(iter != sdr_list.end()) {
+                       glDetachObject(prog, *iter++);
+               }
+               glDeleteObject(prog);
+       }
+}
+
+void GfxProg::add_shader(Shader sdr) {
+       if(engfx_state::sys_caps.prog.shader_obj) {
+               glAttachObject(prog, sdr);
+               sdr_list.push_back(sdr);
+       }
+}
+
+void GfxProg::link() {
+       int linked, log_size;
+       
+       if(!engfx_state::sys_caps.prog.shader_obj) {
+               return;
+       }
+       
+       glLinkProgram(prog);
+       glGetObjectParameteriv(prog, GL_OBJECT_LINK_STATUS_ARB, &linked);
+       glGetObjectParameteriv(prog, GL_OBJECT_INFO_LOG_LENGTH_ARB, &log_size);
+
+       char *err_str = 0;
+       if(log_size) {
+               err_str = new char[log_size + 1];
+               glGetInfoLog(prog, log_size, 0, err_str);
+       }
+
+       if(linked) {
+               if(err_str) {
+                       info("linked: %s", err_str);
+                       delete [] err_str;
+               } else {
+                       info("program linked successfully");
+               }               
+       } else {
+               if(err_str) {
+                       error("linking failed: %s", err_str);
+                       delete [] err_str;
+               } else {
+                       error("program linking failed");
+               }
+       }
+
+       this->linked = (bool)linked;
+}
+
+bool GfxProg::is_linked() const {
+       return linked;
+}
+
+unsigned int GfxProg::get_id() const {
+       if(!linked) {
+               const_cast<GfxProg*>(this)->link();
+       }
+       return linked ? prog : 0;
+}
+
+bool GfxProg::set_parameter(const char *pname, int val) {
+       if(!engfx_state::sys_caps.prog.shader_obj) {
+               return false;
+       }
+       glUseProgramObject(prog);
+       int loc = glGetUniformLocation(prog, pname);
+       if(loc != -1) {
+               glUniform1i(loc, val);
+       }
+       glUseProgramObject(0);
+       return loc == -1 ? false : true;
+}
+
+bool GfxProg::set_parameter(const char *pname, scalar_t val) {
+       if(!engfx_state::sys_caps.prog.shader_obj) {
+               return false;
+       }
+       glUseProgramObject(prog);
+       int loc = glGetUniformLocation(prog, pname);
+       if(loc != -1) {
+               glUniform1f(loc, val);
+       }
+       glUseProgramObject(0);
+       return loc == -1 ? false : true;
+}
+
+bool GfxProg::set_parameter(const char *pname, const Vector2 &val) {
+       if(!engfx_state::sys_caps.prog.shader_obj) {
+               return false;
+       }
+       glUseProgramObject(prog);
+       int loc = glGetUniformLocation(prog, pname);
+       if(loc != -1) {
+               glUniform2f(loc, val.x, val.y);
+       }
+       glUseProgramObject(0);
+       return loc == -1 ? false : true;
+}
+
+bool GfxProg::set_parameter(const char *pname, const Vector3 &val) {
+       if(!engfx_state::sys_caps.prog.shader_obj) {
+               return false;
+       }
+       glUseProgramObject(prog);
+       int loc = glGetUniformLocation(prog, pname);
+       if(loc != -1) {
+               glUniform3f(loc, val.x, val.y, val.z);
+       }
+       glUseProgramObject(0);
+       return loc == -1 ? false : true;
+}
+
+bool GfxProg::set_parameter(const char *pname, const Vector4 &val) {
+       if(!engfx_state::sys_caps.prog.shader_obj) {
+               return false;
+       }
+       glUseProgramObject(prog);
+       int loc = glGetUniformLocation(prog, pname);
+       if(loc != -1) {
+               glUniform4f(loc, val.x, val.y, val.z, val.w);
+       }
+       glUseProgramObject(0);
+       return loc == -1 ? false : true;
+}
+
+bool GfxProg::set_parameter(const char *pname, const Matrix4x4 &val) {
+       if(!engfx_state::sys_caps.prog.shader_obj) {
+               return false;
+       }
+       glUseProgramObject(prog);
+       int loc = glGetUniformLocation(prog, pname);
+       if(loc != -1) {
+               glUniformMatrix4fv(loc, 1, 1, val.opengl_matrix());
+       }
+       glUseProgramObject(0);
+       return loc == -1 ? false : true;
+}
+
+void GfxProg::set_update_handler(void (*func)(GfxProg*)) {
+       update_handler = func;
+}
diff --git a/src/3dengfx/src/3dengfx/gfxprog.hpp b/src/3dengfx/src/3dengfx/gfxprog.hpp
new file mode 100644 (file)
index 0000000..6d47e47
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+This file is part of the 3dengfx, realtime visualization system.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+3dengfx is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+3dengfx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with 3dengfx; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* GPU programs support (shaders)
+ *
+ * Author: John Tsiombikas 2005
+ */
+#ifndef _GFXPROG_HPP_
+#define _GFXPROG_HPP_
+
+#include <list>
+#include "opengl.h"
+#include "n3dmath2/n3dmath2.hpp"
+
+enum {
+       PROG_VERTEX     = GL_VERTEX_SHADER_ARB,
+       PROG_PIXEL      = GL_FRAGMENT_SHADER_ARB
+};
+
+typedef unsigned int Shader;
+
+class GfxProg {
+private:
+       unsigned int prog;
+       std::list<Shader> sdr_list;
+       bool linked;
+       
+       void (*update_handler)(GfxProg*);
+
+public:
+       GfxProg(Shader vertex = 0, Shader pixel = 0);
+       ~GfxProg();
+
+       void add_shader(Shader sdr);
+       void link();
+
+       bool is_linked() const;
+       unsigned int get_id() const;
+
+       bool set_parameter(const char *pname, int val);
+       bool set_parameter(const char *pname, scalar_t val);
+       bool set_parameter(const char *pname, const Vector2 &val);
+       bool set_parameter(const char *pname, const Vector3 &val);
+       bool set_parameter(const char *pname, const Vector4 &val);
+       bool set_parameter(const char *pname, const Matrix4x4 &val);
+
+       void set_update_handler(void (*func)(GfxProg*));
+
+       friend void set_gfx_program(GfxProg *prog);
+};
+       
+
+#endif // _GFXPROG_HPP_
diff --git a/src/3dengfx/src/3dengfx/ggen.cpp b/src/3dengfx/src/3dengfx/ggen.cpp
new file mode 100644 (file)
index 0000000..a920f75
--- /dev/null
@@ -0,0 +1,856 @@
+/*
+This file is part of the 3dengfx, 3d visualization system.
+
+Copyright (c) 2004, 2005, 2006 John Tsiombikas <nuclear@siggraph.org>
+
+3dengfx is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+3dengfx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with 3dengfx; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* geometry generation
+ * 
+ * author: John Tsiombikas 2004
+ * modified: 
+ *             Mihalis Georgoulopoulos 2004, 2005
+ *             John Tsiombikas 2005
+ */
+
+#include <float.h>
+#include "3dengfx_config.h"
+#include "gfx/curves.hpp"
+#include "ggen.hpp"
+
+#define GGEN_SOURCE
+#include "teapot.h"
+
+/* create_cube - (JT)
+ * creates a subdivided cube
+ */
+void create_cube(TriMesh *mesh, scalar_t size, int subdiv) {
+       TriMesh tmp;
+       Matrix4x4 mat;
+
+       Vector3 face_vec[] = {
+               Vector3(0, 0, -1),
+               Vector3(1, 0, 0),
+               Vector3(0, 0, 1),
+               Vector3(-1, 0, 0),
+               Vector3(0, 1, 0),
+               Vector3(0, -1, 0)
+       };
+
+       for(int i=0; i<6; i++) {
+               create_plane(i ? &tmp : mesh, face_vec[i], Vector2(size, size), subdiv);
+               mat.set_translation(face_vec[i] * (size / 2.0));
+
+               if(i) {
+                       tmp.apply_xform(mat);
+                       join_tri_mesh(mesh, mesh, &tmp);
+               } else {
+                       mesh->apply_xform(mat);
+               }
+       }
+}
+/* CreatePlane - (JT)
+ * creates a planar mesh of arbitrary subdivision
+ */
+void create_plane(TriMesh *mesh, const Vector3 &normal, const Vector2 &size, int subdiv) {
+       unsigned long vcount = (subdiv + 2) * (subdiv + 2);
+       unsigned long tcount = (subdiv + 1) * (subdiv + 1) * 2;
+       int quad_num = tcount / 2;
+       int quads_row = subdiv + 1;             // quads per row
+       int vrow = subdiv + 2;          // vertices per row
+       int vcol = vrow;
+
+    Vertex *varray = new Vertex[vcount];
+       Triangle *tarray = new Triangle[tcount];
+
+       for(int j=0; j<vcol; j++) {
+               for(int i=0; i<vrow; i++) {
+
+                       scalar_t u = (scalar_t)i/(scalar_t)quads_row;
+                       scalar_t v = (scalar_t)j/(scalar_t)quads_row;
+                       varray[j * vrow + i] = Vertex(Vector3(u - 0.5f, 1.0f - v - 0.5f, 0), u, 1.0 - v, Color(1.0f));
+                       varray[j * vrow + i].pos.x *= size.x;
+                       varray[j * vrow + i].pos.y *= size.y;
+               }
+       }
+
+       // first seperate the quads and then triangulate
+       Quad *quads = new Quad[quad_num];
+
+       for(int i=0; i<quad_num; i++) {
+               quads[i].vertices[0] = i + i / quads_row;
+               quads[i].vertices[1] = quads[i].vertices[0] + 1;
+               quads[i].vertices[2] = quads[i].vertices[0] + vrow;
+               quads[i].vertices[3] = quads[i].vertices[1] + vrow;
+       }
+
+       for(int i=0; i<quad_num; i++) {
+               tarray[i * 2] = Triangle(quads[i].vertices[0], quads[i].vertices[1], quads[i].vertices[3]);
+               tarray[i * 2 + 1] = Triangle(quads[i].vertices[0], quads[i].vertices[3], quads[i].vertices[2]);
+       }
+
+       for(unsigned long i=0; i<vcount; i++) {
+               varray[i].normal = Vector3(0, 0, -1);
+       }
+
+       // reorient the plane to match the specification
+       Basis b;
+       Vector3 n = normal.normalized();
+       b.k = -n;
+       
+       if(fabs(dot_product(n, Vector3(1, 0, 0))) < 1.0 - small_number) {
+               b.i = Vector3(1, 0, 0);
+               b.j = cross_product(b.k, b.i);
+               b.i = cross_product(b.j, b.k);
+       } else {
+               b.j = Vector3(0, 1, 0);
+               b.i = cross_product(b.j, b.k);
+               b.j = cross_product(b.k, b.i);
+       }
+       
+       Matrix3x3 rot = b.create_rotation_matrix();
+
+       for(unsigned long i=0; i<vcount; i++) {
+               varray[i].pos.transform(rot);
+               varray[i].normal.transform(rot);
+       }
+
+       mesh->set_data(varray, vcount, tarray, tcount);
+
+       delete [] quads;
+       delete [] varray;
+       delete [] tarray;
+}
+
+/* CreateCylinder - (JT)
+ * creates a cylinder by extruding a circle along the y axis, with optional
+ * caps at each end.
+ */
+void create_cylinder(TriMesh *mesh, scalar_t rad, scalar_t len, bool caps, int udiv, int vdiv) {
+       if(udiv < 3) udiv = 3;
+       Vector3 *circle = new Vector3[udiv + 1];
+
+       // generate the circle
+       Vector3 cgen(0.0, -len / 2.0, rad);
+       
+       for(int i=0; i<udiv; i++) {
+               Matrix3x3 mat;
+               mat.set_rotation(Vector3(0.0, two_pi * (scalar_t)i / (scalar_t)udiv, 0.0));
+               circle[i] = cgen.transformed(mat);
+       }
+       circle[udiv] = cgen;
+
+       // extrude along y
+       int slices = vdiv + 2;
+       int vcount = (udiv + 1) * slices + (caps ? 2 * (udiv + 2) : 0);
+       Vertex *verts = new Vertex[vcount];
+       scalar_t yoffs = len / (vdiv + 1);
+
+       Vertex *vptr = verts;
+       for(int i=0; i<slices; i++) {
+               for(int j=0; j<=udiv; j++) {
+                       vptr->pos = circle[j];
+                       vptr->pos.y += yoffs * i;
+                       vptr->normal = circle[j];
+                       vptr->normal.y = 0.0;
+                       vptr->normal /= rad;
+                       scalar_t u = (scalar_t)j / (scalar_t)udiv;
+                       scalar_t v = (scalar_t)i / (scalar_t)(vdiv + 1);
+                       vptr->tex[0] = vptr->tex[1] = TexCoord(u, v);
+                       vptr++;
+               }
+       }
+
+       if(caps) {
+               Vertex *cap1 = vptr;
+               Vertex *cap2 = vptr + udiv + 2;
+               
+               for(int i=0; i<=udiv; i++) {
+                       circle[i].y = -len/2.0;
+                       cap1->pos = circle[i];
+                       cap1->normal = Vector3(0.0, -1.0, 0.0);
+                       //cap1->tex[0] = vptr->tex[1] = TexCoord((scalar_t)i / (scalar_t)udiv, 0.0);
+                       cap1->tex[0].u = cap1->tex[1].u = (cap1->pos.x / rad) * 0.5 + 0.5;
+                       cap1->tex[0].v = cap1->tex[1].v = (cap1->pos.z / rad) * 0.5 + 0.5;
+                       
+                       *cap2 = *cap1;
+                       cap2->pos.y = len/2.0;
+                       cap2->normal.y *= -1.0;
+                       //cap2->tex[0].v = cap2->tex[1].v = 1.0;
+
+                       cap1++;
+                       cap2++;
+               }
+
+               *cap1 = Vertex(Vector3(0.0, -len/2.0, 0.0), 0.5, 0.5);
+               cap1->normal = Vector3(0.0, -1.0, 0.0);
+
+               *cap2 = *cap1;
+               cap2->pos.y = len/2.0;
+               cap2->normal.y *= -1.0;
+               //cap2->tex[0].v = cap2->tex[1].v = 1.0;
+       }
+       delete [] circle;
+
+       // triangulate
+       int tcount = 2 * udiv * (slices - 1) + (caps ? udiv * 2 : 0);
+       Triangle *triangles = new Triangle[tcount];
+       Triangle *tptr = triangles;
+       int v = 0;
+       for(int i=0; i<slices-1; i++) {
+               for(int j=0; j<udiv; j++) {
+                       *tptr++ = Triangle(v + udiv + 1, v + 1, v + udiv + 2);
+                       *tptr++ = Triangle(v + udiv + 1, v, v + 1);
+                       v++;
+               }
+               v++;
+       }
+
+       if(caps) {
+               v += udiv + 1;
+               int v2 = v + udiv + 2;
+               Triangle *tcap2 = tptr + udiv;
+               for(int i=0; i<udiv; i++) {
+                       *tptr++ = Triangle(v + udiv + 1, v + i + 1, v + i);
+                       *tcap2++ = Triangle(v2 + udiv + 1, v2 + i, v2 + i + 1);
+               }               
+       }
+       
+       mesh->set_data(verts, vcount, triangles, tcount);
+
+       delete [] verts;
+       delete [] triangles;
+}
+
+/* CreateSphere - (MG)
+ * creates a sphere as a solid of revolution
+ */
+void create_sphere(TriMesh *mesh, scalar_t radius, int subdiv) {
+       // Solid of revolution. A slice of pi rads is rotated
+       // for 2pi rads. Subdiv in this revolution should be
+       // double than subdiv of the slice, because the angle
+       // is double.
+
+       unsigned long edges_pi  = 2 * subdiv;
+       unsigned long edges_2pi = 4 * subdiv;
+       
+       unsigned long vcount_pi  = edges_pi  + 1;
+       unsigned long vcount_2pi = edges_2pi + 1;
+
+       unsigned long vcount = vcount_pi * vcount_2pi;
+       
+       unsigned long quad_count = edges_pi * edges_2pi;
+       unsigned long tcount = quad_count * 2;
+       
+       Vertex *varray = new Vertex[vcount];
+       Triangle *tarray = new Triangle[tcount];
+
+       for(unsigned long j = 0; j < vcount_pi; j++) {
+               for(unsigned long i = 0; i < vcount_2pi; i++) {
+
+                       Vector3 up_vec(0,1,0);
+
+                       scalar_t rotx,roty;
+                       rotx = -(pi * j) / (vcount_pi - 1);
+                       roty = -(two_pi * i) / (vcount_2pi - 1);
+                       
+                       Matrix4x4 rot_mat;
+                       rot_mat.set_rotation(Vector3(rotx, 0, 0));
+                       up_vec.transform(rot_mat);
+                       rot_mat.set_rotation(Vector3(0, roty, 0));
+                       up_vec.transform(rot_mat);
+
+                       scalar_t u = (scalar_t)i / (scalar_t)(vcount_2pi - 1);
+                       scalar_t v = 1.0 - (scalar_t)j / (scalar_t)(vcount_pi - 1);
+                       varray[j * vcount_2pi + i] = Vertex(up_vec * radius, u, v, Color(1.0f));
+                       varray[j * vcount_2pi + i].normal = up_vec; 
+               }
+       }
+
+       // first seperate the quads and then triangulate
+       Quad *quads = new Quad[quad_count];
+
+       for(unsigned long i=0; i<quad_count; i++) {
+
+               unsigned long hor_edge,vert_edge;
+               hor_edge  = i % edges_2pi;
+               vert_edge = i / edges_2pi;
+               
+               quads[i].vertices[0] = hor_edge + vert_edge * vcount_2pi;
+               quads[i].vertices[1] = quads[i].vertices[0] + 1;
+               quads[i].vertices[2] = quads[i].vertices[0] + vcount_2pi;
+               quads[i].vertices[3] = quads[i].vertices[1] + vcount_2pi;
+       }
+
+       for(unsigned long i=0; i<quad_count; i++) {
+               tarray[i * 2] = Triangle(quads[i].vertices[0], quads[i].vertices[1], quads[i].vertices[3]);
+               tarray[i * 2 + 1] = Triangle(quads[i].vertices[0], quads[i].vertices[3], quads[i].vertices[2]);
+       }
+
+       mesh->set_data(varray, vcount, tarray, tcount);
+
+       delete [] quads;
+       delete [] varray;
+       delete [] tarray;
+}
+
+/* CreateTorus - (MG)
+ * Creates a toroid mesh
+ */
+void create_torus(TriMesh *mesh, scalar_t circle_rad, scalar_t revolv_rad, int subdiv) {
+       unsigned long edges_2pi  = 4 * subdiv;
+       unsigned long vcount_2pi = edges_2pi + 1;
+
+       unsigned long vcount = vcount_2pi * vcount_2pi;
+       unsigned long qcount = edges_2pi * edges_2pi;
+       unsigned long tcount = qcount * 2;
+
+       // alloc mamory
+       Vertex   *varray = new Vertex[vcount];
+       Quad     *qarray = new Quad[qcount];
+       Triangle *tarray = new Triangle[tcount];
+       Vertex   *circle = new Vertex[vcount_2pi];
+       
+       // first create a circle
+       // rotation of this circle will produce the torus
+       for (unsigned long i = 0; i < vcount_2pi; i++)
+       {
+               scalar_t t = (scalar_t)i / (scalar_t)(vcount_2pi - 1);
+               
+               Vector3 up_vec = Vector3(0, 1, 0);
+               Matrix4x4 rot_mat;
+               rot_mat.set_rotation(Vector3(0, 0, two_pi * t));
+               up_vec.transform(rot_mat);
+
+               Vector3 pos_vec = up_vec * circle_rad;
+               pos_vec += Vector3(revolv_rad, 0, 0);
+
+               circle[i] = Vertex(pos_vec, 0, t, Color(1.0f));
+               circle[i].normal = up_vec;
+       }
+
+       // vertex loop
+       for (unsigned long j = 0; j < vcount_2pi; j++)
+       {
+               for (unsigned long i = 0; i < vcount_2pi; i++)
+               {
+                       scalar_t t = (scalar_t)i / (scalar_t)(vcount_2pi - 1);
+                       
+                       Vector3 pos,nor;
+                       pos = circle[j].pos;
+                       nor = circle[j].normal;
+
+                       Matrix4x4 rot_mat;
+                       rot_mat.set_rotation(Vector3(0, two_pi * t, 0));
+                       pos.transform(rot_mat);
+                       nor.transform(rot_mat);
+
+                       unsigned long index = i + vcount_2pi * j;
+
+                       varray[index] = Vertex(pos, t, 1.0 - circle[j].tex[0].v, Color(1.0f));
+                       varray[index].normal = nor;
+               }
+       } // End vertex loop
+
+       
+       for(unsigned long i=0; i<qcount; i++) {
+
+               unsigned long hor_edge,vert_edge;
+               hor_edge  = i % edges_2pi;
+               vert_edge = i / edges_2pi;
+               
+               qarray[i].vertices[0] = hor_edge + vert_edge * vcount_2pi;
+               qarray[i].vertices[1] = qarray[i].vertices[0] + 1;
+               qarray[i].vertices[2] = qarray[i].vertices[0] + vcount_2pi;
+               qarray[i].vertices[3] = qarray[i].vertices[1] + vcount_2pi;
+       }
+       
+       for(unsigned long i=0; i<qcount; i++) {
+               tarray[i * 2] = Triangle(qarray[i].vertices[0], qarray[i].vertices[1], qarray[i].vertices[3]);
+               tarray[i * 2 + 1] = Triangle(qarray[i].vertices[0], qarray[i].vertices[3], qarray[i].vertices[2]);
+       }
+
+       mesh->set_data(varray, vcount, tarray, tcount);
+       
+       // cleanup
+       delete [] varray;
+       delete [] qarray;
+       delete [] tarray;
+       delete [] circle;
+}
+
+
+/* create_revolution - (JT)
+ * Creates a surface of revolution by rotating a curve around the Y axis.
+ */
+void create_revolution(TriMesh *mesh, const Curve &curve, int udiv, int vdiv) {
+       if(udiv < 3) udiv = 3;
+       if(vdiv < 1) vdiv = 1;
+
+       int slices = udiv;
+       int stacks = vdiv + 1;
+
+       // create the slice that will be revolved to create the mesh
+       Vector3 *slice = new Vector3[stacks];
+       Vector3 *slice_normal = new Vector3[stacks];
+       
+       for(int i=0; i<stacks; i++) {
+               scalar_t t = (scalar_t)i / (scalar_t)vdiv;
+               slice[i] = curve(t);
+
+               // calculate normal
+               Vector3 bitangent = (curve(t + 0.0001) - curve(t - 0.0001)).normalized();
+               Vector3 tp1 = slice[i].rotated(Vector3(0.0, DEG_TO_RAD(3), 0.0));
+               Vector3 tp2 = slice[i].rotated(Vector3(0.0, -DEG_TO_RAD(3), 0.0));
+               Vector3 tangent = (tp1 - tp2).normalized();
+
+               slice_normal[i] = cross_product(tangent, bitangent);
+       }
+       
+       int vcount = stacks * slices;
+       int quad_count = udiv * vdiv;
+       int tcount = quad_count * 2;
+       
+       Vertex *varray = new Vertex[vcount];
+       Triangle *tarray = new Triangle[tcount];
+
+       Vertex *vptr = varray;
+       Triangle *tptr = tarray;
+       
+       for(int i=0; i<slices; i++) {
+               Matrix4x4 rot;
+               rot.set_rotation(Vector3(0.0, two_pi * (scalar_t)i / (scalar_t)udiv, 0.0));
+               
+               for(int j=0; j<stacks; j++) {
+                       // create the vertex
+                       vptr->pos = slice[j].transformed(rot);
+                       vptr->tex[0].u = vptr->tex[1].u = (scalar_t)i / (scalar_t)udiv;
+                       vptr->tex[0].v = vptr->tex[1].v = (scalar_t)j / (scalar_t)vdiv;
+                       vptr->normal = slice_normal[j].transformed(rot);
+                       vptr++;
+
+                       if(j < vdiv) {
+                               // create the quad
+                               Quad q;
+                               q.vertices[0] = j + (i % slices) * stacks;
+                               q.vertices[1] = j + ((i + 1) % slices) * stacks;
+                               q.vertices[2] = (j + 1) + ((i + 1) % slices) * stacks;
+                               q.vertices[3] = (j + 1) + (i % slices) * stacks;
+
+                               // triangulate
+                               tptr->vertices[0] = q.vertices[0];
+                               tptr->vertices[1] = q.vertices[1];
+                               tptr->vertices[2] = q.vertices[2];
+                               tptr++;
+                               tptr->vertices[0] = q.vertices[0];
+                               tptr->vertices[1] = q.vertices[2];
+                               tptr->vertices[2] = q.vertices[3];
+                               tptr++;
+                       }
+               }
+       }
+
+       mesh->set_data(varray, vcount, tarray, tcount);
+       delete [] varray;
+       delete [] tarray;
+       delete [] slice;
+       delete [] slice_normal;
+}
+
+/* create_revolution - helper function - (JT)
+ * accepts an array of data points, fits a spline through them and passes the rest
+ * to the real create_revolution defined above.
+ */
+void create_revolution(TriMesh *mesh, const Vector3 *data, int count, int udiv, int vdiv) {
+       CatmullRomSplineCurve spline;
+       for(int i=0; i<count; i++) {
+               spline.add_control_point(data[i]);
+       }
+       spline.set_arc_parametrization(true);
+
+       create_revolution(mesh, spline, udiv, vdiv);
+}
+
+/* create_extrusion - (JT)
+ * Takes a shape and extrudes it along a path.
+ */
+void create_extrusion(TriMesh *mesh, const Curve &shape, const Curve &path, int udiv, int vdiv, scalar_t start_scale, scalar_t end_scale) {
+       if(udiv < 3) udiv = 3;
+       Vector3 *shape_pt = new Vector3[udiv + 1];
+
+       for(int i=0; i<udiv; i++) {
+               shape_pt[i] = shape((scalar_t)i / (scalar_t)udiv);
+       }
+       shape_pt[udiv] = shape_pt[0];
+
+       // extrude along the spline
+       int slices = vdiv + 2;
+       int vcount = (udiv + 1) * slices;
+       Vertex *verts = new Vertex[vcount];
+       scalar_t dt = 1.0 / (vdiv + 1);
+
+       Vertex *vptr = verts;
+       for(int i=0; i<slices; i++) {
+               for(int j=0; j<=udiv; j++) {
+                       // XXX FIX THIS
+                       vptr->pos = shape_pt[j];
+                       vptr->pos.y += dt * i;
+                       scalar_t u = (scalar_t)j / (scalar_t)udiv;
+                       scalar_t v = (scalar_t)i / (scalar_t)(vdiv + 1);
+                       vptr->tex[0] = vptr->tex[1] = TexCoord(u, v);
+                       vptr++;
+               }
+       }
+
+       delete [] shape_pt;
+
+       // triangulate
+       int tcount = 2 * udiv * (slices - 1);
+       Triangle *triangles = new Triangle[tcount];
+       Triangle *tptr = triangles;
+       int v = 0;
+       for(int i=0; i<slices-1; i++) {
+               for(int j=0; j<udiv; j++) {
+                       *tptr++ = Triangle(v + udiv + 1, v + 1, v + udiv + 2);
+                       *tptr++ = Triangle(v + udiv + 1, v, v + 1);
+                       v++;
+               }
+               v++;
+       }
+
+       mesh->set_data(verts, vcount, triangles, tcount);
+       mesh->calculate_normals();
+
+       delete [] verts;
+       delete [] triangles;
+}
+
+/* CreateBezierPatch - (MG)
+ * overloaded function that gets a vector3 array
+ * and makes a single Bezier patch
+ */
+void create_bezier_patch(TriMesh *mesh, const Vector3 *cp, int subdiv)
+{
+
+       // make 8 BezierSpline's
+       BezierSpline u[4], v[4];
+
+       u[0].add_control_point(cp[0]);
+       u[0].add_control_point(cp[1]);
+       u[0].add_control_point(cp[2]);  
+       u[0].add_control_point(cp[3]);
+       
+       u[1].add_control_point(cp[4]);
+       u[1].add_control_point(cp[5]);
+       u[1].add_control_point(cp[6]);  
+       u[1].add_control_point(cp[7]);
+       
+       u[2].add_control_point(cp[8]);
+       u[2].add_control_point(cp[9]);
+       u[2].add_control_point(cp[10]); 
+       u[2].add_control_point(cp[11]);
+       
+       u[3].add_control_point(cp[12]);
+       u[3].add_control_point(cp[13]);
+       u[3].add_control_point(cp[14]); 
+       u[3].add_control_point(cp[15]);
+
+       v[0].add_control_point(cp[0]);
+       v[0].add_control_point(cp[4]);
+       v[0].add_control_point(cp[8]);  
+       v[0].add_control_point(cp[12]);
+       
+       v[1].add_control_point(cp[1]);
+       v[1].add_control_point(cp[5]);
+       v[1].add_control_point(cp[9]);  
+       v[1].add_control_point(cp[13]);
+       
+       v[2].add_control_point(cp[2]);
+       v[2].add_control_point(cp[6]);
+       v[2].add_control_point(cp[10]); 
+       v[2].add_control_point(cp[14]);
+
+       v[3].add_control_point(cp[3]);
+       v[3].add_control_point(cp[7]);
+       v[3].add_control_point(cp[11]); 
+       v[3].add_control_point(cp[15]);
+
+       unsigned long edges = subdiv * 2;
+       unsigned long vrow = edges + 1;
+       unsigned long qcount = edges * edges;
+       unsigned long vcount = vrow * vrow;
+       unsigned long tcount = qcount * 2;
+
+       // allocate memory
+       Vertex *varray = new Vertex[vcount];
+       Quad *qarray = new Quad[qcount];
+       Triangle *tarray = new Triangle[tcount];
+
+       // Vertex loop
+       for (unsigned long j=0; j<vrow; j++)
+       {
+               scalar_t tv = (scalar_t)j / (scalar_t)(vrow - 1);
+               BezierSpline uc;
+               uc.add_control_point(v[0](tv));
+               uc.add_control_point(v[1](tv));
+               uc.add_control_point(v[2](tv));
+               uc.add_control_point(v[3](tv));
+               
+               for (unsigned long i=0; i<vrow; i++)
+               {
+                       scalar_t tu = (scalar_t)i / (scalar_t)(vrow - 1);
+                       BezierSpline vc;
+                       vc.add_control_point(u[0](tu));
+                       vc.add_control_point(u[1](tu));
+                       vc.add_control_point(u[2](tu));
+                       vc.add_control_point(u[3](tu));
+
+                       // get the position
+                       Vector3 pos = uc(tu);
+
+                       // get normal
+                       Vector3 tan_u,tan_v;
+                       tan_u = uc.get_tangent(tu);
+                       tan_v = vc.get_tangent(tv);
+                       Vector3 normal;
+                       normal = cross_product(tan_u, tan_v);
+                       normal.normalize();
+
+                       // store vertex
+                       varray[i + j * vrow] = Vertex(pos, tu, 1.0 - tv, Color(1.0f));
+                       varray[i + j * vrow].normal = normal;
+               }
+       } // end vertex loop
+
+       
+       // first seperate the quads and then triangulate
+       for(unsigned long i=0; i<qcount; i++) {
+               qarray[i].vertices[0] = i + i / edges;
+               qarray[i].vertices[1] = qarray[i].vertices[0] + 1;
+               qarray[i].vertices[2] = qarray[i].vertices[0] + vrow;
+               qarray[i].vertices[3] = qarray[i].vertices[1] + vrow;
+       }
+
+       for(unsigned long i=0; i<qcount; i++) {
+               tarray[i * 2] = Triangle(qarray[i].vertices[0], qarray[i].vertices[1], qarray[i].vertices[3]);
+               tarray[i * 2 + 1] = Triangle(qarray[i].vertices[0], qarray[i].vertices[3], qarray[i].vertices[2]);
+       }
+
+       mesh->set_data(varray, vcount, tarray, tcount);
+       
+       // cleanup
+       delete [] varray;
+       delete [] qarray;
+       delete [] tarray;
+}
+
+/* CreateBezierPatch - (MG)
+ * creates a bezier patch (!)
+ * if the control curves contain more than one 
+ * segments, multiple patches will be included
+ * in the output TriMesh
+ */
+void create_bezier_patch(TriMesh *mesh, const BezierSpline &u0, const BezierSpline &u1, const BezierSpline &u2, const BezierSpline &u3, int subdiv)
+{
+       // get minimum number of segments
+       unsigned long min_seg , tmp;
+       min_seg = u0.get_segment_count();
+       tmp = u1.get_segment_count(); if (min_seg > tmp) min_seg = tmp;
+       tmp = u2.get_segment_count(); if (min_seg > tmp) min_seg = tmp;
+       tmp = u3.get_segment_count(); if (min_seg > tmp) min_seg = tmp;
+
+       TriMesh tmp_mesh;
+       Vector3 *cp = new Vector3[16];
+       for (unsigned long i=0; i<min_seg; i++)
+       {
+               // fill control point array
+               cp[0] = u0.get_control_point(4 * i + 0);
+               cp[1] = u0.get_control_point(4 * i + 1);
+               cp[2] = u0.get_control_point(4 * i + 2);
+               cp[3] = u0.get_control_point(4 * i + 3);
+
+               cp[4] = u1.get_control_point(4 * i + 0);
+               cp[5] = u1.get_control_point(4 * i + 1);
+               cp[6] = u1.get_control_point(4 * i + 2);
+               cp[7] = u1.get_control_point(4 * i + 3);
+               
+               cp[8] = u2.get_control_point(4 * i + 0);
+               cp[9] = u2.get_control_point(4 * i + 1);
+               cp[10] = u2.get_control_point(4 * i + 2);
+               cp[11] = u2.get_control_point(4 * i + 3);
+                       
+               cp[12] = u3.get_control_point(4 * i + 0);
+               cp[13] = u3.get_control_point(4 * i + 1);
+               cp[14] = u3.get_control_point(4 * i + 2);
+               cp[15] = u3.get_control_point(4 * i + 3);
+
+               // Make a single patch and put all patches together     
+               create_bezier_patch(&tmp_mesh, cp, subdiv);
+
+               join_tri_mesh(mesh, mesh, &tmp_mesh);
+       }
+
+       // cleanup
+       delete [] cp;
+}
+
+/* CreateBezierMesh - (MG)
+ * tesselates a whole mesh of bezier patches.
+ * usefull when some patches share vertices
+ * TODO : Make a bezier patch class , like Triangle
+ * and Quad. Store indices
+ */
+void create_bezier_mesh(TriMesh *mesh, const Vector3 *cp, unsigned int *patches, int patch_count, int subdiv)
+{
+       TriMesh tmp_mesh;
+       Vector3 control_pts[16];
+       for(int i=0; i<patch_count; i++)
+       {
+               for(int j=0; j<16; j++)
+               {
+                       control_pts[j] = cp[ patches[16 * i + j] ];
+               }
+
+               create_bezier_patch(&tmp_mesh, control_pts, subdiv);
+
+               join_tri_mesh(mesh, mesh, &tmp_mesh);
+       }
+}
+
+/* CreateTeapot - (MG)
+ * Creates a teapot TriMesh, using the original
+ * data file from Newell
+ */
+void create_teapot(TriMesh *mesh, scalar_t size, int subdiv)
+{
+       unsigned int *patches = new unsigned int[teapot_num_patches * 16];
+       
+       // fix indices to start from zero
+       for(int i=0; i<teapot_num_patches * 16; i++)
+       {
+               patches[i] = teapot_patches[i] - 1;
+       }
+
+               
+       // rearrange patches to clockwise order
+       for(int p=0; p<teapot_num_patches; p++)
+       {
+               unsigned int new_order[16];
+               for(int j=0; j<4; j++)
+               {
+                       for(int i=0; i<4; i++)
+                       {
+                               new_order[j * 4 + (3 - i)] = patches[p * 16 + j * 4 + i];
+                       }
+               }
+
+               for(int k=0; k<16; k++)
+               {
+                       patches[16 * p + k] = new_order[k];
+               }
+       }
+
+       // rearrange vertices to correct axes
+       Vector3 *vertices = new Vector3[teapot_num_vertices];
+       for(int i = 0; i < teapot_num_vertices; i++)
+       {
+               vertices[i].x = teapot_vertices[i * 3 + 0] * size;
+               vertices[i].z = teapot_vertices[i * 3 + 1] * size;
+               vertices[i].y = teapot_vertices[i * 3 + 2] * size;
+       }
+       
+       create_bezier_mesh(mesh, vertices, patches, teapot_num_patches, subdiv);
+
+       mesh->calculate_normals();
+
+       // cleanup
+       delete [] patches;
+       delete [] vertices;
+}
+
+
+// fractal stuff ...
+
+/* create_landscape (JT)
+ * Creates a fractal landscape... (TODO: add algorithm description or something)
+ */
+void create_landscape(TriMesh *mesh, const Vector2 &size, int mesh_detail, scalar_t max_height, int iter, scalar_t roughness, int seed) {
+       create_plane(mesh, Vector3(0, 1, 0), size, mesh_detail);
+       roughness *= 0.25;
+
+       if(seed == GGEN_RANDOM_SEED) {
+               srand(time(0));
+       } else if(seed != GGEN_NO_RESEED) {
+               srand(seed);
+       }
+
+       scalar_t offs = max_height / (scalar_t)iter;
+
+       unsigned long vcount = mesh->get_vertex_array()->get_count();
+       Vertex *varray = mesh->get_mod_vertex_array()->get_mod_data();
+
+       for(int i=0; i<iter; i++) {
+               // pick a partitioning line (2d)
+               Vector2 pt1(frand(size.x) - size.x / 2.0, frand(size.y) - size.y / 2.0);
+               Vector2 pt2(frand(size.x) - size.x / 2.0, frand(size.y) - size.y / 2.0);
+
+               // find its normal
+               Vector2 normal(pt2.y - pt1.y, pt1.x - pt2.x);
+
+               // classify all points wrt. this line and raise them accordingly.
+               for(unsigned long j=0; j<vcount; j++) {
+                       Vector3 *vpos = &varray[j].pos;
+                       Vector2 vpos2d(vpos->x, vpos->z);
+                       
+                       scalar_t dist = dist_line(pt1, pt2, vpos2d);
+                       
+                       /* this was considered but it was producing extremely smooth
+                        * results, which looked unnatural.
+                        */
+                       /* 
+                       if(dot_product(normal, vpos2d - pt1) < 0.0) {
+                               dist = -dist;
+                       }
+                       scalar_t sigmoid = (tanh(dist * size.x * size.y * roughness) + 1.0) * 0.5;
+                       vpos->y += offs * sigmoid;
+                       */
+
+                       if(dot_product(normal, vpos2d - pt1) > 0.0) {
+                               scalar_t sigmoid = tanh(dist * size.x * size.y * roughness);
+                               vpos->y += offs * sigmoid;
+                       }
+               }
+       }
+
+       // normalize the landscape in the range [0, max_height)
+       scalar_t hmin = FLT_MAX, hmax = 0.0;
+       Vertex *vptr = varray;
+
+       for(unsigned long i=0; i<vcount; i++) {
+               if(vptr->pos.y > hmax) hmax = vptr->pos.y;
+               if(vptr->pos.y < hmin) hmin = vptr->pos.y;
+               vptr++;
+       }
+
+       vptr = varray;
+       for(unsigned long i=0; i<vcount; i++) {
+               vptr->pos.y = max_height * (vptr->pos.y - hmin) / (hmax - hmin);
+               vptr++;
+       }
+
+       mesh->calculate_normals();
+}
diff --git a/src/3dengfx/src/3dengfx/ggen.hpp b/src/3dengfx/src/3dengfx/ggen.hpp
new file mode 100644 (file)
index 0000000..bf2ba9b
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+This file is part of the 3dengfx, realtime visualization system.
+
+Copyright (c) 2004, 2005, 2006 John Tsiombikas <nuclear@siggraph.org>
+
+3dengfx is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+3dengfx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with 3dengfx; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* geometry generation
+ * 
+ * author: John Tsiombikas 2004
+ * modified: 
+ *             Mihalis Georgoulopoulos 2004, 2005
+ *             John Tsiombikas 2005
+ */
+
+#ifndef _GGEN_HPP_
+#define _GGEN_HPP_
+
+#include "n3dmath2/n3dmath2.hpp"
+#include "gfx/3dgeom.hpp"
+
+// basic primitives
+void create_cube(TriMesh *mesh, scalar_t size, int subdiv);
+void create_plane(TriMesh *mesh, const Vector3 &normal, const Vector2 &size, int subdiv);
+void create_cylinder(TriMesh *mesh, scalar_t rad, scalar_t len, bool caps, int udiv, int vdiv);
+void create_sphere(TriMesh *mesh, scalar_t radius, int subdiv);
+void create_torus(TriMesh *mesh, scalar_t circle_rad, scalar_t revolv_rad, int subdiv);
+
+// surfaces of revolution
+void create_revolution(TriMesh *mesh, const Curve &curve, int udiv, int vdiv);
+void create_revolution(TriMesh *mesh, const Vector3 *data, int count, int udiv, int vdiv);
+
+// path extrude
+void create_extrusion(TriMesh *mesh, const Curve &shape, const Curve &path, int ssamples, int slices, scalar_t start_scale = 1.0, scalar_t end_scale = 1.0);
+
+// bezier surface construction
+void create_bezier_patch(TriMesh *mesh, const BezierSpline &u0, const BezierSpline &u1, const BezierSpline &u2, const BezierSpline &u3, int subdiv);
+void create_bezier_patch(TriMesh *mesh, const Vector3 *cp, int subdiv);
+void create_bezier_mesh(TriMesh *mesh, const Vector3 *cp, unsigned int *patches, int patch_count, int subdiv);
+
+// oddities
+void create_teapot(TriMesh *mesh, scalar_t size, int subdiv);
+
+// fractal stuff
+#define GGEN_NO_RESEED         (-1)
+#define GGEN_RANDOM_SEED       (-2)
+void create_landscape(TriMesh *mesh, const Vector2 &size, int mesh_detail, scalar_t max_height, int iter, scalar_t roughness = 0.5, int seed = -1);
+
+#endif // _GGEN_HPP_
diff --git a/src/3dengfx/src/3dengfx/light.cpp b/src/3dengfx/src/3dengfx/light.cpp
new file mode 100644 (file)
index 0000000..6639690
--- /dev/null
@@ -0,0 +1,199 @@
+/*
+Copyright 2004 John Tsiombikas <nuclear@siggraph.org>
+
+This file is part of 3dengfx, realtime visualization system.
+
+3dengfx is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+3dengfx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with 3dengfx; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "3dengfx_config.h"
+
+#include "3denginefx.hpp"
+#include "opengl.h"
+#include "light.hpp"
+
+Light::Light() {
+       ambient_color = Color(0, 0, 0);
+       diffuse_color = Color(1.0f, 1.0f, 1.0f);
+       specular_color = Color(1.0f, 1.0f, 1.0f);
+       intensity = 1.0f;
+       attenuation[0] = 1.0f;
+       attenuation[1] = 0.0f;
+       attenuation[2] = 0.0f;
+       cast_shadows = false;
+}
+
+Light::~Light() {}
+
+void Light::set_color(const Color &c, unsigned short color_flags) {
+       if(color_flags & LIGHTCOL_AMBIENT) {
+               ambient_color = c;
+       }
+       
+       if(color_flags & LIGHTCOL_DIFFUSE) {
+               diffuse_color = c;
+       }
+       
+       if(color_flags & LIGHTCOL_SPECULAR) {
+               specular_color = c;
+       }
+}
+
+
+void Light::set_color(const Color &amb, const Color &diff, const Color &spec) {
+       ambient_color = amb;
+       diffuse_color = diff;
+       specular_color = spec;
+}
+
+Color Light::get_color(unsigned short which) const {
+       switch(which) {
+       case LIGHTCOL_AMBIENT:
+               return ambient_color;
+               
+       case LIGHTCOL_SPECULAR:
+               return specular_color;
+               
+       case LIGHTCOL_DIFFUSE:
+       default:
+               return diffuse_color;
+       }
+}
+
+void Light::set_intensity(scalar_t intensity) {
+       this->intensity = intensity;
+}
+
+scalar_t Light::get_intensity() const {
+       return intensity;
+}
+
+void Light::set_attenuation(scalar_t att0, scalar_t att1, scalar_t att2) {
+       attenuation[0] = att0;
+       attenuation[1] = att1;
+       attenuation[2] = att2;
+}
+
+scalar_t Light::get_attenuation(int which) const {
+       return attenuation[which];
+}
+
+Vector3 Light::get_attenuation_vector() const {
+       return Vector3(attenuation[0], attenuation[1], attenuation[2]);
+}
+
+void Light::set_shadow_casting(bool shd) {
+       cast_shadows = shd;
+}
+
+bool Light::casts_shadows() const {
+       return cast_shadows;
+}
+
+// ------- point lights -------
+
+PointLight::PointLight(const Vector3 &pos, const Color &col) {
+       set_position(pos);
+       diffuse_color = specular_color = col;
+}
+
+PointLight::~PointLight() {}
+
+void PointLight::set_gl_light(int n, unsigned long time) const {
+       int light_num = GL_LIGHT0 + n;
+       
+       Vector4 pos;
+       if(time == XFORM_LOCAL_PRS) {
+               pos = (Vector4)local_prs.position;
+       } else {
+               pos = (Vector4)get_prs(time).position;
+       }
+       
+       glMatrixMode(GL_MODELVIEW);
+       glPushMatrix();
+       Matrix4x4 test = engfx_state::view_matrix;
+       test.translate(pos);
+       load_matrix_gl(test);
+
+       Color amb = ambient_color * intensity;
+       Color dif = diffuse_color * intensity;
+       Color spec = specular_color * intensity;
+
+       float position[] = {0.0f, 0.0f, 0.0f, 1.0f};
+       float gl_amb[] = {amb.r, amb.g, amb.b, ambient_color.a};
+       float gl_dif[] = {dif.r, dif.g, dif.b, diffuse_color.a};
+       float gl_spec[] = {spec.r, spec.g, spec.b, specular_color.a};
+       
+       glLightfv(light_num, GL_POSITION, position);
+       glLightfv(light_num, GL_AMBIENT, gl_amb);
+       glLightfv(light_num, GL_DIFFUSE, gl_dif);
+       glLightfv(light_num, GL_SPECULAR, gl_spec);
+       glLightf(light_num, GL_CONSTANT_ATTENUATION, (float)attenuation[0]);
+       glLightf(light_num, GL_LINEAR_ATTENUATION, (float)attenuation[1]);
+       glLightf(light_num, GL_QUADRATIC_ATTENUATION, (float)attenuation[2]);
+       
+       glEnable(light_num);
+       
+       glPopMatrix();
+
+       if(!engfx_state::bump_light) set_bump_light(this);
+}
+
+
+
+// ------- directional lights -------
+
+DirLight::DirLight(const Vector3 &dir, const Color &col) {
+       this->dir = dir;
+       diffuse_color = specular_color = col;
+}
+
+DirLight::~DirLight() {}
+
+Vector3 DirLight::get_direction()
+{
+       return dir;
+}
+
+void DirLight::set_gl_light(int n, unsigned long time) const {
+       int light_num = GL_LIGHT0 + n;
+       
+       Vector3 ldir = dir.transformed(get_prs(time).rotation);
+       
+       glMatrixMode(GL_MODELVIEW);
+       glPushMatrix();
+       Matrix4x4 test = engfx_state::view_matrix;
+       load_matrix_gl(test);
+
+       Color amb = ambient_color * intensity;
+       Color dif = diffuse_color * intensity;
+       Color spec = specular_color * intensity;
+
+       float position[] = {-ldir.x, -ldir.y, -ldir.z, 0.0f};
+       float gl_amb[] = {amb.r, amb.g, amb.b, ambient_color.a};
+       float gl_dif[] = {dif.r, dif.g, dif.b, diffuse_color.a};
+       float gl_spec[] = {spec.r, spec.g, spec.b, specular_color.a};
+       
+       glLightfv(light_num, GL_POSITION, position);
+       glLightfv(light_num, GL_AMBIENT, gl_amb);
+       glLightfv(light_num, GL_DIFFUSE, gl_dif);
+       glLightfv(light_num, GL_SPECULAR, gl_spec);
+       
+       glEnable(light_num);
+       
+       glPopMatrix();
+
+       if(!engfx_state::bump_light) set_bump_light(this);
+}
diff --git a/src/3dengfx/src/3dengfx/light.hpp b/src/3dengfx/src/3dengfx/light.hpp
new file mode 100644 (file)
index 0000000..1259de0
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+Copyright 2004 John Tsiombikas <nuclear@siggraph.org>
+
+This file is part of the 3dengfx, realtime visualization system.
+
+3dengfx is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+3dengfx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with 3dengfx; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#ifndef _LIGHT_HPP_
+#define _LIGHT_HPP_
+
+#include <string>
+#include "n3dmath2/n3dmath2.hpp"
+#include "gfx/animation.hpp"
+#include "gfx/color.hpp"
+
+#define LIGHTCOL_AMBIENT       1
+#define LIGHTCOL_DIFFUSE       2
+#define LIGHTCOL_SPECULAR      4
+
+// abstract base class Light
+class Light : public XFormNode {
+protected:
+       Color ambient_color, diffuse_color, specular_color;
+       scalar_t intensity;
+       scalar_t attenuation[3];
+       bool cast_shadows;
+
+public:
+       Light();
+       virtual ~Light();
+       
+       virtual void set_color(const Color &c, unsigned short color_flags = 0);
+       virtual void set_color(const Color &amb, const Color &diff, const Color &spec);
+       virtual Color get_color(unsigned short which) const;
+       
+       virtual void set_intensity(scalar_t intensity);
+       virtual scalar_t get_intensity() const;
+       
+       virtual void set_attenuation(scalar_t att0, scalar_t att1, scalar_t att2);
+       virtual scalar_t get_attenuation(int which) const;
+       virtual Vector3 get_attenuation_vector() const;
+
+       virtual void set_shadow_casting(bool shd);
+       virtual bool casts_shadows() const;
+       
+       virtual void set_gl_light(int n, unsigned long time = XFORM_LOCAL_PRS) const = 0;
+};
+
+
+class PointLight : public Light {
+public:
+       PointLight(const Vector3 &pos=Vector3(0,0,0), const Color &col=Color(1.0f, 1.0f, 1.0f));
+       virtual ~PointLight();
+
+       virtual void set_gl_light(int n, unsigned long time = XFORM_LOCAL_PRS) const;
+};
+
+class DirLight : public Light {
+private:
+       Vector3 dir;    // actually get rid of this and work with the PRS directly?
+
+public:
+       DirLight(const Vector3 &dir=Vector3(0, 0, 1), const Color &col=Color(1.0f, 1.0f, 1.0f));
+       virtual ~DirLight();
+
+       Vector3 get_direction();
+       
+       virtual void set_gl_light(int n, unsigned long time = XFORM_LOCAL_PRS) const;
+};
+
+#endif // _LIGHT_HPP_
diff --git a/src/3dengfx/src/3dengfx/makefile.part b/src/3dengfx/src/3dengfx/makefile.part
new file mode 100644 (file)
index 0000000..b2d8698
--- /dev/null
@@ -0,0 +1,18 @@
+3dengfx_obj = \
+       src/3dengfx/3denginefx.o\
+       src/3dengfx/textures.o\
+       src/3dengfx/camera.o\
+       src/3dengfx/material.o\
+       src/3dengfx/object.o\
+       src/3dengfx/texman.o\
+       src/3dengfx/light.o\
+       src/3dengfx/ggen.o\
+       src/3dengfx/3dscene.o\
+       src/3dengfx/sceneloader.o\
+       src/3dengfx/gfxprog.o\
+       src/3dengfx/psys.o\
+       src/3dengfx/scfield.o\
+       src/3dengfx/rend_curve.o\
+       src/3dengfx/sdrman.o\
+       src/3dengfx/ply.o\
+       src/3dengfx/shadows.o
diff --git a/src/3dengfx/src/3dengfx/material.cpp b/src/3dengfx/src/3dengfx/material.cpp
new file mode 100644 (file)
index 0000000..10f8f3b
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+Copyright 2004 John Tsiombikas <nuclear@siggraph.org>
+
+This file is part of the 3dengfx, realtime visualization system.
+
+3dengfxis free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+3dengfx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with 3dengfx; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "3dengfx_config.h"
+
+#include "opengl.h"
+#include "material.hpp"
+
+Material::Material() {
+       ambient_color = diffuse_color = Color(1.0f, 1.0f, 1.0f);
+       specular_color = emissive_color = Color(0.0f, 0.0f, 0.0f);
+       
+       specular_power = 1.0f;
+       env_intensity = 1.0f;
+       bump_intensity = 1.0f;
+       alpha = 1.0f;
+
+       wireframe = false;
+       shading = SHADING_GOURAUD;
+
+       auto_refl = true;
+       auto_refl_upd = 1;
+
+       two_sided = false;
+
+       tex_count = 0;
+       
+       memset(tex, 0, MAX_TEXTURES * sizeof(Texture*));
+}
+
+Material::Material(const Color &col) {
+       ambient_color = diffuse_color = col;
+       specular_color = emissive_color = Color(0.0f, 0.0f, 0.0f);
+       
+       specular_power = 1.0f;
+       env_intensity = 1.0f;
+       bump_intensity = 1.0f;
+       alpha = 1.0f;
+       
+       wireframe = false;
+       shading = SHADING_GOURAUD;
+
+       auto_refl = true;
+       auto_refl_upd = 1;
+
+       tex_count = 0;
+       
+       memset(tex, 0, MAX_TEXTURES * sizeof(Texture*));
+}
+
+void Material::set_texture(Texture *texture, TextureType type) {
+       if(texture) tex_count++;
+       tex[type] = texture;
+}
+
+Texture *Material::get_texture(TextureType type) {
+       return tex[type];
+}
+
+int Material::get_texture_count() const {
+       return tex_count;
+}
+
+void Material::set_glmaterial() const {
+       float amb[] = {ambient_color.r, ambient_color.g, ambient_color.b, ambient_color.a};
+       float dif[] = {diffuse_color.r, diffuse_color.g, diffuse_color.b, diffuse_color.a};
+       float spc[] = {specular_color.r, specular_color.g, specular_color.b, specular_color.a};
+       float ems[] = {emissive_color.r, emissive_color.g, emissive_color.b, emissive_color.a};
+
+       amb[3] *= alpha;
+       dif[3] *= alpha;
+       spc[3] *= alpha;
+       ems[3] *= alpha;
+       
+       glMaterialfv(GL_FRONT, GL_AMBIENT, amb);
+       glMaterialfv(GL_FRONT, GL_DIFFUSE, dif);
+       glMaterialfv(GL_FRONT, GL_SPECULAR, spc);
+       glMaterialfv(GL_FRONT, GL_EMISSION, ems);
+       glMaterialf(GL_FRONT, GL_SHININESS, specular_power);
+}
diff --git a/src/3dengfx/src/3dengfx/material.hpp b/src/3dengfx/src/3dengfx/material.hpp
new file mode 100644 (file)
index 0000000..55acaa1
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+Copyright 2004 John Tsiombikas <nuclear@siggraph.org>
+
+This file is part of the 3dengfx, realtime visualization system.
+
+3dengfx is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+3dengfx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with 3dengfx; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#ifndef _MATERIALS_HPP_
+#define _MATERIALS_HPP_
+
+#include <string>
+#include "3denginefx_types.hpp"
+#include "textures.hpp"
+#include "gfx/color.hpp"
+#include "n3dmath2/n3dmath2.hpp"
+
+enum ColorComponent {
+       COLOR_AMBIENT,
+       COLOR_DIFFUSE,
+       COLOR_SPECULAR,
+       COLOR_EMISSIVE
+};
+
+enum TextureType {
+       TEXTYPE_DIFFUSE,
+       TEXTYPE_DETAIL,
+       TEXTYPE_ENVMAP,
+       TEXTYPE_LIGHTMAP,
+       TEXTYPE_BUMPMAP
+};
+
+#define MAX_TEXTURES   5
+
+class Material {       
+public:
+       std::string name;
+       
+       Color ambient_color, diffuse_color, specular_color, emissive_color;
+       scalar_t specular_power;
+       scalar_t env_intensity;
+       scalar_t bump_intensity;
+       scalar_t alpha;
+       
+       Texture *tex[MAX_TEXTURES];
+       Matrix4x4 tmat[MAX_TEXTURES];
+       int tex_count;
+
+       bool wireframe;
+       ShadeMode shading;
+
+       bool auto_refl;
+       int auto_refl_upd;
+
+       bool two_sided;
+       
+       Material();
+       Material(const Color &col);
+       
+       void set_texture(Texture *texture, TextureType type);
+       Texture *get_texture(TextureType type);
+       int get_texture_count() const;
+       
+       void set_glmaterial() const;
+};
+       
+
+#endif // _MATERIALS_HPP_
diff --git a/src/3dengfx/src/3dengfx/mcube_tables.h b/src/3dengfx/src/3dengfx/mcube_tables.h
new file mode 100644 (file)
index 0000000..e2ce940
--- /dev/null
@@ -0,0 +1,281 @@
+#ifndef SCFIELD_SOURCE
+#error "Do not include mcube_tables.h anywhere!"
+#endif /* ISOSURF_SOURCE */
+
+static int cube_edge_flags[256] = {
+       0x000, 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c, 0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00,
+       0x190, 0x099, 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c, 0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90,
+       0x230, 0x339, 0x033, 0x13a, 0x636, 0x73f, 0x435, 0x53c, 0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30,
+       0x3a0, 0x2a9, 0x1a3, 0x0aa, 0x7a6, 0x6af, 0x5a5, 0x4ac, 0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0,
+       0x460, 0x569, 0x663, 0x76a, 0x066, 0x16f, 0x265, 0x36c, 0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60,
+       0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0x0ff, 0x3f5, 0x2fc, 0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0,
+       0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x055, 0x15c, 0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950,
+       0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0x0cc, 0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0,
+       0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc, 0x0cc, 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0,
+       0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c, 0x15c, 0x055, 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650,
+       0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc, 0x2fc, 0x3f5, 0x0ff, 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0,
+       0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c, 0x36c, 0x265, 0x16f, 0x066, 0x76a, 0x663, 0x569, 0x460,
+       0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac, 0x4ac, 0x5a5, 0x6af, 0x7a6, 0x0aa, 0x1a3, 0x2a9, 0x3a0,
+       0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c, 0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x033, 0x339, 0x230,
+       0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c, 0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x099, 0x190,
+       0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c, 0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x000
+};
+
+static int tri_table[256][16] = {
+       {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {0, 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {9, 2, 10, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {2, 8, 3, 2, 10, 8, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1},
+       {3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {0, 11, 2, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {1, 9, 0, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {1, 11, 2, 1, 9, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1},
+       {3, 10, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {0, 10, 1, 0, 8, 10, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1},
+       {3, 9, 0, 3, 11, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1},
+       {9, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {0, 1, 9, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {4, 1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1},
+       {1, 2, 10, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {3, 4, 7, 3, 0, 4, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1},
+       {9, 2, 10, 9, 0, 2, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1},
+       {2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1},
+       {8, 4, 7, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {11, 4, 7, 11, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1},
+       {9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1},
+       {4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, -1, -1, -1, -1},
+       {3, 10, 1, 3, 11, 10, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1},
+       {1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, -1, -1, -1, -1},
+       {4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, -1, -1, -1, -1},
+       {4, 7, 11, 4, 11, 9, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1},
+       {9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {0, 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1},
+       {1, 2, 10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1},
+       {5, 2, 10, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1},
+       {2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1},
+       {9, 5, 4, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {0, 11, 2, 0, 8, 11, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1},
+       {0, 5, 4, 0, 1, 5, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1},
+       {2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, -1, -1, -1, -1},
+       {10, 3, 11, 10, 1, 3, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1},
+       {4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, -1, -1, -1, -1},
+       {5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, -1, -1, -1, -1},
+       {5, 4, 8, 5, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1},
+       {9, 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1},
+       {0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1},
+       {1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {9, 7, 8, 9, 5, 7, 10, 1, 2, -1, -1, -1, -1, -1, -1, -1},
+       {10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, -1, -1, -1, -1},
+       {8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, -1, -1, -1, -1},
+       {2, 10, 5, 2, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1},
+       {7, 9, 5, 7, 8, 9, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1},
+       {9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, -1, -1, -1, -1},
+       {2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, -1, -1, -1, -1},
+       {11, 2, 1, 11, 1, 7, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1},
+       {9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, -1, -1, -1, -1},
+       {5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, -1},
+       {11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, -1},
+       {11, 10, 5, 7, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {0, 8, 3, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {9, 0, 1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {1, 8, 3, 1, 9, 8, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1},
+       {1, 6, 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {1, 6, 5, 1, 2, 6, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1},
+       {9, 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1},
+       {5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1},
+       {2, 3, 11, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {11, 0, 8, 11, 2, 0, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1},
+       {0, 1, 9, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1},
+       {5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, -1, -1, -1, -1},
+       {6, 3, 11, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1},
+       {0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, -1, -1, -1, -1},
+       {3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1},
+       {6, 5, 9, 6, 9, 11, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1},
+       {5, 10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {4, 3, 0, 4, 7, 3, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1},
+       {1, 9, 0, 5, 10, 6, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1},
+       {10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, -1, -1, -1, -1},
+       {6, 1, 2, 6, 5, 1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1},
+       {1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, -1, -1, -1, -1},
+       {8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, -1, -1, -1, -1},
+       {7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, -1},
+       {3, 11, 2, 7, 8, 4, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1},
+       {5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, -1, -1, -1, -1},
+       {0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1},
+       {9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, -1},
+       {8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, -1, -1, -1, -1},
+       {5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, -1},
+       {0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, -1},
+       {6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, -1, -1, -1, -1},
+       {10, 4, 9, 6, 4, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {4, 10, 6, 4, 9, 10, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1},
+       {10, 0, 1, 10, 6, 0, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1},
+       {8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, -1, -1, -1, -1},
+       {1, 4, 9, 1, 2, 4, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1},
+       {3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, -1, -1, -1, -1},
+       {0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1},
+       {10, 4, 9, 10, 6, 4, 11, 2, 3, -1, -1, -1, -1, -1, -1, -1},
+       {0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, -1, -1, -1, -1},
+       {3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, -1, -1, -1, -1},
+       {6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, -1},
+       {9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, -1, -1, -1, -1},
+       {8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, -1},
+       {3, 11, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1},
+       {6, 4, 8, 11, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {7, 10, 6, 7, 8, 10, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1},
+       {0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, -1, -1, -1, -1},
+       {10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, -1, -1, -1, -1},
+       {10, 6, 7, 10, 7, 1, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1},
+       {1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, -1, -1, -1, -1},
+       {2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, -1},
+       {7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1},
+       {7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, -1, -1, -1, -1},
+       {2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, -1},
+       {1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, -1},
+       {11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, -1, -1, -1, -1},
+       {8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, -1},
+       {0, 9, 1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, -1, -1, -1, -1},
+       {7, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {3, 0, 8, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {0, 1, 9, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {8, 1, 9, 8, 3, 1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1},
+       {10, 1, 2, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {1, 2, 10, 3, 0, 8, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1},
+       {2, 9, 0, 2, 10, 9, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1},
+       {6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, -1, -1, -1, -1},
+       {7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1},
+       {2, 7, 6, 2, 3, 7, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1},
+       {1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1},
+       {10, 7, 6, 10, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1},
+       {10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1},
+       {0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, -1, -1, -1, -1},
+       {7, 6, 10, 7, 10, 8, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1},
+       {6, 8, 4, 11, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {3, 6, 11, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1},
+       {8, 6, 11, 8, 4, 6, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1},
+       {9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, -1, -1, -1, -1},
+       {6, 8, 4, 6, 11, 8, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1},
+       {1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, -1, -1, -1, -1},
+       {4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, -1, -1, -1, -1},
+       {10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, -1},
+       {8, 2, 3, 8, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1},
+       {0, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, -1, -1, -1, -1},
+       {1, 9, 4, 1, 4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1},
+       {8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, -1, -1, -1, -1},
+       {10, 1, 0, 10, 0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1},
+       {4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, -1},
+       {10, 9, 4, 6, 10, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {4, 9, 5, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {0, 8, 3, 4, 9, 5, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1},
+       {5, 0, 1, 5, 4, 0, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1},
+       {11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, -1, -1, -1, -1},
+       {9, 5, 4, 10, 1, 2, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1},
+       {6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, -1, -1, -1, -1},
+       {7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, -1, -1, -1, -1},
+       {3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, -1},
+       {7, 2, 3, 7, 6, 2, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1},
+       {9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, -1, -1, -1, -1},
+       {3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, -1, -1, -1, -1},
+       {6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, -1},
+       {9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, -1, -1, -1, -1},
+       {1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, -1},
+       {4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, -1},
+       {7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, -1, -1, -1, -1},
+       {6, 9, 5, 6, 11, 9, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1},
+       {3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1, -1},
+       {0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, -1, -1, -1, -1},
+       {6, 11, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1},
+       {1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, -1, -1, -1, -1},
+       {0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, -1},
+       {11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, -1},
+       {6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, -1, -1, -1, -1},
+       {5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1},
+       {9, 5, 6, 9, 6, 0, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1},
+       {1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, -1},
+       {1, 5, 6, 2, 1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, -1},
+       {10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, -1, -1, -1, -1},
+       {0, 3, 8, 5, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {10, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {11, 5, 10, 7, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {11, 5, 10, 11, 7, 5, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1},
+       {5, 11, 7, 5, 10, 11, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1},
+       {10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, -1, -1, -1, -1},
+       {11, 1, 2, 11, 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1},
+       {0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, -1, -1, -1, -1},
+       {9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, -1, -1, -1, -1},
+       {7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, -1},
+       {2, 5, 10, 2, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1},
+       {8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, -1, -1, -1, -1},
+       {9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, -1, -1, -1, -1},
+       {9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, -1},
+       {1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1},
+       {9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1},
+       {9, 8, 7, 5, 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {5, 8, 4, 5, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1},
+       {5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, -1, -1, -1, -1},
+       {0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, -1, -1, -1, -1},
+       {10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, -1},
+       {2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, -1, -1, -1, -1},
+       {0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, -1},
+       {0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, -1},
+       {9, 4, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, -1, -1, -1, -1},
+       {5, 10, 2, 5, 2, 4, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1},
+       {3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, -1},
+       {5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, -1, -1, -1, -1},
+       {8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1},
+       {0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, -1, -1, -1, -1},
+       {9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {4, 11, 7, 4, 9, 11, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1},
+       {0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, -1, -1, -1, -1},
+       {1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, -1, -1, -1, -1},
+       {3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, -1},
+       {4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, -1, -1, -1, -1},
+       {9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, -1},
+       {11, 7, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1},
+       {11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, -1, -1, -1, -1},
+       {2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1, -1, -1, -1},
+       {9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, -1},
+       {3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, -1},
+       {1, 10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1},
+       {4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, -1, -1, -1, -1},
+       {4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {9, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {3, 0, 9, 3, 9, 11, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1},
+       {0, 1, 10, 0, 10, 8, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1},
+       {3, 1, 10, 11, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {1, 2, 11, 1, 11, 9, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1},
+       {3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, -1, -1, -1, -1},
+       {0, 2, 11, 8, 0, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {3, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {2, 3, 8, 2, 8, 10, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1},
+       {9, 10, 2, 0, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1},
+       {1, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {1, 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}
+};
diff --git a/src/3dengfx/src/3dengfx/object.cpp b/src/3dengfx/src/3dengfx/object.cpp
new file mode 100644 (file)
index 0000000..7fd4772
--- /dev/null
@@ -0,0 +1,630 @@
+/*
+This file is part of the 3dengfx, realtime visualization system.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+3dengfx is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+3dengfx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with 3dengfx; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* higher level 3d object abstraction
+ *
+ * Author: John Tsiombikas 2004
+ * Modified: John Tsiombikas 2005, 2006
+ */
+
+#include "3dengfx_config.h"
+
+#include "opengl.h"
+#include "object.hpp"
+#include "3denginefx.hpp"
+#include "camera.hpp"
+#include "gfxprog.hpp"
+#include "texman.hpp"
+#include "ggen.hpp"
+#include "common/err_msg.h"
+
+RenderParams::RenderParams() {
+       billboarded = false;
+       zwrite = true;
+       blending = false;
+       src_blend = BLEND_SRC_ALPHA;
+       dest_blend = BLEND_ONE_MINUS_SRC_ALPHA;
+       handle_blending = true;
+       gfxprog = 0;
+       auto_cube_maps = false;
+       hidden = false;
+       show_normals = false;
+       show_normals_scale = 0.5;
+       highlight = false;
+       highlight_color = Color(1.0, 1.0, 1.0, 1.0);
+       highlight_line_width = 1.0;
+       use_vertex_color = false;
+       taddr = TEXADDR_WRAP;
+       auto_normalize = false;
+       cast_shadows = true;
+}
+
+
+unsigned long master_render_mode = RMODE_ALL;
+       
+
+Object::Object() {
+       bvol_valid = false;
+       bvol = 0;
+       set_dynamic(false);
+}
+
+Object::Object(const TriMesh &mesh) {
+       bvol = 0;
+       set_mesh(mesh);
+       set_dynamic(false);
+}
+
+Object::~Object() {
+       if(bvol) delete bvol;
+}
+
+void Object::set_mesh(const TriMesh &mesh) {
+       this->mesh = mesh;
+       update_bounding_volume();
+}
+
+TriMesh *Object::get_mesh_ptr() {
+       bvol_valid = false;
+       return &mesh;
+}
+
+TriMesh &Object::get_mesh() {
+       return mesh;
+}
+
+const TriMesh &Object::get_mesh() const {
+       return mesh;
+}
+
+unsigned long Object::get_vertex_count() const {
+       return mesh.get_vertex_array()->get_count();
+}
+
+const Vertex *Object::get_vertex_data() const {
+       return mesh.get_vertex_array()->get_data();
+}
+
+Vertex *Object::get_mod_vertex_data() {
+       return mesh.get_mod_vertex_array()->get_mod_data();
+}
+
+unsigned long Object::get_triangle_count() const {
+       return mesh.get_triangle_array()->get_count();
+}
+
+const Triangle *Object::get_triangle_data() const {
+       return mesh.get_triangle_array()->get_data();
+}
+
+Triangle *Object::get_mod_triangle_data() {
+       return mesh.get_mod_triangle_array()->get_mod_data();
+}
+
+void Object::set_dynamic(bool enable) {
+       const_cast<VertexArray*>(mesh.get_vertex_array())->set_dynamic(enable);
+       const_cast<TriangleArray*>(mesh.get_triangle_array())->set_dynamic(enable);
+       //const_cast<IndexArray*>(mesh.get_index_array())->set_dynamic(enable);
+}
+
+bool Object::get_dynamic() const {
+       return mesh.get_vertex_array()->get_dynamic();
+}
+
+void Object::set_material(const Material &mat) {
+       this->mat = mat;
+}
+
+Material *Object::get_material_ptr() {
+       return &mat;
+}
+
+Material Object::get_material() const {
+       return mat;
+}
+
+void Object::set_render_params(const RenderParams &rp) {
+       render_params = rp;
+}
+
+RenderParams Object::get_render_params() const {
+       return render_params;
+}
+
+void Object::set_shading(ShadeMode shading_mode) {
+       mat.shading = shading_mode;
+}
+
+void Object::set_billboarding(bool enable) {
+       render_params.billboarded = enable;
+}
+
+void Object::set_zwrite(bool enable) {
+       render_params.zwrite = enable;
+}
+
+void Object::set_blending(bool enable) {
+       render_params.blending = enable;
+}
+
+void Object::set_blending_mode(BlendingFactor sblend, BlendingFactor dblend) {
+       render_params.src_blend = sblend;
+       render_params.dest_blend = dblend;
+}
+
+void Object::set_handle_blending(bool enable) {
+       render_params.handle_blending = enable;
+}
+
+void Object::set_wireframe(bool enable) {
+       mat.wireframe = enable;
+}
+
+void Object::set_gfx_program(GfxProg *prog) {
+       render_params.gfxprog = prog;
+}
+
+void Object::set_auto_cube_maps(bool enable) {
+       render_params.auto_cube_maps = enable;
+}
+
+void Object::set_hidden(bool enable) {
+       render_params.hidden = enable;
+}
+
+void Object::set_show_normals(bool enable) {
+       render_params.show_normals = enable;
+}
+
+void Object::set_show_normals_scale(scalar_t scale) {
+       render_params.show_normals_scale = scale;
+}
+
+void Object::set_highlight(bool enable)
+{
+       render_params.highlight = enable;
+}
+
+void Object::set_highlight_color(const Color &color)
+{
+       render_params.highlight_color = color;
+}
+
+void Object::set_highlight_line_width(scalar_t width)
+{
+       render_params.highlight_line_width = width;
+}
+
+void Object::set_auto_global(bool enable) {
+       mat.auto_refl = enable;
+}
+
+void Object::set_use_vertex_color(bool enable) {
+       render_params.use_vertex_color = enable;
+}
+
+void Object::set_texture_addressing(TextureAddressing taddr) {
+       render_params.taddr = taddr;
+}
+
+void Object::set_auto_normalize(bool enable) {
+       render_params.auto_normalize = enable;
+}
+
+void Object::set_shadow_casting(bool enable)
+{
+       render_params.cast_shadows = enable;
+}
+
+void Object::apply_xform(unsigned long time) {
+       world_mat = get_prs(time).get_xform_matrix();
+       mesh.apply_xform(world_mat);
+       reset_xform(time);
+}
+
+void Object::calculate_normals() {
+       mesh.calculate_normals();
+}
+
+void Object::normalize_normals() {
+       mesh.normalize_normals();
+}
+
+bool Object::render(unsigned long time) {
+       world_mat = get_prs(time).get_xform_matrix();
+
+       if(!bvol_valid) update_bounding_volume();
+
+       // set the active world-space transformation for the bounding volume ...
+       bvol->set_transform(world_mat);
+       
+       /* if we have the camera that generated the active view matrix available
+        * chances are it already has the view frustum, so use it directly to test
+        * the object, otherwise generate one.
+        */
+       if(engfx_state::view_mat_camera) {
+               if(!bvol->visible(engfx_state::view_mat_camera->get_frustum())) return false;
+       } else {
+               Matrix4x4 view_proj = engfx_state::proj_matrix * engfx_state::view_matrix;
+               
+               FrustumPlane frustum[6];
+               for(int i=0; i<6; i++) {
+                       frustum[i] = FrustumPlane(view_proj, i);
+               }
+
+               if(!bvol->visible(frustum)) return false;
+       }
+       
+       
+       set_matrix(XFORM_WORLD, world_mat);
+       mat.set_glmaterial();
+
+       ::set_auto_normalize(render_params.auto_normalize);
+       
+       //render8tex_units();
+       render_hack(time);
+
+       if(render_params.auto_normalize) ::set_auto_normalize(false);
+
+       return true;
+}
+
+void Object::render_hack(unsigned long time) {
+       //::set_material(mat);
+       int tex_unit = 0;
+
+       if(master_render_mode & RMODE_TEXTURES) {
+               if(mat.tex[TEXTYPE_BUMPMAP]) {
+                       setup_bump_light(time); // sets the light vector into texcoord[1]
+
+                       set_texture(tex_unit, mat.tex[TEXTYPE_BUMPMAP]);
+                       enable_texture_unit(tex_unit);
+                       set_texture_coord_index(tex_unit, 0);
+                       set_texture_unit_color(tex_unit, TOP_REPLACE, TARG_TEXTURE, TARG_TEXTURE);
+                       set_texture_unit_alpha(tex_unit, TOP_REPLACE, TARG_PREV, TARG_PREV);
+                       tex_unit++;
+               
+                       select_texture_unit(tex_unit);
+                       set_texture(tex_unit, get_normal_cube());
+                       enable_texture_unit(tex_unit);
+//                     ::set_texture_filtering(tex_unit, render_params.tfilter);
+                       set_texture_coord_index(tex_unit, 1);   // tex coord with the light vector (UVW)
+                       set_texture_unit_color(tex_unit, TOP_DOT3, TARG_TEXTURE, TARG_PREV);
+                       set_texture_unit_alpha(tex_unit, TOP_REPLACE, TARG_PREV, TARG_PREV);
+                       tex_unit++;
+               }
+       
+               if(mat.tex[TEXTYPE_DIFFUSE]) {
+                       set_texture(tex_unit, mat.tex[TEXTYPE_DIFFUSE]);
+                       enable_texture_unit(tex_unit);
+                       set_texture_coord_index(tex_unit, 0);
+                       set_texture_unit_color(tex_unit, TOP_MODULATE, TARG_TEXTURE, TARG_PREV);
+                       set_texture_unit_alpha(tex_unit, TOP_MODULATE, TARG_TEXTURE, TARG_PREV);
+                       //tex_id = mat.tex[TEXTYPE_DIFFUSE]->tex_id;
+                       ::set_texture_addressing(tex_unit, render_params.taddr, render_params.taddr);
+//                     ::set_texture_filtering(tex_unit, render_params.tfilter);
+                       set_matrix(XFORM_TEXTURE, mat.tmat[TEXTYPE_DIFFUSE], 0);
+                       tex_unit++;
+               }
+
+               if(mat.tex[TEXTYPE_DETAIL]) {
+                       set_texture(tex_unit, mat.tex[TEXTYPE_DETAIL]);
+                       enable_texture_unit(tex_unit);
+                       set_texture_coord_index(tex_unit, 1);
+                       set_texture_unit_color(tex_unit, TOP_ADD, TARG_TEXTURE, TARG_PREV);
+                       set_texture_unit_color(tex_unit, TOP_MODULATE, TARG_PREV, TARG_TEXTURE);
+                       ::set_texture_addressing(tex_unit, render_params.taddr, render_params.taddr);
+//                     ::set_texture_filtering(tex_unit, render_params.tfilter);
+                       set_matrix(XFORM_TEXTURE, mat.tmat[TEXTYPE_DIFFUSE], 1);
+                       tex_unit++;
+               }
+       
+               if(mat.tex[TEXTYPE_ENVMAP]) {
+                       set_texture(tex_unit, mat.tex[TEXTYPE_ENVMAP]);
+//                     ::set_texture_filtering(tex_unit, render_params.tfilter);
+                       enable_texture_unit(tex_unit);
+                       set_texture_unit_color(tex_unit, TOP_ADD, TARG_TEXTURE, TARG_PREV);
+                       set_texture_unit_alpha(tex_unit, TOP_REPLACE, TARG_PREV, TARG_TEXTURE);
+
+                       if(mat.tex[TEXTYPE_ENVMAP]->get_type() == TEX_CUBE) {
+                               glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
+                               glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
+                               glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
+                               glEnable(GL_TEXTURE_GEN_S);
+                               glEnable(GL_TEXTURE_GEN_T);
+                               glEnable(GL_TEXTURE_GEN_R);
+
+                               Matrix4x4 inv_view = engfx_state::view_matrix;
+                               inv_view[0][3] = inv_view[1][3] = inv_view[2][3] = 0.0;
+                               inv_view.transpose();
+
+                               set_matrix(XFORM_TEXTURE, inv_view, tex_unit);
+
+                               ::set_texture_addressing(tex_unit, TEXADDR_CLAMP, TEXADDR_CLAMP);
+                       } else {
+                               ::set_texture_addressing(tex_unit, render_params.taddr, render_params.taddr);
+                               glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
+                               glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
+                               glEnable(GL_TEXTURE_GEN_S);
+                               glEnable(GL_TEXTURE_GEN_T);
+
+                               // TODO: fix this to produce the correct orientation
+                               /*glMatrixMode(GL_TEXTURE);
+                               glLoadIdentity();
+                               glRotatef(180.0, 0.0, 1.0, 0.0);*/
+                       }
+                       //tex_id = mat.tex[TEXTYPE_ENVMAP]->tex_id;
+                       tex_unit++;
+               }
+       }
+
+       ::set_zwrite(render_params.zwrite);
+       set_shading_mode(mat.shading);
+
+       if(master_render_mode & RMODE_BLENDING) {
+               if(render_params.handle_blending) {
+                       if(mat.alpha < 1.0 - small_number) {
+                               set_alpha_blending(true);
+                               set_blend_func(BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA);
+                       }
+               } else {
+                       set_alpha_blending(render_params.blending);
+                       set_blend_func(render_params.src_blend, render_params.dest_blend);
+               }
+       }
+
+       if(mat.wireframe) ::set_wireframe(true);
+
+       if(render_params.gfxprog && (master_render_mode & RMODE_SHADERS)) {
+               ::set_gfx_program(render_params.gfxprog);
+       }
+       // XXX: cont. here
+
+       if(mat.two_sided) set_backface_culling(false);
+       if(render_params.use_vertex_color) ::use_vertex_colors(true);
+       
+       draw(*mesh.get_vertex_array(), *mesh.get_index_array());
+
+       if(render_params.use_vertex_color) ::use_vertex_colors(false);
+       if(mat.two_sided) set_backface_culling(true);
+
+       if(mat.wireframe) ::set_wireframe(false);
+       if((master_render_mode & RMODE_BLENDING) &&
+                       (render_params.handle_blending && mat.alpha < 1.0 - small_number) || 
+                       (!render_params.handle_blending && render_params.blending)) {
+               set_alpha_blending(false);
+       }
+       if(!render_params.zwrite) ::set_zwrite(true);
+       if(mat.shading == SHADING_FLAT) set_shading_mode(SHADING_GOURAUD);
+
+
+       if(master_render_mode & RMODE_TEXTURES) {
+               for(int i=0; i<tex_unit; i++) {
+                       disable_texture_unit(i);
+                       glDisable(GL_TEXTURE_GEN_S);
+                       glDisable(GL_TEXTURE_GEN_T);
+                       glDisable(GL_TEXTURE_GEN_R);
+                       glMatrixMode(GL_TEXTURE);
+                       glLoadIdentity();
+                       glMatrixMode(GL_MODELVIEW);
+                       set_matrix(XFORM_TEXTURE, Matrix4x4::identity_matrix, i);
+                       ::set_texture_addressing(tex_unit, TEXADDR_WRAP, TEXADDR_WRAP);
+                       //::set_texture_filtering(tex_unit, BILINEAR_FILTERING);
+               }
+       }
+
+       if(render_params.show_normals) {
+               draw_normals();
+       }
+
+       if (render_params.highlight)
+       {
+               draw_highlight();
+       }
+       
+       if((master_render_mode & RMODE_SHADERS) && render_params.gfxprog) {
+               ::set_gfx_program(0);
+       }
+}
+
+void Object::draw_normals() {
+       scalar_t normal_scale = mesh.get_vertex_stats().avg_dist * render_params.show_normals_scale;
+       int vcount = mesh.get_vertex_array()->get_count();
+       const Vertex *vptr = mesh.get_vertex_array()->get_data();
+
+       set_lighting(false);
+       
+       glBegin(GL_LINES);
+       glColor4f(1.0, 1.0, 1.0, 1.0);
+       for(int i=0; i<vcount; i++) {
+               Vector3 pos = vptr->pos;
+               Vector3 normal = vptr->normal * normal_scale;
+               
+               glVertex3f(pos.x, pos.y, pos.z);
+               glVertex3f(pos.x + normal.x, pos.y + normal.y, pos.z + normal.z);
+               vptr++;
+       }
+       glEnd();
+
+       set_lighting(true);
+}
+
+void Object::draw_highlight()
+{
+       const Vertex *vptr = mesh.get_vertex_array()->get_data();
+
+       // get contour edges relative to viewer
+       Vector3 pov = Vector3(0, 0, 0);
+       Matrix4x4 model = get_matrix(XFORM_WORLD);
+       Matrix4x4 view = get_matrix(XFORM_VIEW);
+       pov.transform(view.inverse());
+       pov.transform(model.inverse());
+       std::vector<Edge> *edges = mesh.get_contour_edges(pov, false);
+       
+       set_lighting(false);
+       ::set_gfx_program(0);
+
+       glEnable(GL_LINE_SMOOTH);
+       glLineWidth(render_params.highlight_line_width);
+       
+       glEnable(GL_BLEND);
+       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+       
+       Color clr = render_params.highlight_color;
+       glBegin(GL_LINES);
+       glColor4f(clr.r, clr.g, clr.b, clr.a);
+       for (unsigned int i=0; i<edges->size(); i++) 
+       {
+               Vector3 p1, p2;
+               p1 = vptr[(*edges)[i].vertices[0]].pos;
+               p2 = vptr[(*edges)[i].vertices[1]].pos;
+               glVertex3f(p1.x, p1.y, p1.z);
+               glVertex3f(p2.x, p2.y, p2.z);
+       }
+       glEnd();
+
+       glLineWidth(1);
+       
+       glDisable(GL_BLEND);
+       
+       set_lighting(true);
+
+}
+
+void Object::setup_bump_light(unsigned long time) {
+       Vector3 lpos = engfx_state::bump_light->get_prs(time).position;
+
+       Matrix4x4 inv_world = world_mat.inverse();
+       lpos.transform(inv_world);
+
+       VertexArray *va = mesh.get_mod_vertex_array();
+       int vcount = va->get_count();
+       Vertex *varray = va->get_mod_data();
+       int tcount = mesh.get_triangle_array()->get_count();
+       const Triangle *tptr = mesh.get_triangle_array()->get_data();
+
+       
+       Vector3 *utan = new Vector3[vcount];
+       memset(utan, 0, vcount * sizeof(Vector3));
+
+       Vector3 *vtan = new Vector3[vcount];
+       memset(vtan, 0, vcount * sizeof(Vector3));
+
+       for(int i=0; i<tcount; i++) {
+               Vertex *v1 = &varray[tptr->vertices[0]];
+               Vertex *v2 = &varray[tptr->vertices[1]];
+               Vertex *v3 = &varray[tptr->vertices[2]];
+
+               Vector3 vec1 = v2->pos - v1->pos;
+               Vector3 vec2 = v3->pos - v1->pos;
+
+               TexCoord tc1(v2->tex[0].u - v1->tex[0].u, v2->tex[0].v - v1->tex[0].v);
+               TexCoord tc2(v3->tex[0].u - v1->tex[0].u, v3->tex[0].v - v1->tex[0].v);
+       
+               scalar_t r = 1.0 / (tc1.u * tc2.v - tc2.u * tc1.v);
+               Vector3 udir(   (tc2.v * vec1.x - tc1.v * vec2.x) * r,
+                                               (tc2.v * vec1.y - tc1.v * vec2.y) * r,
+                                               (tc2.v * vec1.z - tc1.v * vec2.z) * r);
+
+               Vector3 vdir(   (tc1.u * vec2.x - tc2.u * vec1.x) * r,
+                                               (tc1.u * vec2.y - tc2.u * vec1.y) * r,
+                                               (tc1.u * vec2.z - tc2.u * vec1.z) * r);
+
+               utan[tptr->vertices[0]] += udir;
+               utan[tptr->vertices[1]] += udir;
+               utan[tptr->vertices[2]] += udir;
+               
+               vtan[tptr->vertices[0]] += vdir;
+               vtan[tptr->vertices[1]] += vdir;
+               vtan[tptr->vertices[2]] += vdir;
+               
+               tptr++;         
+       }
+
+       Vertex *vptr = varray;
+       for(int i=0; i<vcount; i++) {
+               Vector3 lvec = lpos - vptr->pos;
+
+               Vector3 normal = -vptr->normal;
+               Vector3 tan = utan[i];
+               tan = (tan - normal * dot_product(normal, tan)).normalized();
+               Vector3 bitan = cross_product(normal, tan);
+
+               Basis tbn(tan, bitan, normal);
+               lvec.transform(tbn.create_rotation_matrix());
+               //lvec.normalize();
+               
+               vptr->tex[1].u = -lvec.z;
+               vptr->tex[1].v = -lvec.y;
+               vptr->tex[1].w = lvec.x;
+               vptr++;
+       }
+       
+       delete [] utan;
+       delete [] vtan;
+}
+
+
+void Object::update_bounding_volume() {
+       VertexStatistics vstat = mesh.get_vertex_stats();
+
+       if(!bvol) {
+               bvol = new BoundingSphere(vstat.centroid, vstat.max_dist);
+               bvol_valid = true;
+       } else {
+               BoundingSphere *bsph;
+               
+               if((bsph = dynamic_cast<BoundingSphere*>(bvol))) {
+                       bsph->set_position(vstat.centroid);
+                       bsph->set_radius(vstat.max_dist);
+                       bvol_valid = true;
+               } else {
+                       static int dbg;
+                       if(!dbg++) error("obj \"%s\": only bounding spheres are supported at this point", name.c_str());
+               }
+       }
+}
+
+
+// Convenience classes to deal with generated geometry
+
+ObjCube::ObjCube(scalar_t sz, int subdiv) {
+       create_cube(get_mesh_ptr(), sz, subdiv);
+}
+
+ObjPlane::ObjPlane(const Vector3 &normal, const Vector2 &size, int subdiv) {
+       create_plane(get_mesh_ptr(), normal, size, subdiv);
+}
+
+ObjCylinder::ObjCylinder(scalar_t rad, scalar_t len, bool caps, int udiv, int vdiv) {
+       create_cylinder(get_mesh_ptr(), rad, len, caps, udiv, vdiv);
+}
+
+ObjSphere::ObjSphere(scalar_t radius, int subdiv) {
+       create_sphere(get_mesh_ptr(), radius, subdiv);
+}
+
+ObjTorus::ObjTorus(scalar_t circle_rad, scalar_t revolv_rad, int subdiv) {
+       create_torus(get_mesh_ptr(), circle_rad, revolv_rad, subdiv);
+}
+
+ObjTeapot::ObjTeapot(scalar_t size, int subdiv) {
+       create_teapot(get_mesh_ptr(), size, subdiv);
+}
diff --git a/src/3dengfx/src/3dengfx/object.hpp b/src/3dengfx/src/3dengfx/object.hpp
new file mode 100644 (file)
index 0000000..c66d843
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+This file is part of the 3dengfx, realtime visualization system.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+3dengfx is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+3dengfx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with 3dengfx; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* higher level 3d object abstraction
+ *
+ * Author: John Tsiombikas 2004
+ * Modified: John Tsiombikas 2005
+ */
+
+#ifndef _OBJECT_HPP_
+#define _OBJECT_HPP_
+
+#include <string>
+#include "gfx/3dgeom.hpp"
+#include "gfx/animation.hpp"
+#include "n3dmath2/n3dmath2.hpp"
+#include "material.hpp"
+#include "3denginefx.hpp"
+#include "gfx/bvol.hpp"
+
+struct RenderParams {
+       bool billboarded;
+       bool zwrite;
+       bool blending;
+       BlendingFactor src_blend, dest_blend;
+       bool handle_blending;
+       GfxProg *gfxprog;
+       bool auto_cube_maps;
+       bool hidden;
+       bool show_normals;
+       scalar_t show_normals_scale;
+       bool highlight;
+       Color highlight_color;
+       scalar_t highlight_line_width;
+       bool two_sided;
+       bool use_vertex_color;
+       TextureAddressing taddr;
+       bool auto_normalize;
+       bool cast_shadows;
+       
+       RenderParams();
+};
+
+enum {
+       RMODE_COLOR                     = 1,            // unused
+       RMODE_LIGHTING          = 2,            // unused
+       RMODE_TEXTURES          = 4,
+       RMODE_BLENDING          = 8,
+       RMODE_SHADERS           = 16,
+       RMODE_ALL                       = 0xffff
+};
+
+// this bitfield determines which aspects of rendering will actually take place
+// it overrides all render parameters.
+extern unsigned long master_render_mode;
+
+class Object : public XFormNode {
+private:
+       Matrix4x4 world_mat;
+       RenderParams render_params;
+       BoundingVolume *bvol;
+       bool bvol_valid;
+       
+       void render_hack(unsigned long time);
+
+       void draw_normals();
+       void draw_highlight();
+       
+       void setup_bump_light(unsigned long time);
+       void update_bounding_volume();
+       
+public:
+       TriMesh mesh;
+       Material mat;
+       
+       Object();
+       Object(const TriMesh &mesh);
+       ~Object();
+       
+       void set_mesh(const TriMesh &mesh);
+       TriMesh *get_mesh_ptr();
+       TriMesh &get_mesh();
+       const TriMesh &get_mesh() const;
+
+       // shortcut functions for accessing the geometry easily
+       unsigned long get_vertex_count() const;
+       const Vertex *get_vertex_data() const;
+       Vertex *get_mod_vertex_data();
+       unsigned long get_triangle_count() const;
+       const Triangle *get_triangle_data() const;
+       Triangle *get_mod_triangle_data();
+
+       void set_dynamic(bool enable);
+       bool get_dynamic() const;
+       
+       void set_material(const Material &mat);
+       Material *get_material_ptr();
+       Material get_material() const;
+       
+       void set_render_params(const RenderParams &rp);
+       RenderParams get_render_params() const;
+       
+       void set_shading(ShadeMode shading_mode);
+       void set_billboarding(bool enable);
+       void set_zwrite(bool enable);
+       void set_blending(bool enable);
+       void set_blending_mode(BlendingFactor sblend, BlendingFactor dblend);
+       void set_handle_blending(bool enable);
+       void set_wireframe(bool enable);
+       void set_gfx_program(GfxProg *prog);
+       void set_auto_cube_maps(bool enable);
+       void set_hidden(bool enable);
+       void set_show_normals(bool enable);
+       void set_show_normals_scale(scalar_t scale);
+       void set_highlight(bool enable);
+       void set_highlight_color(const Color &color);
+       void set_highlight_line_width(scalar_t width);
+       void set_auto_global(bool enable);
+       void set_use_vertex_color(bool enable);
+       void set_texture_addressing(TextureAddressing taddr);
+       void set_auto_normalize(bool enable);
+       void set_shadow_casting(bool enable);
+
+       void apply_xform(unsigned long time = XFORM_LOCAL_PRS);
+
+       void calculate_normals();
+       void normalize_normals();
+       
+       bool render(unsigned long time = XFORM_LOCAL_PRS);
+};
+
+
+// --- some convinient derived objects for geom. generation ---
+
+class ObjCube : public Object {
+public:
+       ObjCube(scalar_t sz, int subdiv);
+};
+
+class ObjPlane : public Object {
+public:
+       ObjPlane(const Vector3 &normal = Vector3(0, 1, 0), const Vector2 &size = Vector2(1, 1), int subdiv = 0);
+};
+
+class ObjCylinder : public Object {
+public:
+       ObjCylinder(scalar_t rad = 1.0, scalar_t len = 1.0, bool caps = true, int udiv = 12, int vdiv = 0);
+};
+
+class ObjSphere : public Object {
+public:
+       ObjSphere(scalar_t radius = 1.0, int subdiv = 5);
+};
+
+class ObjTorus : public Object {
+public:
+       ObjTorus(scalar_t circle_rad = 0.5, scalar_t revolv_rad = 1.0, int subdiv = 5);
+};
+
+class ObjTeapot : public Object {
+public:
+       ObjTeapot(scalar_t size = 1.0, int subdiv = 5);
+};
+
+#endif // _OBJECT_HPP_
diff --git a/src/3dengfx/src/3dengfx/opengl.h b/src/3dengfx/src/3dengfx/opengl.h
new file mode 100644 (file)
index 0000000..b43ddb8
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+This file is part of the 3dengfx, realtime visualization system.
+Copyright (C) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+3dengfx is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+3dengfx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with 3dengfx; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef _OPENGL_H_
+#define _OPENGL_H_
+
+#if defined(WIN32) || defined(__WIN32__)
+#define WIN32_LEAN_AND_MEAN    1
+#include <windows.h>
+#endif /* WIN32 */
+
+#include <GL/gl.h>
+
+#ifdef GL_ARB_transpose_matrix
+#undef GL_ARB_transpose_matrix
+#endif
+
+#ifdef GL_ARB_multitexture
+#undef GL_ARB_multitexture
+#endif
+
+#ifdef GL_ARB_vertex_array_object
+#undef GL_ARB_vertex_array_object
+#endif
+
+#ifdef GL_ARB_fragment_program
+#undef GL_ARB_fragment_program
+#endif
+
+#ifdef GL_ARB_vertex_program
+#undef GL_ARB_vertex_program
+#endif
+
+#ifdef GL_ARB_point_parameters
+#undef GL_ARB_point_parameters
+#endif
+
+#ifdef GL_ARB_shader_objects
+#undef GL_ARB_shader_objects
+#endif
+
+#include "sgi_glext.h"
+
+namespace glext {
+#ifdef GL_ARB_transpose_matrix
+#ifdef SINGLE_PRECISION_MATH
+       extern PFNGLLOADTRANSPOSEMATRIXFARBPROC glLoadTransposeMatrix;
+#else
+       extern PFNGLLOADTRANSPOSEMATRIXDARBPROC glLoadTransposeMatrix;
+#endif /* SINGLE_PRECISION_MATH */
+#endif /* GL_ARB_transpose_matrix */
+
+#ifdef GL_ARB_multitexture
+       extern PFNGLACTIVETEXTUREARBPROC glActiveTexture;
+       extern PFNGLCLIENTACTIVETEXTUREARBPROC glClientActiveTexture;
+#endif /* GL_ARB_multitexture */
+
+#ifdef GL_ARB_vertex_buffer_object
+       extern PFNGLBINDBUFFERARBPROC glBindBuffer;
+       extern PFNGLBUFFERDATAARBPROC glBufferData;
+       extern PFNGLDELETEBUFFERSARBPROC glDeleteBuffers;
+       extern PFNGLISBUFFERARBPROC glIsBuffer;
+       extern PFNGLMAPBUFFERARBPROC glMapBuffer;
+       extern PFNGLUNMAPBUFFERARBPROC glUnmapBuffer;
+       extern PFNGLGENBUFFERSARBPROC glGenBuffers;
+#endif /* GL_ARB_vertex_buffer_object */
+
+       /* fragment/vertex program extensions */
+#ifdef GL_ARB_vertex_program
+       extern PFNGLBINDPROGRAMARBPROC glBindProgram;
+       extern PFNGLGENPROGRAMSARBPROC glGenPrograms;
+       extern PFNGLDELETEPROGRAMSARBPROC glDeletePrograms;
+       extern PFNGLPROGRAMSTRINGARBPROC glProgramString;
+#endif /* GL_ARB_vertex_program */
+
+#ifdef GL_ARB_point_parameters
+       extern PFNGLPOINTPARAMETERFARBPROC glPointParameterf;
+       extern PFNGLPOINTPARAMETERFVARBPROC glPointParameterfv;
+#endif /* GL_ARB_point_parameters */
+
+       /* --- OpenGL 2.0 Shading Language --- */
+       
+#ifdef GL_ARB_shader_objects
+       extern PFNGLDELETEOBJECTARBPROC glDeleteObject;
+       extern PFNGLATTACHOBJECTARBPROC glAttachObject;
+       extern PFNGLDETACHOBJECTARBPROC glDetachObject;
+       extern PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameteriv;
+       extern PFNGLGETINFOLOGARBPROC glGetInfoLog;
+
+       extern PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObject;
+       extern PFNGLLINKPROGRAMARBPROC glLinkProgram;
+       extern PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObject;
+
+       extern PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObject;
+       extern PFNGLSHADERSOURCEARBPROC glShaderSource;
+       extern PFNGLCOMPILESHADERARBPROC glCompileShader;
+
+       extern PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocation;
+       extern PFNGLGETACTIVEUNIFORMARBPROC glGetActiveUniform;
+       extern PFNGLUNIFORM1IARBPROC glUniform1i;
+       extern PFNGLUNIFORM1FARBPROC glUniform1f;
+       extern PFNGLUNIFORM2FARBPROC glUniform2f;
+       extern PFNGLUNIFORM3FARBPROC glUniform3f;
+       extern PFNGLUNIFORM4FARBPROC glUniform4f;
+       extern PFNGLUNIFORMMATRIX3FVARBPROC glUniformMatrix3fv;
+       extern PFNGLUNIFORMMATRIX4FVARBPROC glUniformMatrix4fv;
+#endif /* GL_ARB_shader_objects */
+
+}
+
+#endif /* _OPENGL_H_ */
diff --git a/src/3dengfx/src/3dengfx/ply.cpp b/src/3dengfx/src/3dengfx/ply.cpp
new file mode 100644 (file)
index 0000000..78bdc53
--- /dev/null
@@ -0,0 +1,378 @@
+#include <vector>
+#include <string>
+#include <cstdio>
+#include <cctype>
+#include <cassert>
+#include "gfx/3dgeom.hpp"
+#include "common/err_msg.h"
+
+#define BUFFER_SIZE            256
+
+using std::vector;
+using std::string;
+
+enum PlyFormat {
+       PLY_ASCII,
+       PLY_LITTLE_ENDIAN,
+       PLY_BIG_ENDIAN
+};
+
+enum PropType {
+       PROP_FLOAT,
+       PROP_INT8,
+       PROP_INT16,
+       PROP_INT32,
+       PROP_LIST
+};
+
+const size_t prop_size[] = {32, 8, 16, 32, 0};
+
+struct PropTypeMatch {
+       char *symb;
+       PropType type;
+} prop_match[] = {
+       {"float",       PROP_FLOAT},
+       {"float32",     PROP_FLOAT},
+       {"int",         PROP_INT32},
+       {"int32",       PROP_INT32},
+       {"uint",        PROP_INT32},
+       {"uint32",      PROP_INT32},
+       {"int16",       PROP_INT16},
+       {"uint16",      PROP_INT16},
+       {"char",        PROP_INT8},
+       {"uchar",       PROP_INT8},
+       {"int8",        PROP_INT8},
+       {"uint8",       PROP_INT8},
+       {"list",        PROP_LIST},
+       {0, (PropType)0}
+};
+
+struct Property {
+       string name;
+       PropType type;
+       PropType list_type;     // list elements type, if type == PROP_LIST
+       size_t size;
+};
+
+enum ElementType {ELEM_UNKNOWN, ELEM_VERTEX, ELEM_FACE};
+
+struct Element {
+       ElementType type;
+       unsigned long count;
+       vector<Property> prop;
+       long offset;
+};
+
+struct Ply {
+       PlyFormat fmt;
+       vector<Element> elem;
+       FILE *fp;
+       unsigned long header_skip;
+};
+
+static Ply *read_header(FILE *fp);
+static Element *seek_elem(Ply *ply, ElementType elem_type);
+
+static const char *ply_filename = 0;   // for error reports
+
+bool file_is_ply(FILE *file) {
+       char sig[5] = {0};
+       
+       fseek(file, 0, SEEK_SET);
+       fgets(sig, 5, file);
+
+       return !strcmp(sig, "ply\n");
+}
+
+#define FAIL(m) {\
+       error("ply(%s): " m, fname);\
+       fclose(fp);\
+       delete ply;\
+       return 0;\
+}
+
+TriMesh *load_mesh_ply(const char *fname) {
+       const char *sep = " \t\n";
+       char buf[BUFFER_SIZE];
+
+       FILE *fp = fopen(fname, "r");
+       if(!fp || !file_is_ply(fp)) {
+               if(fp) fclose(fp);
+               return 0;
+       }
+
+       ply_filename = fname;
+
+       Ply *ply = read_header(fp);
+       if(!ply) {
+               fclose(fp);
+               return 0;
+       }
+       ply->fp = fp;
+
+       vector<Vertex> verts;
+       vector<Triangle> tris;
+
+       Element *elem;
+
+       // -- read the vertices
+       if(!(elem = seek_elem(ply, ELEM_VERTEX))) {
+               FAIL("failed to locate vertex data");
+       }
+
+       if(elem->prop[0].type != PROP_FLOAT || elem->prop[1].type != PROP_FLOAT || elem->prop[2].type != PROP_FLOAT) {
+               FAIL("weird vertex format, didn't find 3 floats");
+       }
+
+       for(unsigned long i=0; i<elem->count; i++) {
+               Vertex v;
+               if(ply->fmt == PLY_ASCII) {
+                       fgets(buf, BUFFER_SIZE, fp);
+
+                       char *x_str = strtok(buf, sep);
+                       char *y_str = strtok(0, sep);
+                       char *z_str = strtok(0, sep);
+
+                       if(!x_str || !y_str || !z_str) {
+                               FAIL("vertex data loading failed, format inconsistent");
+                       }
+                       v.pos.x = atof(x_str);
+                       v.pos.y = atof(y_str);
+                       v.pos.z = -atof(z_str);
+                       
+               } else {
+                       FAIL("sorry binary ply loading not implemented yet");
+               }
+
+               verts.push_back(v);
+       }
+
+       // -- read the face list
+       if(!(elem = seek_elem(ply, ELEM_FACE))) {
+               FAIL("failed to locate face data");
+       }
+
+       if(elem->prop[0].type != PROP_LIST) {
+               FAIL("weird face format, didn't find an index list");
+       }
+
+       for(unsigned long i=0; i<elem->count; i++) {
+               int count;
+               unsigned long indices[4];
+               
+               if(ply->fmt == PLY_ASCII) {
+                       fgets(buf, BUFFER_SIZE, fp);
+
+                       count = atoi(strtok(buf, sep));
+                       if(count < 3 || count > 4) {
+                               FAIL("only triangles and quads are supported");
+                       }
+
+                       for(int j=0; j<count; j++) {
+                               char *substr = strtok(0, sep);
+                               if(!substr) {
+                                       FAIL("inconsistent face list data");
+                               }
+                               indices[j] = atol(substr);
+                       }
+                       
+               } else {
+                       FAIL("sorry binary ply loading not implemented yet");
+               }
+
+               Triangle tri(indices[0], indices[1], indices[2]);
+               tris.push_back(tri);
+
+               if(count == 4) {
+                       Triangle tri2(indices[0], indices[2], indices[3]);
+                       tris.push_back(tri2);
+               }
+       }
+
+       fclose(fp);
+       delete ply;
+
+       // ok now we have the vertex/triangle vectors, let's create the mesh and return it
+       TriMesh *mesh = new TriMesh(&verts[0], verts.size(), &tris[0], tris.size());
+       mesh->calculate_normals();
+       return mesh;
+}
+
+static Ply *read_header(FILE *fp) {
+       const char *sep = " \t\n";
+       char buf[BUFFER_SIZE];
+       
+       fseek(fp, 0, SEEK_SET);
+
+       Ply *ply = new Ply;
+       memset(ply, 0, sizeof(Ply));
+
+       bool vertex_ok = false, face_ok = false;
+
+       while(fgets(buf, BUFFER_SIZE, fp)) {
+               char *field = strtok(buf, sep);
+               if(!field) continue;
+
+               if(!strcmp(field, "format")) {
+                       char *fmt = strtok(0, sep);
+                       if(!fmt) {
+                               error("ply(%s): invalid format field", ply_filename);
+                               delete ply;
+                               return 0;
+                       }
+
+                       if(!strcmp(fmt, "ascii")) {
+                               ply->fmt = PLY_ASCII;
+                       } else if(!strcmp(fmt, "binary_little_endian")) {
+                               ply->fmt = PLY_LITTLE_ENDIAN;
+                       } else if(!strcmp(fmt, "binary_big_endian")) {
+                               ply->fmt = PLY_BIG_ENDIAN;
+                       } else {
+                               error("ply(%s): invalid format field", ply_filename);
+                               delete ply;
+                               return 0;
+                       }
+                       
+               } else if(!strcmp(field, "element")) {
+                       char *elem_name = strtok(0, sep);
+                       if(!elem_name) {
+                               warning("ply(%s): invalid element definition", ply_filename);
+                               continue;
+                       }
+                       
+                       char *count_str = strtok(0, sep);
+                       if(!count_str || !isdigit(*count_str)) {
+                               error("ply(%s): element not followed by a count", ply_filename);
+                               delete ply;
+                               return 0;
+                       }
+
+                       unsigned long count = atol(count_str);
+
+                       Element elem;
+                       elem.type = ELEM_UNKNOWN;
+                       elem.count = count;
+                                               
+                       if(!strcmp(elem_name, "vertex")) {
+                               elem.type = ELEM_VERTEX;
+                               vertex_ok = true;
+                       }
+                       
+                       if(!strcmp(elem_name, "face")) {
+                               elem.type = ELEM_FACE;
+                               face_ok = true;
+                       }
+
+                       // determine element properties
+                       while((buf[0] = fgetc(fp)) == 'p') {
+                               if(!fgets(buf + 1, BUFFER_SIZE - 1, fp)) {
+                                       error("ply(%s): unexpected end of file while reading element properties", ply_filename);
+                                       delete ply;
+                                       return 0;
+                               }
+                               char *ptr = strtok(buf, sep);
+                               if(!ptr || strcmp(ptr, "property")) {
+                                       error("ply(%s): looking for \"propery\", got \"%s\"", ply_filename, ptr ? ptr : "NULL");
+                                       delete ply;
+                                       return 0;
+                               }
+
+                               Property prop;
+                               prop.size = 0;
+                               
+                               /*
+                               char *name = strtok(0, sep);
+                               if(!name) {
+                                       error("ply(%s): invalid property entry, no name specified", ply_filename);
+                                       delete ply;
+                                       return 0;
+                               }
+                               prop.name = name;
+                               */
+
+                               char *type = strtok(0, sep);
+                               if(!type) {
+                                       error("ply(%s): invalid property entry, no type specified", ply_filename);
+                                       delete ply;
+                                       return 0;
+                               }
+
+                               PropTypeMatch *mptr = prop_match;
+                               while(mptr->symb) {
+                                       if(!strcmp(type, mptr->symb)) {
+                                               prop.type = mptr->type;
+                                               prop.size = prop_size[prop.type];
+                                               break;
+                                       }
+                                       mptr++;
+                               }
+
+                               if(prop.type == PROP_LIST) {
+                                       type = strtok(0, sep);
+                                       if(!type) {
+                                               error("ply(%s): invalid property entry, no list subtype specified", ply_filename);
+                                               delete ply;
+                                               return 0;
+                                       }
+                                       
+                                       mptr = prop_match;
+                                       while(mptr->symb) {
+                                               if(!strcmp(type, mptr->symb)) {
+                                                       prop.list_type = mptr->type;
+                                                       prop.size = prop_size[prop.list_type];
+                                                       break;
+                                               }
+                                               mptr++;
+                                       }
+                               }
+
+                               if(!prop.size) {
+                                       error("ply(%s): unknown property type \"%s\"", ply_filename, type);
+                                       delete ply;
+                                       return 0;
+                               }
+
+                               elem.prop.push_back(prop);
+                       }
+
+                       ungetc(buf[0], fp);
+
+                       ply->elem.push_back(elem);
+
+               } else if(!strcmp(field, "end_header")) {
+                       if(!vertex_ok || !face_ok) {
+                               error("ply(%s): some important element is unspecified (vertex or face list)", ply_filename);
+                               delete ply;
+                               return 0;
+                       }
+                       ply->header_skip = ftell(fp);
+                       break;
+               }
+       }
+
+       return ply;
+}
+
+static Element *seek_elem(Ply *ply, ElementType elem_type) {
+       fseek(ply->fp, ply->header_skip, SEEK_SET);
+       
+       if(ply->fmt == PLY_ASCII) {
+               char buf[BUFFER_SIZE];
+
+               for(size_t i=0; i<ply->elem.size(); i++) {
+                       if(ply->elem[i].type == elem_type) {
+                               return &ply->elem[i];
+                       }
+
+                       // it's not the one we want, skip it.
+                       for(size_t j=0; j<ply->elem[i].count; j++) {
+                               fgets(buf, BUFFER_SIZE, ply->fp);
+                       }
+               }
+               return 0;
+
+       } else {
+               error("ply(%s): seek failed, binary ply loading not implemented yet", ply_filename);
+               return 0;
+       }
+}
diff --git a/src/3dengfx/src/3dengfx/psys.cpp b/src/3dengfx/src/3dengfx/psys.cpp
new file mode 100644 (file)
index 0000000..b32cb69
--- /dev/null
@@ -0,0 +1,652 @@
+/*
+This file is part of the 3dengfx, realtime visualization system.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <vector>
+#include <cmath>
+#include "3dengfx_config.h"
+#include "3denginefx.hpp"
+#include "texman.hpp"
+#include "psys.hpp"
+#include "common/config_parser.h"
+#include "common/err_msg.h"
+
+#ifdef SINGLE_PRECISION_MATH
+#define GL_SCALAR_TYPE GL_FLOAT
+#else
+#define GL_SCALAR_TYPE GL_DOUBLE
+#endif // SINGLE_PRECISION_MATH
+
+static scalar_t global_time;
+
+// just a trial and error constant to match point-sprite size with billboard size
+#define PSPRITE_BILLBOARD_RATIO                100
+
+// particle rendering state
+static bool use_psprites = true;
+static bool volatile_particles = false;
+
+Fuzzy::Fuzzy(scalar_t num, scalar_t range) {
+       this->num = num;
+       this->range = range;
+}
+
+scalar_t Fuzzy::operator()() const {
+       return range == 0.0 ? num : frand(range) + num - range / 2.0;
+}
+
+
+FuzzyVec3::FuzzyVec3(const Fuzzy &x, const Fuzzy &y, const Fuzzy &z) {
+       this->x = x;
+       this->y = y;
+       this->z = z;
+}
+
+Vector3 FuzzyVec3::operator()() const {
+       return Vector3(x(), y(), z());
+}
+
+
+Particle::Particle() {
+       friction = 1.0;
+       lifespan = 0;
+       birth_time = 0;
+}
+
+Particle::Particle(const Vector3 &pos, const Vector3 &vel, scalar_t friction, scalar_t lifespan) {
+       set_position(pos);
+       velocity = vel;
+       this->friction = friction;
+       this->lifespan = lifespan;
+       birth_time = global_time;
+}
+
+Particle::~Particle(){}
+
+bool Particle::alive() const {
+       return global_time - birth_time < lifespan;
+}
+
+void Particle::update(const Vector3 &ext_force) {
+       scalar_t time = global_time - birth_time;
+       if(time > lifespan) return;
+
+       velocity = (velocity + ext_force) * friction;
+       translate(velocity);    // update position
+}
+
+void BillboardParticle::update(const Vector3 &ext_force) {
+       Particle::update(ext_force);
+       
+       scalar_t time = global_time - birth_time;
+       if(time > lifespan) return;
+       scalar_t t = time / lifespan;
+       
+       color = blend_colors(start_color, end_color, t);
+
+       size = size_start + (size_end - size_start) * t;
+
+       angle = rot * time + birth_angle;
+}
+
+/* NOTE:
+ * if we use point sprites, and the particles are not rotating, then the
+ * calling function has taken care to call glBegin() before calling this.
+ */
+void BillboardParticle::draw() const {
+       Matrix4x4 tex_rot;
+       if(volatile_particles) {
+               tex_rot.translate(Vector3(0.5, 0.5, 0.0));
+               tex_rot.rotate(Vector3(0.0, 0.0, angle));
+               tex_rot.translate(Vector3(-0.5, -0.5, 0.0));
+               set_matrix(XFORM_TEXTURE, tex_rot);
+       }
+
+       Vector3 pos = get_position();
+       
+       if(use_psprites) {
+               if(volatile_particles) {
+                       glPointSize(size);
+                       
+                       glBegin(GL_POINTS);
+                       glColor4f(color.r, color.g, color.b, color.a);
+                       glVertex3f(pos.x, pos.y, pos.z);
+                       glEnd();
+               } else {
+                       glColor4f(color.r, color.g, color.b, color.a);
+                       glVertex3f(pos.x, pos.y, pos.z);
+               }
+       } else {        // don't use point sprites
+               Vertex v(pos, 0, 0, color);
+               draw_point(v, size / PSPRITE_BILLBOARD_RATIO);
+       }
+}
+
+
+
+ParticleSysParams::ParticleSysParams() {
+       psize_end = -1.0;
+       friction = 0.95;
+       billboard_tex = 0;
+       halo = 0;
+       rot = 0.0;
+       glob_rot = 0.0;
+       halo_rot = 0.0;
+       big_particles = false;
+       spawn_offset_curve = 0;
+       spawn_offset_curve_area = Fuzzy(0.5, 1.0);
+
+       src_blend = BLEND_SRC_ALPHA;
+       dest_blend = BLEND_ONE;
+}
+
+
+
+ParticleSystem::ParticleSystem(const char *fname) {
+       timeslice = 1.0 / 50.0;
+       SysCaps sys_caps = get_system_capabilities();
+       /* XXX: My Radeon Mobility 9000 supports point sprites but does not say so
+        * in the extension string, it only has point params there. So I changed this
+        * condition to && since probably if a card supports one, it will also support
+        * the other.
+        */
+       psprites_unsupported = !sys_caps.point_sprites && !sys_caps.point_params;
+
+       prev_update = -1.0;
+       fraction = 0.0;
+       ptype = PTYPE_BILLBOARD;
+
+       ready = true;
+
+       if(fname) {
+               if(!psys::load_particle_sys_params(fname, &psys_params)) {
+                       error("Error loading particle file: %s", fname);
+                       ready = false;
+               }
+       }
+}
+
+ParticleSystem::~ParticleSystem() {
+       reset();
+}
+
+void ParticleSystem::reset() {
+       prev_update = -1.0;
+       std::list<Particle*>::iterator iter = particles.begin();
+       while(iter != particles.end()) {
+               delete *iter++;
+       }
+       particles.clear();
+}
+
+void ParticleSystem::set_update_interval(scalar_t timeslice) {
+       this->timeslice = timeslice;
+}
+
+void ParticleSystem::set_params(const ParticleSysParams &psys_params) {
+       this->psys_params = psys_params;
+}
+
+ParticleSysParams *ParticleSystem::get_params() {
+       return &psys_params;
+}
+
+void ParticleSystem::set_particle_type(ParticleType ptype) {
+       this->ptype = ptype;
+}
+
+void ParticleSystem::update(const Vector3 &ext_force) {
+       if(!ready) return;
+       
+       curr_time = global_time;
+       int updates_missed = (int)round((global_time - prev_update) / timeslice);
+
+       if(!updates_missed) return;     // less than a timeslice has elapsed, nothing to do
+       
+       PRS prs = get_prs((unsigned long)(global_time * 1000.0));
+       curr_pos = prs.position;
+       curr_halo_rot = psys_params.halo_rot * global_time;
+
+       curr_rot = fmod(psys_params.glob_rot * global_time, two_pi);
+
+       // spawn new particles
+       scalar_t spawn = psys_params.birth_rate() * (global_time - prev_update);
+       int spawn_count = (int)round(spawn);
+
+       // handle sub-timeslice spawning rates
+       fraction += spawn - round(spawn);
+       if(fraction > 1.0) {
+               fraction -= 1.0;
+               spawn_count++;
+       } else if(fraction < -1.0) {
+               fraction += 1.0;
+               spawn_count--;
+       }
+
+       Vector3 dp, pos;
+       if(prev_update < 0.0) {
+               prev_pos = curr_pos;
+               prev_update = curr_time;
+               return;
+       } else {
+               dp = (curr_pos - prev_pos) / (scalar_t)spawn_count;
+               pos = prev_pos;
+       }
+       
+       scalar_t dt = (global_time - prev_update) / (scalar_t)spawn_count;
+       scalar_t t = prev_update;
+       
+       for(int i=0; i<spawn_count; i++) {
+               Particle *particle;
+               
+               switch(ptype) {
+               case PTYPE_BILLBOARD:
+                       particle = new BillboardParticle;
+                       {
+                               curr_rot = fmod(psys_params.glob_rot * t, two_pi);
+                               
+                               BillboardParticle *bbp = (BillboardParticle*)particle;
+                               bbp->texture = psys_params.billboard_tex;
+                               bbp->start_color = psys_params.start_color;
+                               bbp->end_color = psys_params.end_color;
+                               bbp->rot = psys_params.rot;
+                               bbp->birth_angle = curr_rot;
+                       }
+
+                       break;
+
+               default:
+                       error("Only billboarded particles implemented currently");
+                       exit(-1);
+                       break;
+               }
+               
+               //PRS sub_prs = get_prs((unsigned long)(t * 1000.0));
+               
+
+               Vector3 offset = psys_params.spawn_offset();
+               if(psys_params.spawn_offset_curve) {
+                       float t = psys_params.spawn_offset_curve_area();
+                       offset += (*psys_params.spawn_offset_curve)(t);
+               }
+               // XXX: correct this rotation to span the whole interval
+               particle->set_position(pos + offset.transformed(prs.rotation));
+               particle->set_rotation(prs.rotation);
+               particle->set_scaling(prs.scale);
+
+               particle->size_start = psys_params.psize();
+               if(psys_params.psize_end < 0.0) {
+                       particle->size_end = particle->size_start;
+               } else {
+                       particle->size_end = psys_params.psize_end;
+               }
+               particle->velocity = psys_params.shoot_dir().transformed(prs.rotation); // XXX: correct this rotation to span the interval
+               particle->friction = psys_params.friction;
+               particle->birth_time = t;
+               particle->lifespan = psys_params.lifespan();
+
+               particles.push_back(particle);
+
+               pos += dp;
+               t += dt;
+       }
+       
+
+       // update particles
+       
+       std::list<Particle*>::iterator iter = particles.begin();
+       while(iter != particles.end()) {
+               Particle *p = *iter;
+               int i = 0;
+               while(p->alive() && i++ < updates_missed) {
+                       p->update(psys_params.gravity);
+               }
+
+               if(p->alive()) {
+                       iter++;
+               } else {
+                       delete *iter;
+                       iter = particles.erase(iter);
+               }
+       }
+
+       prev_update = global_time;
+       prev_pos = curr_pos;
+}
+
+void ParticleSystem::draw() const {
+       if(!ready) return;
+
+       // use point sprites if the system supports them AND we don't need big particles
+       use_psprites = !psys_params.big_particles && !psprites_unsupported;
+
+       // particles are volatile if they rotate OR they fluctuate in size
+       volatile_particles = psys_params.rot > small_number || psys_params.psize.range > small_number;
+       
+       set_matrix(XFORM_WORLD, Matrix4x4());
+       load_xform_matrices();
+
+       std::list<Particle*>::const_iterator iter = particles.begin();
+       if(iter != particles.end()) {
+               
+               if(ptype == PTYPE_BILLBOARD) {
+                       // ------ setup render state ------
+                       set_lighting(false);
+                       set_zwrite(false);
+                       set_alpha_blending(true);
+                       set_blend_func(psys_params.src_blend, psys_params.dest_blend);
+
+                       if(psys_params.billboard_tex) {
+                               enable_texture_unit(0);
+                               disable_texture_unit(1);
+                               set_texture(0, psys_params.billboard_tex);
+                               set_texture_addressing(0, TEXADDR_CLAMP, TEXADDR_CLAMP);
+
+                               if(use_psprites) {
+                                       set_point_sprites(true);
+                                       set_point_sprite_coords(0, true);
+                               }
+
+                               if(!volatile_particles) {
+                                       Matrix4x4 prot;
+                                       prot.translate(Vector3(0.5, 0.5, 0.0));
+                                       prot.rotate(Vector3(0.0, 0.0, curr_rot));
+                                       prot.translate(Vector3(-0.5, -0.5, 0.0));
+                                       set_matrix(XFORM_TEXTURE, prot);
+                               }
+                       }
+
+                       set_texture_unit_color(0, TOP_MODULATE, TARG_TEXTURE, TARG_PREV);
+                       set_texture_unit_alpha(0, TOP_MODULATE, TARG_TEXTURE, TARG_PREV);
+
+                       if(use_psprites && !volatile_particles) {
+                               glPointSize((*iter)->size);
+                               glBegin(GL_POINTS);
+                       }
+               }
+
+               // ------ render particles ------
+               while(iter != particles.end()) {
+                       (*iter++)->draw();
+               }
+       
+               if(ptype == PTYPE_BILLBOARD) {
+                       // ------ restore render states -------
+                       if(use_psprites) {
+                               if(!volatile_particles) glEnd();
+                               glPointSize(1.0);
+                       }
+
+                       if(psys_params.billboard_tex) {
+                               if(use_psprites) {
+                                       set_point_sprites(true);
+                                       set_point_sprite_coords(0, true);
+                               }
+                               set_texture_addressing(0, TEXADDR_WRAP, TEXADDR_WRAP);
+                               disable_texture_unit(0);
+
+                               set_matrix(XFORM_TEXTURE, Matrix4x4::identity_matrix);
+                       }
+
+                       set_alpha_blending(false);
+                       set_zwrite(true);
+                       set_lighting(true);
+               }
+       }
+
+       // ------ render a halo around the emitter if we need to ------
+       if(psys_params.halo) {
+               // construct texture matrix for halo rotation
+               Matrix4x4 mat;
+               mat.translate(Vector3(0.5, 0.5, 0.0));
+               mat.rotate(Vector3(0, 0, curr_halo_rot));
+               mat.translate(Vector3(-0.5, -0.5, 0.0));
+               set_matrix(XFORM_TEXTURE, mat);
+
+               set_alpha_blending(true);
+               set_blend_func(BLEND_SRC_ALPHA, BLEND_ONE);
+               enable_texture_unit(0);
+               disable_texture_unit(1);
+               set_texture(0, psys_params.halo);
+               set_zwrite(false);
+               Vertex v(curr_pos, 0, 0, psys_params.halo_color);
+               draw_point(v, psys_params.halo_size() / PSPRITE_BILLBOARD_RATIO);
+               set_zwrite(true);
+               disable_texture_unit(0);
+               set_alpha_blending(false);
+
+               set_matrix(XFORM_TEXTURE, Matrix4x4::identity_matrix);
+       }
+}
+
+
+void psys::set_global_time(unsigned long msec) {
+       global_time = (scalar_t)msec / 1000.0;
+}
+
+
+static Vector3 get_vector(const char *str) {
+       char *buf = new char[strlen(str) + 1];
+       strcpy(buf, str);
+
+       Vector3 res;
+
+       char *beg = buf;
+       char *ptr;
+       
+       res.x = atof(beg);
+       if(!(ptr = strchr(beg, ','))) {
+               delete [] buf;
+               return res;
+       }
+       *ptr = 0;
+       beg = ptr + 1;
+       
+       res.y = atof(beg);
+       if(!(ptr = strchr(beg, ','))) {
+               delete [] buf;
+               return res;
+       }
+       *ptr = 0;
+       beg = ptr + 1;
+
+       res.z = atof(beg);
+
+       delete [] buf;
+       return res;
+}
+
+static Vector4 get_vector4(const char *str) {
+       char *buf = new char[strlen(str) + 1];
+       strcpy(buf, str);
+
+       Vector4 res;
+
+       char *beg = buf;
+       char *ptr;
+       
+       res.x = atof(beg);
+       if(!(ptr = strchr(beg, ','))) {
+               delete [] buf;
+               return res;
+       }
+       *ptr = 0;
+       beg = ptr + 1;
+       
+       res.y = atof(beg);
+       if(!(ptr = strchr(beg, ','))) {
+               delete [] buf;
+               return res;
+       }
+       *ptr = 0;
+       beg = ptr + 1;
+
+       res.z = atof(beg);
+       if(!(ptr = strchr(beg, ','))) {
+               delete [] buf;
+               return res;
+       }
+       *ptr = 0;
+       beg = ptr + 1;
+       
+       res.w = atof(beg);
+
+       delete [] buf;
+       return res;
+}
+
+
+bool psys::load_particle_sys_params(const char *fname, ParticleSysParams *psp) {
+       Vector3 shoot, shoot_range;
+       Vector3 spawn_off, spawn_off_range;
+       
+       set_parser_state(PS_AssignmentSymbol, ':');
+       set_parser_state(PS_CommentSymbol, '#');
+
+       if(load_config_file(fname) == -1) return false;
+
+       const ConfigOption *opt;
+       while((opt = get_next_option())) {
+
+               if(!strcmp(opt->option, "psize")) {
+                       psp->psize.num = opt->flt_value;
+                       
+               } else if(!strcmp(opt->option, "psize-r")) {
+                       psp->psize.range = opt->flt_value;
+
+               } else if(!strcmp(opt->option, "psize_end")) {
+                       psp->psize_end = opt->flt_value;
+
+               } else if(!strcmp(opt->option, "life")) {
+                       psp->lifespan.num = opt->flt_value;
+
+               } else if(!strcmp(opt->option, "life-r")) {
+                       psp->lifespan.range = opt->flt_value;
+
+               } else if(!strcmp(opt->option, "birth-rate")) {
+                       psp->birth_rate.num = opt->flt_value;
+
+               } else if(!strcmp(opt->option, "birth-rate-r")) {
+                       psp->birth_rate.range = opt->flt_value;
+
+               } else if(!strcmp(opt->option, "grav")) {
+                       psp->gravity = get_vector(opt->str_value);
+                       
+               } else if(!strcmp(opt->option, "shoot")) {
+                       shoot = get_vector(opt->str_value);
+
+               } else if(!strcmp(opt->option, "shoot-r")) {
+                       shoot_range = get_vector(opt->str_value);
+
+               } else if(!strcmp(opt->option, "friction")) {
+                       psp->friction = opt->flt_value;
+
+               } else if(!strcmp(opt->option, "spawn_off")) {
+                       spawn_off = get_vector(opt->str_value);
+
+               } else if(!strcmp(opt->option, "spawn_off-r")) {
+                       spawn_off_range = get_vector(opt->str_value);
+
+               } else if(!strcmp(opt->option, "tex")) {
+                       psp->billboard_tex = get_texture(opt->str_value);
+                       if(!psp->billboard_tex) {
+                               error("Could not load texture: \"%s\"", opt->str_value);
+                       }
+
+               } else if(!strcmp(opt->option, "color")) {
+                       Vector4 v = get_vector4(opt->str_value);
+                       psp->start_color = psp->end_color = Color(v.x, v.y, v.z, v.w);
+                       
+               } else if(!strcmp(opt->option, "color_start")) {
+                       Vector4 v = get_vector4(opt->str_value);
+                       psp->start_color = Color(v.x, v.y, v.z, v.w);
+
+               } else if(!strcmp(opt->option, "color_end")) {
+                       Vector4 v = get_vector4(opt->str_value);
+                       psp->end_color = Color(v.x, v.y, v.z, v.w);
+
+               } else if(!strcmp(opt->option, "rot")) {
+                       psp->rot = opt->flt_value;
+
+               } else if(!strcmp(opt->option, "glob_rot")) {
+                       psp->glob_rot = opt->flt_value;
+                       
+               } else if(!strcmp(opt->option, "halo")) {
+                       psp->halo = get_texture(opt->str_value);
+                       if(!psp->halo) {
+                               error("Could not load texture: \"%s\"", opt->str_value);
+                       }
+
+               } else if(!strcmp(opt->option, "halo_color")) {
+                       Vector4 v = get_vector4(opt->str_value);
+                       psp->halo_color = Color(v.x, v.y, v.z, v.w);
+
+               } else if(!strcmp(opt->option, "halo_size")) {
+                       psp->halo_size.num = opt->flt_value;
+
+               } else if(!strcmp(opt->option, "halo_size-r")) {
+                       psp->halo_size.range = opt->flt_value;
+                       
+               } else if(!strcmp(opt->option, "halo_rot")) {
+                       psp->halo_rot = opt->flt_value;
+                       
+               } else if(!strcmp(opt->option, "big_particles")) {
+                       if(!strcmp(opt->str_value, "true")) {
+                               psp->big_particles = true;
+                       }
+                       
+               } else if(!strcmp(opt->option, "blend_src") || !strcmp(opt->option, "blend_dest")) {
+                       BlendingFactor factor = (BlendingFactor)0xfbad;
+                       if(!strcmp(opt->str_value, "0")) {
+                               factor = BLEND_ZERO;
+                       } else if(!strcmp(opt->str_value, "1")) {
+                               factor = BLEND_ONE;
+                       } else if(!strcmp(opt->str_value, "srcc")) {
+                               factor = BLEND_SRC_COLOR;
+                       } else if(!strcmp(opt->str_value, "srca")) {
+                               factor = BLEND_SRC_ALPHA;
+                       } else if(!strcmp(opt->str_value, "1-srcc")) {
+                               factor = BLEND_ONE_MINUS_SRC_COLOR;
+                       } else if(!strcmp(opt->str_value, "1-srca")) {
+                               factor = BLEND_ONE_MINUS_SRC_ALPHA;
+                       } else if(!strcmp(opt->str_value, "1-dstc")) {
+                               factor = BLEND_ONE_MINUS_DST_COLOR;
+                       } else {
+                               error("psys: invalid blend specification: %s", opt->str_value);
+                       }
+
+                       if(factor != (BlendingFactor)0xfbad) {
+                               if(!strcmp(opt->option, "blend_src")) {
+                                       psp->src_blend = factor;
+                               } else {
+                                       psp->dest_blend = factor;
+                               }
+                       }
+               } else if(!strcmp(opt->option, "spawn_offset_curve")) {
+                       if(!(psp->spawn_offset_curve = load_curve(opt->str_value))) {
+                               error("psys: could not load spawn offset curve: %s", opt->str_value);
+                       }
+               }
+       }
+
+       psp->shoot_dir = FuzzyVec3(Fuzzy(shoot.x, shoot_range.x), Fuzzy(shoot.y, shoot_range.y), Fuzzy(shoot.z, shoot_range.z));
+       psp->spawn_offset = FuzzyVec3(Fuzzy(spawn_off.x, spawn_off_range.x), Fuzzy(spawn_off.y, spawn_off_range.y), Fuzzy(spawn_off.z, spawn_off_range.z));
+
+       return true;
+}
diff --git a/src/3dengfx/src/3dengfx/psys.hpp b/src/3dengfx/src/3dengfx/psys.hpp
new file mode 100644 (file)
index 0000000..a8df4fd
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+This file is part of the 3dengfx, realtime visualization system.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* Particle system
+ *
+ * Author: John Tsiombikas 2004
+ * Modified: John Tsiombikas 2005
+ */
+
+#ifndef _PSYS_HPP_
+#define _PSYS_HPP_
+
+#include <list>
+#include "gfx/3dgeom.hpp"
+#include "n3dmath2/n3dmath2.hpp"
+
+/* fuzzy scalar values
+ * random variables defined as a range of values around a central,
+ * with equiprobable distrubution function
+ */
+class Fuzzy {
+public:
+       scalar_t num, range;
+
+       Fuzzy(scalar_t num = 0.0, scalar_t range = 0.0);
+       scalar_t operator()() const;
+};
+
+/* TODO: make a fuzzy direction with polar coordinates, so the random 
+ * values lie on the surface of a sphere.
+ */
+
+/* vector of the above */
+class FuzzyVec3 {
+private:
+       Fuzzy x, y, z;
+
+public:
+       FuzzyVec3(const Fuzzy &x = Fuzzy(), const Fuzzy &y = Fuzzy(), const Fuzzy &z = Fuzzy());
+       Vector3 operator()() const;
+};
+
+
+/* particle abstract base class.
+ * Derived from XFormNode for controller functionality
+ */
+class Particle : public XFormNode {
+public:
+       Vector3 velocity;
+       scalar_t friction;
+       scalar_t size, size_start, size_end;
+       scalar_t birth_time, lifespan;
+
+       
+       Particle();
+       Particle(const Vector3 &pos, const Vector3 &vel, scalar_t friction, scalar_t lifespan);
+       virtual ~Particle();
+
+       virtual bool alive() const;
+
+       virtual void update(const Vector3 &ext_force = Vector3());
+       virtual void draw() const = 0;
+};
+
+/* draws the particle as a textured quad */
+class BillboardParticle : public Particle {
+public:
+       Texture *texture;
+       Color start_color, end_color;
+       scalar_t rot, birth_angle;
+       
+       Color color;
+       scalar_t angle;
+       
+       virtual void update(const Vector3 &ext_force = Vector3());
+       virtual void draw() const;
+};
+
+/* TODO: draws a 3D object in the position of the particle
+ * note that rotational and such controllers also apply for each
+ * of the particles seperately
+ */
+class MeshParticle : public Particle {
+};
+
+
+struct ParticleSysParams {
+       Fuzzy psize;                    // particle size
+       scalar_t psize_end;             // end size (end of life)
+       Fuzzy lifespan;                 // lifespan in seconds
+       Fuzzy birth_rate;               // birth rate in particles per second
+       Vector3 gravity;                // gravitual force to be applied to all particles
+       FuzzyVec3 shoot_dir;    // shoot direction (initial particle velocity)
+       scalar_t friction;              // friction of the environment
+       FuzzyVec3 spawn_offset; // where to spawn in relation to position
+       Curve *spawn_offset_curve;      // a spawn curve in space, relative to position, offset still counts
+       Fuzzy spawn_offset_curve_area;
+       Texture *billboard_tex; // texture used for billboards
+       Color start_color;              // start color
+       Color end_color;                // end color
+       scalar_t rot;                   // particle rotation (radians / second counting from birth)
+       scalar_t glob_rot;              // particle emmiter rotation, particles inherit this
+
+       BlendingFactor src_blend, dest_blend;
+       
+       Texture *halo;                  // halo texture
+       Color halo_color;               // halo color
+       Fuzzy halo_size;                // halo size
+       scalar_t halo_rot;              // halo rotation (radians / second)
+
+       bool big_particles;             // need support for big particles (i.e. don't use point sprites)
+
+       ParticleSysParams();
+};
+
+enum ParticleType {PTYPE_PSYS, PTYPE_BILLBOARD, PTYPE_MESH};
+
+/* Particle system
+ * The design here gets a bit confusing but for good reason
+ * the particle system is also a particle because it can be emmited by
+ * another particle system. This way we get a tree structure of particle
+ * emmiters with the leaves being just billboards or mesh-particles.
+ */
+class ParticleSystem : public Particle {
+protected:
+       scalar_t timeslice;
+
+       bool ready;
+       bool psprites_unsupported;
+       std::list<Particle*> particles;
+
+       ParticleSysParams psys_params;
+       ParticleType ptype;
+
+       scalar_t fraction;
+       scalar_t prev_update;
+       Vector3 prev_pos;
+
+       // current variables are calculated during each update()
+       scalar_t curr_time;
+       Vector3 curr_pos;
+       scalar_t curr_rot, curr_halo_rot;
+
+public:
+       ParticleSystem(const char *fname = 0);
+       virtual ~ParticleSystem();
+
+       virtual void reset();
+       virtual void set_update_interval(scalar_t timeslice);
+
+       virtual void set_params(const ParticleSysParams &psys_params);
+       virtual ParticleSysParams *get_params();
+       virtual void set_particle_type(ParticleType ptype);
+
+       virtual void update(const Vector3 &ext_force = Vector3());
+       virtual void draw() const;
+};
+
+namespace psys {
+       void set_global_time(unsigned long msec);
+
+       bool load_particle_sys_params(const char *fname, ParticleSysParams *psp);
+}
+
+
+#endif // _PSYS_HPP_
diff --git a/src/3dengfx/src/3dengfx/rend_curve.cpp b/src/3dengfx/src/3dengfx/rend_curve.cpp
new file mode 100644 (file)
index 0000000..b501b3e
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+This file is part of the 3dengfx, realtime visualization system.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+3dengfx is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+3dengfx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with 3dengfx; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* renderable curves
+ *
+ * Author: John Tsiombikas 2005
+ */
+
+#include "3denginefx.hpp"
+#include "rend_curve.hpp"
+
+RendCurve::RendCurve(Curve *curve) {
+       this->curve = curve;
+       stroke = false;
+       width = 1.0;
+       detail = 5;
+       set_blending_mode(BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA);
+}
+
+void RendCurve::set_curve(Curve *curve) {
+       this->curve = curve;
+}
+
+Curve *RendCurve::get_curve() {
+       return curve;
+}
+
+void RendCurve::set_width(scalar_t width) {
+       this->width = width;
+}
+
+scalar_t RendCurve::get_width() const {
+       return width;
+}
+
+void RendCurve::set_blending_mode(BlendingFactor sblend, BlendingFactor dblend) {
+       src_blend = sblend;
+       dst_blend = dblend;
+}
+
+void RendCurve::set_stroke(bool enable) {
+       stroke = enable;
+}
+
+void RendCurve::set_detail(int detail) {
+       this->detail = detail;
+}
+
+void RendCurve::set_material(const Material &mat) {
+       this->mat = mat;
+}
+
+Material *RendCurve::get_material_ptr() {
+       return &mat;
+}
+
+Material RendCurve::get_material() const {
+       return mat;
+}
+
+bool RendCurve::render(unsigned long time) {
+       if(!curve) return false;
+       
+       set_matrix(XFORM_WORLD, get_prs(time).get_xform_matrix());
+       mat.set_glmaterial();
+
+       if(mat.tex[TEXTYPE_DIFFUSE]) {
+               set_texture(0, mat.tex[TEXTYPE_DIFFUSE]);
+               enable_texture_unit(0);
+               set_texture_coord_index(0, 0);
+               set_texture_unit_color(0, TOP_MODULATE, TARG_TEXTURE, TARG_PREV);
+               set_texture_unit_alpha(0, TOP_MODULATE, TARG_TEXTURE, TARG_PREV);
+       }
+
+       set_alpha_blending(true);
+       set_zwrite(false);
+       set_blend_func(src_blend, dst_blend);
+
+       int line_count = curve->get_segment_count() * detail;
+       scalar_t dx = 1.0 / (scalar_t)line_count;
+       scalar_t t = dx;
+       Vector3 prev_pos = (*curve)(0.0);
+       for(int i=1; i<line_count; i++) {
+               Vector3 pos = (*curve)(t);
+               draw_line(Vertex(prev_pos, 0.0), Vertex(pos, 1.0), width, width);
+               prev_pos = pos;
+               t += dx;
+       }
+       
+       set_alpha_blending(false);
+       set_zwrite(true);
+       disable_texture_unit(0);
+
+       return true;
+}
+
+bool RendCurve::render_segm(float start, float end, unsigned long time) {
+       if(!curve) return false;
+       
+       set_matrix(XFORM_WORLD, get_prs(time).get_xform_matrix());
+       mat.set_glmaterial();
+
+       if(mat.tex[TEXTYPE_DIFFUSE]) {
+               set_texture(0, mat.tex[TEXTYPE_DIFFUSE]);
+               enable_texture_unit(0);
+               set_texture_coord_index(0, 0);
+               set_texture_unit_color(0, TOP_MODULATE, TARG_TEXTURE, TARG_PREV);
+               set_texture_unit_alpha(0, TOP_MODULATE, TARG_TEXTURE, TARG_PREV);
+       }
+
+       set_alpha_blending(true);
+       set_zwrite(false);
+       set_blend_func(src_blend, dst_blend);
+
+       int line_count = curve->get_segment_count() * detail;
+       scalar_t dx = (end - start) / (scalar_t)line_count;
+       scalar_t t = start + dx;
+       Vector3 prev_pos = (*curve)(start);
+       for(int i=1; i<line_count; i++) {
+               Vector3 pos = (*curve)(t);
+               draw_line(Vertex(prev_pos, (float)i / (float)line_count), Vertex(pos, (float)(i + 1) / line_count), width, width, mat.diffuse_color);
+               prev_pos = pos;
+               t += dx;
+       }
+       
+       set_alpha_blending(false);
+       set_zwrite(true);
+       disable_texture_unit(0);
+
+       return true;
+}
diff --git a/src/3dengfx/src/3dengfx/rend_curve.hpp b/src/3dengfx/src/3dengfx/rend_curve.hpp
new file mode 100644 (file)
index 0000000..a373064
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+This file is part of the 3dengfx, realtime visualization system.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+3dengfx is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+3dengfx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with 3dengfx; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* renderable curves
+ *
+ * Author: John Tsiombikas 2005
+ */
+
+#ifndef _REND_CURVE_HPP_
+#define _REND_CURVE_HPP_
+
+#include "material.hpp"
+#include "gfx/animation.hpp"
+#include "gfx/curves.hpp"
+
+class RendCurve : public XFormNode {
+private:
+       Curve *curve;
+
+       scalar_t width;
+       BlendingFactor src_blend, dst_blend;
+       bool stroke;
+       int detail;
+
+public:
+       Material mat;
+
+       RendCurve(Curve *curve = 0);
+
+       void set_curve(Curve *curve);
+       Curve *get_curve();
+
+       void set_width(scalar_t width);
+       scalar_t get_width() const;
+
+       void set_blending_mode(BlendingFactor sblend, BlendingFactor dblend);
+
+       void set_stroke(bool enable);
+
+       void set_detail(int detail);
+
+       void set_material(const Material &mat);
+       Material *get_material_ptr();
+       Material get_material() const;
+
+       bool render(unsigned long time = XFORM_LOCAL_PRS);
+       bool render_segm(float start, float end, unsigned long time = XFORM_LOCAL_PRS);
+};
+
+#endif // _REND_CURVE_HPP_
diff --git a/src/3dengfx/src/3dengfx/sceneloader.cpp b/src/3dengfx/src/3dengfx/sceneloader.cpp
new file mode 100644 (file)
index 0000000..b337add
--- /dev/null
@@ -0,0 +1,613 @@
+/*
+This file is part of the 3dengfx, realtime visualization system.
+
+Copyright (c) 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* Scene loader from 3ds files.
+ *
+ * author: John Tsiombikas 2005
+ */
+
+#include "3dengfx_config.h"
+
+#include <algorithm>
+
+#include <cstdio>
+#include <cassert>
+#include <lib3ds/file.h>
+#include <lib3ds/camera.h>
+#include <lib3ds/mesh.h>
+#include <lib3ds/node.h>
+#include <lib3ds/material.h>
+#include <lib3ds/matrix.h>
+#include <lib3ds/vector.h>
+#include <lib3ds/light.h>
+#include "3dscene.hpp"
+#include "object.hpp"
+#include "light.hpp"
+#include "camera.hpp"
+#include "texman.hpp"
+#include "gfx/curves.hpp"
+#include "common/err_msg.h"
+
+#define CONV_VEC3(v)           Vector3((v)[0], (v)[2], (v)[1])
+#define CONV_QUAT(q)           Quaternion((q)[3], Vector3((q)[0], (q)[2], (q)[1]))
+#define CONV_TEXCOORD(t)       TexCoord((t)[0], (t)[1])
+#define CONV_TRIANGLE(t)       Triangle((t).points[0], (t).points[2], (t).points[1])
+#define CONV_RGBA(c)           Color((c)[0], (c)[1], (c)[2], (c)[3])
+#define CONV_RGB(c)                    Color((c)[0], (c)[1], (c)[2])
+
+static bool load_objects(Lib3dsFile *file, Scene *scene);
+static bool load_lights(Lib3dsFile *file, Scene *scene);
+static bool load_cameras(Lib3dsFile *file, Scene *scene);
+static bool load_material(Lib3dsFile *file, const char *name, Material *mat);
+static bool load_keyframes(Lib3dsFile *file, const char *name, Lib3dsNodeTypes type, XFormNode *node);
+static void construct_hierarchy(Lib3dsFile *file, Scene *scene);
+//static void fix_hierarchy(XFormNode *node);
+
+TriMesh *load_mesh_ply(const char *fname);     // defined in ply.cpp
+
+static const char *tex_path(const char *path);
+static std::vector<int> *get_frames(Lib3dsObjectData *o);
+static std::vector<int> *get_frames(Lib3dsLightData *lt);
+static std::vector<int> *get_frames(Lib3dsCameraData *cam);
+
+#define TPATH_SIZE     256
+
+#ifdef __unix__
+#define DIR_SEP        '/'
+#else
+#define DIR_SEP        '\\'
+#endif /* __unix__ */
+
+static char data_path[TPATH_SIZE];
+
+void set_scene_data_path(const char *path) {
+       if(!path || !*path) {
+               data_path[0] = 0;
+       } else {
+               strncpy(data_path, path, TPATH_SIZE);
+               data_path[TPATH_SIZE - 1] = 0;
+
+               char *ptr = data_path + strlen(data_path);
+               if(*ptr != DIR_SEP && ptr - data_path < TPATH_SIZE) {
+                       *ptr++ = DIR_SEP;
+                       *ptr = 0;
+               }
+       }
+}
+
+
+Scene *load_scene(const char *fname) {
+
+       Lib3dsFile *file;
+       if(!(file = lib3ds_file_load(fname))) {
+               error("%s: could not load %s", __func__, fname);
+               return 0;
+       }
+       lib3ds_file_eval(file, 0);
+
+       Scene *scene = new Scene;
+
+       load_objects(file, scene);
+       load_lights(file, scene);
+       load_cameras(file, scene);
+
+       construct_hierarchy(file, scene);
+
+       /*
+       std::list<Object*> *obj_list = scene->get_objects_list();
+       std::list<Object*>::iterator iter = obj_list->begin();
+       while(iter != obj_list->end()) {
+               fix_hierarchy(*iter++);
+       }
+       */
+       
+       lib3ds_file_free(file);
+
+       return scene;
+}
+
+TriMesh *load_mesh(const char *fname, const char *name) {
+       TriMesh *mesh = 0;
+       
+       Lib3dsFile *file = lib3ds_file_load(fname);
+       if(file && name) {
+               Scene *scene = new Scene;
+               load_objects(file, scene);
+
+               Object *obj = scene->get_object(name);
+               if(obj) {
+                       mesh = new TriMesh;
+                       *mesh = obj->get_mesh();
+               }
+               lib3ds_file_free(file);
+               return mesh;
+       }
+
+       mesh = load_mesh_ply(fname);
+       return mesh;
+}
+       
+
+static bool load_objects(Lib3dsFile *file, Scene *scene) {
+       // load meshes
+       unsigned long poly_count = 0;
+       Lib3dsMesh *m = file->meshes;
+       while(m) {
+
+               Lib3dsNode *node = lib3ds_file_node_by_name(file, m->name, LIB3DS_OBJECT_NODE);
+               if(!node) {
+                       warning("object \"%s\" does not have a corresponding node!", m->name);
+               }
+               Vector3 node_pos = node ? CONV_VEC3(node->data.object.pos) : Vector3();
+               Quaternion node_rot = node ? CONV_QUAT(node->data.object.rot) : Quaternion();
+               Vector3 node_scl = node ? CONV_VEC3(node->data.object.scl) : Vector3(1,1,1);
+               Vector3 pivot = node ? CONV_VEC3(node->data.object.pivot) : Vector3();
+
+               // load the vertices
+               Vertex *varray = new Vertex[m->points];
+               Vertex *vptr = varray;
+               for(int i=0; i<(int)m->points; i++) {
+                       vptr->pos = CONV_VEC3(m->pointL[i].pos) - node_pos;
+                       vptr->pos.transform(node_rot);
+                       
+                       if(m->texels) {
+                               vptr->tex[0] = vptr->tex[1] = CONV_TEXCOORD(m->texelL[i]);
+                       }
+                       
+                       vptr++;
+               }
+               
+               if(m->faces) {
+                       poly_count += m->faces;
+                       // -------- object ---------
+                       Object *obj = new Object;
+                       obj->set_dynamic(false);
+
+                       obj->name = m->name;
+
+                       obj->set_position(node_pos - pivot);
+                       obj->set_rotation(node_rot);
+                       obj->set_scaling(node_scl);
+
+                       obj->set_pivot(pivot);
+               
+                       // load the polygons
+                       Triangle *tarray = new Triangle[m->faces];
+                       Triangle *tptr = tarray;
+                       for(int i=0; i<(int)m->faces; i++) {
+                               *tptr = CONV_TRIANGLE(m->faceL[i]);
+                               tptr->normal = CONV_VEC3(m->faceL[i].normal);
+                               tptr->smoothing_group = m->faceL[i].smoothing;
+
+                               tptr++;
+                       }
+
+                       // set the geometry data to the object
+                       obj->get_mesh_ptr()->set_data(varray, m->points, tarray, m->faces);
+                       obj->get_mesh_ptr()->calculate_normals();
+               
+                       delete [] tarray;
+
+                       // load the material
+                       load_material(file, m->faceL[0].material, obj->get_material_ptr());
+
+                       // load the keyframes (if any)
+                       if(load_keyframes(file, m->name, LIB3DS_OBJECT_NODE, obj)) {
+                               obj->set_position(Vector3());
+                               obj->set_rotation(Quaternion());
+                               obj->set_scaling(Vector3(1, 1, 1));
+                       }
+
+                       scene->add_object(obj);
+                       
+               } else {
+                       // --------- curve ------------
+                       Curve *curve = new CatmullRomSplineCurve;
+                       curve->name = m->name;
+
+                       Vector3 offs = node_pos - pivot;
+                       
+                       for(int i=0; i<(int)m->points; i++) {
+                               curve->add_control_point(varray[i].pos + offs);
+                       }
+
+                       scene->add_curve(curve);
+               }
+
+               delete [] varray;
+
+
+               m = m->next;
+       }
+       
+       scene->set_poly_count(poly_count);
+       return true;
+}
+
+static bool is_pow_two(unsigned long val) {
+       int count_ones = 0;
+       while(val && count_ones <= 1) {
+               if(val & 1) count_ones++;
+               val >>= 1;
+       }
+       return (count_ones == 1 && !(val & 1)) ? true : false;
+}
+
+static bool load_material(Lib3dsFile *file, const char *name, Material *mat) {
+       Lib3dsMaterial *m;
+       if(!name || !*name || !(m = lib3ds_file_material_by_name(file, name))) {
+               return false;
+       }
+       
+       mat->name = name;
+       mat->ambient_color = CONV_RGBA(m->ambient);
+       mat->diffuse_color = CONV_RGBA(m->diffuse);
+       mat->specular_color = CONV_RGBA(m->specular) * m->shin_strength;
+       if(m->self_illum) {
+               std::cerr << "self illuminating material: " << name << std::endl;
+               mat->emissive_color = 1.0;
+       }
+       
+       scalar_t s = pow(2.0, 10.0 * m->shininess);
+       mat->specular_power = s > 128.0 ? 128.0 : s;
+
+       mat->alpha = 1.0 - m->transparency;
+
+       if(m->shading == LIB3DS_WIRE_FRAME || m->use_wire) {
+               mat->wireframe = true;
+       }
+       
+       if(m->shading == LIB3DS_FLAT) {
+               mat->shading = SHADING_FLAT;
+       }
+
+       // load the textures
+       Texture *tex = 0, *detail = 0, *env = 0, *light = 0, *bump = 0;
+       const char *tpath;
+       
+       tpath = tex_path(m->texture1_map.name);
+       if(tpath && (tex = get_texture(tpath))) {
+               mat->set_texture(tex, TEXTYPE_DIFFUSE);
+       }
+
+       tpath = tex_path(m->texture2_map.name);
+       if(tpath && (detail = get_texture(tpath))) {
+               mat->set_texture(detail, TEXTYPE_DETAIL);
+       }
+
+       tpath = tex_path(m->reflection_map.name);
+       if(tpath && (env = get_texture(tpath))) {
+               mat->set_texture(env, TEXTYPE_ENVMAP);
+               mat->env_intensity = m->reflection_map.percent;
+       }
+       
+       tpath = tex_path(m->bump_map.name);
+       if(tpath && (bump = get_texture(tpath))) {
+               //FIXME: make dot3 work first mat->set_texture(bump, TEXTYPE_BUMPMAP);
+       }
+
+       tpath = tex_path(m->self_illum_map.name);
+       if(tpath && (light = get_texture(tpath))) {
+               mat->set_texture(light, TEXTYPE_LIGHTMAP);
+       }
+
+       if(m->autorefl_map.flags & LIB3DS_USE_REFL_MAP) {
+               mat->env_intensity = m->reflection_map.percent;
+               
+               int cube_sz = m->autorefl_map.size;
+               if(!is_pow_two(cube_sz)) {
+                       warning("Material \"%s\" specifies a non power of 2 cube map and won't render correctly!", m->name);
+               }
+               
+               Texture *cube_tex = new Texture(cube_sz, cube_sz, TEX_CUBE);
+               add_texture(cube_tex);
+
+               mat->set_texture(cube_tex, TEXTYPE_ENVMAP);
+               mat->auto_refl_upd = m->autorefl_map.frame_step;
+               if(m->autorefl_map.flags & LIB3DS_READ_FIRST_FRAME_ONLY ||
+                       m->autorefl_map.flags & 0x8 || m->autorefl_map.frame_step == 1000) {
+                       mat->auto_refl = true;
+                       mat->auto_refl_upd = 0;
+               }
+       }
+               
+
+       return true;
+}
+
+static const char *tex_path(const char *path) {
+       if(!path || !*path) return 0;
+
+       static char texpath[TPATH_SIZE];
+
+       strncpy(texpath, data_path, TPATH_SIZE);
+       texpath[TPATH_SIZE - 1] = 0;
+
+       const char *tmp = strrchr(path, '\\');
+       if(tmp) path = tmp + 1;
+
+       char *tp_ptr = texpath + strlen(texpath);
+       do {
+               *tp_ptr++ = tolower(*path++);
+       } while(*path);
+               
+       return texpath;
+}
+
+
+bool load_lights(Lib3dsFile *file, Scene *scene) {
+       Lib3dsLight *lt = file->lights;
+       while(lt) {
+               Light *light;
+               
+               if(!lt->spot_light) {
+                       light = new PointLight;
+                       light->name = lt->name;
+                       light->set_position(CONV_VEC3(lt->position));
+                       light->set_color(CONV_RGB(lt->color));
+                       light->set_intensity(lt->multiplier);
+                       //TODO: attenuation
+               } else {
+                       light = 0;      // TODO: support spotlights at some point
+               }
+
+               if(light) {
+                       if(load_keyframes(file, lt->name, LIB3DS_LIGHT_NODE, light)) {
+                               light->set_position(Vector3());
+                       }
+                       scene->add_light(light);
+               }
+
+               lt = lt->next;
+       }
+
+       return true;
+}
+
+bool load_cameras(Lib3dsFile *file, Scene *scene) {
+       Lib3dsCamera *c = file->cameras;
+       while(c) {
+               TargetCamera *cam = new TargetCamera;
+               cam->name = c->name;
+               cam->set_position(CONV_VEC3(c->position));
+               cam->set_target(CONV_VEC3(c->target));
+               //cam->set_clipping_planes(c->near_range, c->far_range);
+               
+               //scalar_t angle = atan(1.0 / cam->get_aspect());
+               //cam->set_fov(sin(angle) * DEG_TO_RAD(c->fov));
+               cam->set_fov(DEG_TO_RAD(c->fov) / cam->get_aspect());
+
+               if(load_keyframes(file, c->name, LIB3DS_CAMERA_NODE, cam)) {
+                       cam->set_position(Vector3());
+               }
+               //TODO: load_keyframes(file, ... hmmm where is the target node?
+               
+               scene->add_camera(cam);
+               c = c->next;
+       }
+       return true;
+}
+
+
+#define FPS    30
+#define FRAME_TO_TIME(x)       (((x) * 1000) / FPS)
+
+static bool load_keyframes(Lib3dsFile *file, const char *name, Lib3dsNodeTypes type, XFormNode *node) {
+       if(!name || !*name) return false;
+       
+       Lib3dsNode *n = lib3ds_file_node_by_name(file, name, type);
+       if(!n) return false;
+
+       switch(type) {
+       case LIB3DS_OBJECT_NODE:
+               {
+                       Lib3dsObjectData *obj = &n->data.object;
+                       std::vector<int> *frames = get_frames(obj);
+                       if(!frames) return false;
+
+                       for(int i=0; i<(int)frames->size(); i++) {
+                               lib3ds_node_eval(n, (float)(*frames)[i]);
+                                       
+                               Vector3 pos = CONV_VEC3(obj->pos) - CONV_VEC3(obj->pivot);
+                               Quaternion rot = CONV_QUAT(obj->rot);
+                               Vector3 scl = CONV_VEC3(obj->scl);
+
+                               Keyframe key(PRS(pos, rot, scl), FRAME_TO_TIME((*frames)[i]));
+                               node->add_keyframe(key);
+                       }
+               }
+               break;
+
+       case LIB3DS_LIGHT_NODE:
+               {
+                       Lib3dsLightData *light = &n->data.light;
+                       std::vector<int> *frames = get_frames(light);
+                       if(!frames) return false;
+
+                       for(int i=0; i<(int)frames->size(); i++) {
+                               lib3ds_node_eval(n, (float)(*frames)[i]);
+
+                               Vector3 pos = CONV_VEC3(light->pos);
+
+                               Keyframe key(PRS(pos, Quaternion()), FRAME_TO_TIME((*frames)[i]));
+                               node->add_keyframe(key);
+                       }
+               }
+               break;
+
+       case LIB3DS_CAMERA_NODE:
+               {
+                       Lib3dsCameraData *cam = &n->data.camera;
+                       std::vector<int> *frames = get_frames(cam);
+                       if(!frames) return false;
+
+                       for(int i=0; i<(int)frames->size(); i++) {
+                               lib3ds_node_eval(n, (float)(*frames)[i]);
+
+                               Vector3 pos = CONV_VEC3(cam->pos);
+
+                               Keyframe key(PRS(pos, Quaternion()), FRAME_TO_TIME((*frames)[i]));
+                               node->add_keyframe(key);
+                       }
+               }
+               break;
+
+               /*
+       case LIB3DS_TARGET_NODE:
+               {
+                       Lib3dsCameraData *targ = &n->data.target;
+                       std::vector<int> *frames = get_frames(targ);
+                       if(!frames) return false;
+
+                       for(int i=0; i<(int)frames->size(); i++) {
+                               lib3ds_node_eval(n, (float)(*frames)[i]);
+
+                               Vector3 pos = CONV_VEC3(targ->pos);
+
+                               Keyframe key(PRS(pos, Quaternion()), FRAME_TO_TIME((*frames)[i]));
+                               node->add_keyframe(key);
+                       }
+
+               }
+               break;
+               */
+
+       default:
+               break;
+       }
+
+       return true;
+}
+
+static void construct_hierarchy(Lib3dsFile *file, Scene *scene) {
+       std::list<Object*> *list = scene->get_object_list();
+       std::list<Object*>::iterator iter = list->begin();
+       while(iter != list->end()) {
+               Object *obj = *iter;
+               Lib3dsNode *n = lib3ds_file_node_by_name(file, obj->name.c_str(), LIB3DS_OBJECT_NODE);
+               if(!n) {
+                       iter++;
+                       continue;
+               }
+
+               // get parent
+               if(n->parent) {
+                       obj->parent = scene->get_node(n->parent->name);
+               }
+               
+               // get children
+               Lib3dsNode *child = n->childs;
+               while(child) {
+                       XFormNode *child_node = scene->get_node(child->name);
+                       if(child_node) {
+                               (*iter)->children.push_back(child_node);
+                       }
+                       child = child->next;
+               }
+
+               iter++;
+       }
+}
+
+
+/*
+static void fix_hierarchy(XFormNode *node) {
+       if(!node) return;
+
+       if(node->parent) {
+               XFormNode *parent = node->parent;
+               node->parent = 0;
+               PRS prs = node->get_prs(XFORM_LOCAL_PRS);
+               node->parent = parent;
+               
+               PRS pprs = node->parent->get_prs(XFORM_LOCAL_PRS);
+
+               Vector3 pos = prs.position.transformed(pprs.rotation.conjugate());
+               
+               node->set_position(pos);
+       }
+
+       for(int i=0; i<(int)node->children.size(); i++) {
+               fix_hierarchy(node->children[i]);
+       }
+}
+*/                     
+
+static std::vector<int> *get_frames(Lib3dsObjectData *o) {
+       static std::vector<int> frames;
+       
+       Lib3dsLin3Key *pos_key = o->pos_track.keyL;
+       while(pos_key) {
+               int frame = pos_key->tcb.frame;
+               if(find(frames.begin(), frames.end(), frame) == frames.end()) {
+                       frames.push_back(frame);
+               }
+               pos_key = pos_key->next;
+       }
+
+       Lib3dsQuatKey *rot_key = o->rot_track.keyL;
+       while(rot_key) {
+               int frame = rot_key->tcb.frame;
+               if(find(frames.begin(), frames.end(), frame) == frames.end()) {
+                       frames.push_back(frame);
+               }
+               rot_key = rot_key->next;
+       }
+
+       Lib3dsLin3Key *scl_key = o->scl_track.keyL;
+       while(scl_key) {
+               int frame = scl_key->tcb.frame;
+               if(find(frames.begin(), frames.end(), frame) == frames.end()) {
+                       frames.push_back(frame);
+               }
+               scl_key = scl_key->next;
+       }
+
+       if(frames.size() > 1) return &frames;
+       return 0;
+}
+
+static std::vector<int> *get_frames(Lib3dsLightData *lt) {
+       static std::vector<int> frames;
+       
+       Lib3dsLin3Key *pos_key = lt->pos_track.keyL;
+       while(pos_key) {
+               int frame = pos_key->tcb.frame;
+               frames.push_back(frame);
+               pos_key = pos_key->next;
+       }
+
+       if(frames.size() > 1) return &frames;
+       return 0;
+}
+
+static std::vector<int> *get_frames(Lib3dsCameraData *cam) {
+       static std::vector<int> frames;
+       
+       Lib3dsLin3Key *pos_key = cam->pos_track.keyL;
+       while(pos_key) {
+               int frame = pos_key->tcb.frame;
+               frames.push_back(frame);
+               pos_key = pos_key->next;
+       }
+
+       if(frames.size() > 1) return &frames;
+       return 0;
+}
diff --git a/src/3dengfx/src/3dengfx/sceneloader.hpp b/src/3dengfx/src/3dengfx/sceneloader.hpp
new file mode 100644 (file)
index 0000000..5de792c
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+This file is part of the 3dengfx, realtime visualization system.
+
+Copyright (c) 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* Scene loader from 3ds files.
+ *
+ * author: John Tsiombikas 2005
+ */
+
+#ifndef _SCENELOADER_HPP_
+#define _SCENELOADER_HPP_
+
+#include "object.hpp"
+#include "3dscene.hpp"
+#include "material.hpp"
+
+void set_scene_data_path(const char *path);
+
+Scene *load_scene(const char *fname);
+TriMesh *load_mesh(const char *fname, const char *name = 0);
+
+#endif // _SCENELOADER_H_
diff --git a/src/3dengfx/src/3dengfx/scfield.cpp b/src/3dengfx/src/3dengfx/scfield.cpp
new file mode 100644 (file)
index 0000000..fe67628
--- /dev/null
@@ -0,0 +1,659 @@
+/*
+This file is part of the 3dengfx, realtime visualization system.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+3dengfx is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+3dengfx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with 3dengfx; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* Scalar fields and polygonization
+ *
+ * Author: Mihalis Georgoulopoulos 2005
+ */
+
+#define SCFIELD_SOURCE
+#include "mcube_tables.h"
+#include "scfield.hpp"
+#include "3dengfx/3denginefx.hpp"
+
+// don't change this
+#define EDGE_NOT_ASSOCIATED            0xFFFFFFFF
+
+/* -----------------
+ * private functions
+ * -----------------
+ */
+
+/*
+ * AddVertex
+ * adds a vertex and returns its index
+ */
+unsigned int ScalarField::add_vertex(const Vertex &vert)
+{
+       verts.push_back(vert);
+       return verts.size() - 1;
+}
+
+/*
+ * Clear
+ * clears std::vector's that hold mesh data and resets edges table
+ */
+void ScalarField::clear()
+{
+       verts.erase(verts.begin(), verts.end());
+       tris.erase(tris.begin(), tris.end());
+       
+       unsigned int num_bytes = dimensions * dimensions * dimensions * sizeof(unsigned int);
+
+       memset(edges_x, 0xFF, num_bytes);
+       memset(edges_y, 0xFF, num_bytes);
+       memset(edges_z, 0xFF, num_bytes);
+}
+
+/*
+ * EvaluateAll
+ * Evaluates all values with the external Evaluate function (if specified)
+ */
+void ScalarField::evaluate_all(scalar_t t)
+{
+       if (!evaluate)
+       {
+               return;
+       }
+
+       for (unsigned int z=0; z<dimensions; z++)
+       {
+               for (unsigned int y=0; y<dimensions; y++)
+               {
+                       for (unsigned int x=0; x<dimensions; x++)
+                       {
+                               set_value(x, y, z, evaluate(get_position(x, y, z), t));
+                       }
+               }
+       }
+}
+
+
+/*
+ * ProcesssCell
+ */
+void ScalarField::process_cell(int x, int y, int z, scalar_t isolevel)
+{
+       unsigned char cube_index = 0;
+       if(get_value(x, y, z, 0) < isolevel) cube_index |= 1;
+       if(get_value(x, y, z, 1) < isolevel) cube_index |= 2;
+       if(get_value(x, y, z, 2) < isolevel) cube_index |= 4;
+       if(get_value(x, y, z, 3) < isolevel) cube_index |= 8;
+       if(get_value(x, y, z, 4) < isolevel) cube_index |= 16;
+       if(get_value(x, y, z, 5) < isolevel) cube_index |= 32;
+       if(get_value(x, y, z, 6) < isolevel) cube_index |= 64;
+       if(get_value(x, y, z, 7) < isolevel) cube_index |= 128;
+
+       int edge_index = cube_edge_flags[cube_index];
+
+       scalar_t p , val1, val2;
+       Vector3 vec1, vec2;
+
+       if ( (edge_index & 1) && (get_edge(x, y, z, 0) == EDGE_NOT_ASSOCIATED) )
+       {
+               val1 = get_value(x, y, z, 0);
+               val2 = get_value(x, y, z, 1);
+               p = (isolevel - val1) / (val2 - val1);
+               
+               vec1 = get_position(x, y, z, 0);
+               vec2 = get_position(x, y, z, 1);
+
+               set_edge(x, y, z, 0, add_vertex( Vertex( vec1 + p * (vec2 - vec1) ) ) );
+       }
+
+       if ( (edge_index & 2) && (get_edge(x, y, z, 1) == EDGE_NOT_ASSOCIATED) )
+       {
+               val1 = get_value(x, y, z, 1);
+               val2 = get_value(x, y, z, 2);
+               p = (isolevel - val1) / (val2 - val1);
+               
+               vec1 = get_position(x, y, z, 1);
+               vec2 = get_position(x, y, z, 2);
+
+               set_edge(x, y, z, 1, add_vertex( Vertex( vec1 + p * (vec2 - vec1) ) ) );
+       }
+
+       if ( (edge_index & 4) && (get_edge(x, y, z, 2) == EDGE_NOT_ASSOCIATED) )
+       {
+               val1 = get_value(x, y, z, 2);
+               val2 = get_value(x, y, z, 3);
+               p = (isolevel - val1) / (val2 - val1);
+               
+               vec1 = get_position(x, y, z, 2);
+               vec2 = get_position(x, y, z, 3);
+
+               set_edge(x, y, z, 2, add_vertex( Vertex( vec1 + p * (vec2 - vec1) ) ) );
+       }
+
+       if ( (edge_index & 8) && (get_edge(x, y, z, 3) == EDGE_NOT_ASSOCIATED) )
+       {
+               val1 = get_value(x, y, z, 3);
+               val2 = get_value(x, y, z, 0);
+               p = (isolevel - val1) / (val2 - val1);
+               
+               vec1 = get_position(x, y, z, 0);
+               vec2 = get_position(x, y, z, 1);
+
+               set_edge(x, y, z, 3, add_vertex( Vertex( vec1 + p * (vec2 - vec1) ) ) );
+       }
+
+       if ( (edge_index & 16) && (get_edge(x, y, z, 4) == EDGE_NOT_ASSOCIATED) )
+       {
+               val1 = get_value(x, y, z, 4);
+               val2 = get_value(x, y, z, 5);
+               p = (isolevel - val1) / (val2 - val1);
+               
+               vec1 = get_position(x, y, z, 4);
+               vec2 = get_position(x, y, z, 5);
+
+               set_edge(x, y, z, 4, add_vertex( Vertex( vec1 + p * (vec2 - vec1) ) ) );
+       }
+
+       if ( (edge_index & 32) && (get_edge(x, y, z, 5) == EDGE_NOT_ASSOCIATED) )
+       {
+               val1 = get_value(x, y, z, 5);
+               val2 = get_value(x, y, z, 6);
+               p = (isolevel - val1) / (val2 - val1);
+               
+               vec1 = get_position(x, y, z, 5);
+               vec2 = get_position(x, y, z, 6);
+
+               set_edge(x, y, z, 5, add_vertex( Vertex( vec1 + p * (vec2 - vec1) ) ) );
+       }
+
+       if ( (edge_index & 64) && (get_edge(x, y, z, 6) == EDGE_NOT_ASSOCIATED) )
+       {
+               val1 = get_value(x, y, z, 6);
+               val2 = get_value(x, y, z, 7);
+               p = (isolevel - val1) / (val2 - val1);
+               
+               vec1 = get_position(x, y, z, 6);
+               vec2 = get_position(x, y, z, 7);
+
+               set_edge(x, y, z, 6, add_vertex( Vertex( vec1 + p * (vec2 - vec1) ) ) );
+       }
+
+       if ( (edge_index & 128) && (get_edge(x, y, z, 7) == EDGE_NOT_ASSOCIATED) )
+       {
+               val1 = get_value(x, y, z, 7);
+               val2 = get_value(x, y, z, 4);
+               p = (isolevel - val1) / (val2 - val1);
+               
+               vec1 = get_position(x, y, z, 7);
+               vec2 = get_position(x, y, z, 4);
+
+               set_edge(x, y, z, 7, add_vertex( Vertex( vec1 + p * (vec2 - vec1) ) ) );
+       }
+
+       if ( (edge_index & 256) && (get_edge(x, y, z, 8) == EDGE_NOT_ASSOCIATED) )
+       {
+               val1 = get_value(x, y, z, 0);
+               val2 = get_value(x, y, z, 4);
+               p = (isolevel - val1) / (val2 - val1);
+               
+               vec1 = get_position(x, y, z, 0);
+               vec2 = get_position(x, y, z, 4);
+
+               set_edge(x, y, z, 8, add_vertex( Vertex( vec1 + p * (vec2 - vec1) ) ) );
+       }
+
+       if ( (edge_index & 512) && (get_edge(x, y, z, 9) == EDGE_NOT_ASSOCIATED) )
+       {
+               val1 = get_value(x, y, z, 1);
+               val2 = get_value(x, y, z, 5);
+               p = (isolevel - val1) / (val2 - val1);
+               
+               vec1 = get_position(x, y, z, 1);
+               vec2 = get_position(x, y, z, 5);
+
+               set_edge(x, y, z, 9, add_vertex( Vertex( vec1 + p * (vec2 - vec1) ) ) );
+       }
+
+       if ( (edge_index & 1024) && (get_edge(x, y, z, 10) == EDGE_NOT_ASSOCIATED) )
+       {
+               val1 = get_value(x, y, z, 2);
+               val2 = get_value(x, y, z, 6);
+               p = (isolevel - val1) / (val2 - val1);
+               
+               vec1 = get_position(x, y, z, 2);
+               vec2 = get_position(x, y, z, 6);
+
+               set_edge(x, y, z, 10, add_vertex( Vertex( vec1 + p * (vec2 - vec1) ) ) );
+       }
+
+       if ( (edge_index & 2048) && (get_edge(x, y, z, 11) == EDGE_NOT_ASSOCIATED) )
+       {
+               val1 = get_value(x, y, z, 3);
+               val2 = get_value(x, y, z, 7);
+               p = (isolevel - val1) / (val2 - val1);
+               
+               vec1 = get_position(x, y, z, 3);
+               vec2 = get_position(x, y, z, 7);
+
+               set_edge(x, y, z, 11, add_vertex( Vertex( vec1 + p * (vec2 - vec1) ) ) );
+       }
+
+       // Add triangles
+       unsigned int p1, p2, p3;
+
+       if (tri_table[cube_index][0] != -1)
+       {
+               p1 = get_edge(x, y, z, tri_table[cube_index][0]);
+               p2 = get_edge(x, y, z, tri_table[cube_index][1]);
+               p3 = get_edge(x, y, z, tri_table[cube_index][2]);
+               tris.push_back(Triangle(p2, p1, p3));
+       }
+
+       if (tri_table[cube_index][3] != -1)
+       {
+               p1 = get_edge(x, y, z, tri_table[cube_index][3]);
+               p2 = get_edge(x, y, z, tri_table[cube_index][4]);
+               p3 = get_edge(x, y, z, tri_table[cube_index][5]);
+               tris.push_back(Triangle(p2, p1, p3));
+       }
+
+       if (tri_table[cube_index][6] != -1)
+       {
+               p1 = get_edge(x, y, z, tri_table[cube_index][6]);
+               p2 = get_edge(x, y, z, tri_table[cube_index][7]);
+               p3 = get_edge(x, y, z, tri_table[cube_index][8]);
+               tris.push_back(Triangle(p2, p1, p3));
+       }
+
+       if (tri_table[cube_index][9] != -1)
+       {
+               p1 = get_edge(x, y, z, tri_table[cube_index][9]);
+               p2 = get_edge(x, y, z, tri_table[cube_index][10]);
+               p3 = get_edge(x, y, z, tri_table[cube_index][11]);
+               tris.push_back(Triangle(p2, p1, p3));
+       }
+
+       if (tri_table[cube_index][12] != -1)
+       {
+               p1 = get_edge(x, y, z, tri_table[cube_index][12]);
+               p2 = get_edge(x, y, z, tri_table[cube_index][13]);
+               p3 = get_edge(x, y, z, tri_table[cube_index][14]);
+               tris.push_back(Triangle(p2, p1, p3));
+       }
+}
+
+/*
+ * GetValueIndex
+ * returns the index to the values array for the specified coords
+ */
+unsigned int ScalarField::get_value_index(int x, int y, int z)
+{
+       return x + y * dimensions + z * dimensions * dimensions;
+}
+
+
+Vector3 ScalarField::def_eval_normals(const Vector3 &vec, scalar_t t) {
+       if(!evaluate) return Vector3(0, 0, 0);
+       
+       Vector3 diff = cell_size * 0.25;
+
+       Vector3 grad;
+       grad.x = evaluate(vec + Vector3(diff.x, 0, 0), t) - evaluate(vec + Vector3(-diff.x, 0, 0), t);
+       grad.y = evaluate(vec + Vector3(0, diff.y, 0), t) - evaluate(vec + Vector3(0, -diff.y, 0), t);
+       grad.z = evaluate(vec + Vector3(0, 0, diff.z), t) - evaluate(vec + Vector3(0, 0, -diff.z), t);
+
+       return grad.normalized();
+}
+
+/* --------------
+ * public methods
+ * --------------
+ */
+
+// constructor
+ScalarField::ScalarField()
+{
+       values = 0;
+       edges_x = edges_y = edges_z = 0;
+       dimensions = 0;
+       from = to = cell_size =  Vector3(0, 0, 0);
+       evaluate = 0;
+       get_normal = 0;
+}
+
+ScalarField::ScalarField(unsigned int dimensions, const Vector3 &from, const Vector3 &to)
+{
+       this->dimensions = dimensions;
+       this->from = from;
+       this->to = to;
+       this->cell_size =  (to - from) / (dimensions - 1);
+
+       values = 0;
+       edges_x = edges_y = edges_z = 0;
+
+       evaluate = 0;
+       get_normal = 0;
+
+       set_dimensions(dimensions);
+}
+
+ScalarField::~ScalarField()
+{
+       if (values)
+               delete [] values;
+       if (edges_x)
+               delete [] edges_x;
+       if (edges_y)
+               delete [] edges_y;
+       if (edges_z)
+               delete [] edges_z;
+}
+
+void ScalarField::set_dimensions(unsigned int dimensions)
+{
+       this->dimensions = dimensions;
+       if (values)
+               delete [] values;
+       if (edges_x)
+               delete [] edges_x;
+       if (edges_y)
+               delete [] edges_y;
+       if (edges_z)
+               delete [] edges_z;
+
+       values = new scalar_t [dimensions * dimensions * dimensions];
+       
+       unsigned int edges_per_dim = dimensions * dimensions * dimensions;
+       edges_x = new unsigned int[edges_per_dim];
+       edges_y = new unsigned int[edges_per_dim];
+       edges_z = new unsigned int[edges_per_dim];
+
+       clear();
+}
+
+// Get / Set
+void ScalarField::set_value(int x, int y, int z, scalar_t value)
+{
+       values[get_value_index(x, y, z)] = value;
+}
+
+scalar_t ScalarField::get_value(int x, int y, int z)
+{
+       return values[get_value_index(x, y, z)];
+}
+
+
+// get / set relative to cell
+void ScalarField::set_value(int cx, int cy, int cz, int vert_index, scalar_t value)
+{
+       if (vert_index == 0) set_value(cx + 0, cy + 0, cz + 1, value);
+       else if (vert_index == 1) set_value(cx + 1, cy + 0, cz + 1, value);
+       else if (vert_index == 2) set_value(cx + 1, cy + 0, cz + 0, value);
+       else if (vert_index == 3) set_value(cx + 0, cy + 0, cz + 0, value);
+       else if (vert_index == 4) set_value(cx + 0, cy + 1, cz + 1, value);
+       else if (vert_index == 5) set_value(cx + 1, cy + 1, cz + 1, value);
+       else if (vert_index == 6) set_value(cx + 1, cy + 1, cz + 0, value);
+       else if (vert_index == 7) set_value(cx + 0, cy + 1, cz + 0, value);
+}
+
+
+scalar_t ScalarField::get_value(int cx, int cy, int cz, int vert_index)
+{
+       if (vert_index == 0) return get_value(cx + 0, cy + 0, cz + 1);
+       if (vert_index == 1) return get_value(cx + 1, cy + 0, cz + 1);
+       if (vert_index == 2) return get_value(cx + 1, cy + 0, cz + 0);
+       if (vert_index == 3) return get_value(cx + 0, cy + 0, cz + 0);
+       if (vert_index == 4) return get_value(cx + 0, cy + 1, cz + 1);
+       if (vert_index == 5) return get_value(cx + 1, cy + 1, cz + 1);
+       if (vert_index == 6) return get_value(cx + 1, cy + 1, cz + 0);
+       if (vert_index == 7) return get_value(cx + 0, cy + 1, cz + 0);
+
+       return 0;
+}
+
+// edges are addressed relatively to a cell (cx, cy, cz)
+// and the cell's edge number
+void ScalarField::set_edge(int cx, int cy, int cz, int edge, unsigned int index)
+{
+       unsigned int d = dimensions;
+       unsigned int d2 = dimensions * dimensions;
+       
+       if (edge == 0) 
+               edges_x[cx + 0 + (cy + 0) * d + (cz + 1) * d2] =  index;
+       else if (edge == 1) 
+               edges_z[cx + 1 + (cy + 0) * d + (cz + 0) * d2] =  index;
+       else if (edge == 2) 
+               edges_x[cx + 0 + (cy + 0) * d + (cz + 0) * d2] =  index;
+       else if (edge == 3) 
+               edges_z[cx + 0 + (cy + 0) * d + (cz + 0) * d2] =  index;
+       else if (edge == 4) 
+               edges_x[cx + 0 + (cy + 1) * d + (cz + 1) * d2] =  index;
+       else if (edge == 5) 
+               edges_z[cx + 1 + (cy + 1) * d + (cz + 0) * d2] =  index;
+       else if (edge == 6) 
+               edges_x[cx + 0 + (cy + 1) * d + (cz + 0) * d2] =  index;
+       else if (edge == 7) 
+               edges_z[cx + 0 + (cy + 1) * d + (cz + 0) * d2] =  index;
+       else if (edge == 8) 
+               edges_y[cx + 0 + (cy + 0) * d + (cz + 1) * d2] =  index;
+       else if (edge == 9) 
+               edges_y[cx + 1 + (cy + 0) * d + (cz + 1) * d2] =  index;
+       else if (edge == 10) 
+               edges_y[cx + 1 + (cy + 0) * d + (cz + 0) * d2] =  index;
+       else if (edge == 11) 
+               edges_y[cx + 0 + (cy + 0) * d + (cz + 0) * d2] =  index;
+}
+
+unsigned int ScalarField::get_edge(int cx, int cy, int cz, int edge)
+{
+       unsigned int d = dimensions;
+       unsigned int d2 = dimensions * dimensions;
+
+       if (edge == 0)  return edges_x[cx + 0 + (cy + 0) * d + (cz + 1) * d2];
+       if (edge == 1)  return edges_z[cx + 1 + (cy + 0) * d + (cz + 0) * d2];
+       if (edge == 2)  return edges_x[cx + 0 + (cy + 0) * d + (cz + 0) * d2];
+       if (edge == 3)  return edges_z[cx + 0 + (cy + 0) * d + (cz + 0) * d2];
+       if (edge == 4)  return edges_x[cx + 0 + (cy + 1) * d + (cz + 1) * d2];
+       if (edge == 5)  return edges_z[cx + 1 + (cy + 1) * d + (cz + 0) * d2];
+       if (edge == 6)  return edges_x[cx + 0 + (cy + 1) * d + (cz + 0) * d2];
+       if (edge == 7)  return edges_z[cx + 0 + (cy + 1) * d + (cz + 0) * d2];
+       if (edge == 8)  return edges_y[cx + 0 + (cy + 0) * d + (cz + 1) * d2];
+       if (edge == 9)  return edges_y[cx + 1 + (cy + 0) * d + (cz + 1) * d2];
+       if (edge == 10) return edges_y[cx + 1 + (cy + 0) * d + (cz + 0) * d2];
+       if (edge == 11) return edges_y[cx + 0 + (cy + 0) * d + (cz + 0) * d2];
+
+       return 0;
+}
+
+// Position in space
+Vector3 ScalarField::get_position(int x, int y, int z)
+{
+       scalar_t vx, vy, vz;
+       vx = from.x + cell_size.x * x;
+       vy = from.y + cell_size.y * y;
+       vz = from.z + cell_size.z * z;
+
+       return Vector3(vx, vy, vz);
+}
+
+Vector3 ScalarField::get_position(int cx, int cy, int cz, int vert_index)
+{
+       if (vert_index == 0) return get_position(cx + 0, cy + 0, cz + 1);
+       if (vert_index == 1) return get_position(cx + 1, cy + 0, cz + 1);
+       if (vert_index == 2) return get_position(cx + 1, cy + 0, cz + 0);
+       if (vert_index == 3) return get_position(cx + 0, cy + 0, cz + 0);
+       if (vert_index == 4) return get_position(cx + 0, cy + 1, cz + 1);
+       if (vert_index == 5) return get_position(cx + 1, cy + 1, cz + 1);
+       if (vert_index == 6) return get_position(cx + 1, cy + 1, cz + 0);
+       if (vert_index == 7) return get_position(cx + 0, cy + 1, cz + 0);
+
+       return Vector3(0, 0, 0);
+}
+
+void ScalarField::set_from_to(const Vector3 &from, const Vector3 &to)
+{
+       this->from = from;
+       this->to = to;
+       this->cell_size = (to - from) / (dimensions - 1);
+}
+
+void ScalarField::draw_field(bool full)
+{
+       set_lighting(false);
+               
+       if (full)
+       {
+               glBegin(GL_LINES);
+               {
+                       glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+
+                       for (unsigned int j=0; j<dimensions; j++)
+                       {
+                               for (unsigned int i=0; i<dimensions; i++)
+                               {
+                                       // x lines
+                                       glVertex3f(from.x, from.y + i * cell_size.y, from.z + j * cell_size.z); 
+                                       glVertex3f(  to.x, from.y + i * cell_size.y, from.z + j * cell_size.z);
+
+                                       // y lines
+                                       glVertex3f(from.x + i * cell_size.x, from.y, from.z + j * cell_size.z); 
+                                       glVertex3f(from.x + i * cell_size.x,   to.y, from.z + j * cell_size.z);
+
+                                       // z lines
+                                       glVertex3f(from.x + i * cell_size.x, from.y + j * cell_size.y, from.z); 
+                                       glVertex3f(from.x + i * cell_size.x, from.y + j * cell_size.y,   to.z);
+
+                               }
+                       }
+               }
+               glEnd();
+       }
+       else
+       {
+               glBegin(GL_LINES);
+               {
+                       glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+
+                       // x lines
+                       glVertex3f(from.x, from.y, from.z); glVertex3f(  to.x, from.y, from.z);
+                       glVertex3f(from.x,   to.y, from.z); glVertex3f(  to.x,   to.y, from.z);
+                       glVertex3f(from.x,   to.y,   to.z); glVertex3f(  to.x,   to.y,   to.z);
+                       glVertex3f(from.x, from.y,   to.z); glVertex3f(  to.x, from.y,   to.z);
+
+                       // y lines
+                       glVertex3f(from.x, from.y, from.z); glVertex3f(from.x,   to.y, from.z);
+                       glVertex3f(  to.x, from.y, from.z); glVertex3f(  to.x,   to.y, from.z);
+                       glVertex3f(  to.x, from.y,   to.z); glVertex3f(  to.x,   to.y,   to.z);
+                       glVertex3f(from.x, from.y,   to.z); glVertex3f(from.x,   to.y,   to.z);
+
+                       // z lines
+                       glVertex3f(from.x, from.y, from.z); glVertex3f(from.x, from.y,   to.z);
+                       glVertex3f(  to.x, from.y, from.z); glVertex3f(  to.x, from.y,   to.z);
+                       glVertex3f(  to.x,   to.y, from.z); glVertex3f(  to.x,   to.y,   to.z);
+                       glVertex3f(from.x,   to.y, from.z); glVertex3f(from.x,   to.y,   to.z);
+
+               }
+               glEnd();
+       }
+       set_lighting(true);
+}
+
+Vector3 ScalarField::get_from()
+{
+       return this->from;
+}
+
+Vector3 ScalarField::get_to()
+{
+       return this->to;
+}
+
+// Evaluators
+void ScalarField::set_evaluator(scalar_t (*evaluate) (const Vector3 &vec, scalar_t t))
+{
+       this->evaluate = evaluate;
+}
+       
+void ScalarField::set_normal_evaluator(Vector3 (*get_normal) (const Vector3 &vec, scalar_t t))
+{
+       this->get_normal = get_normal;
+}
+
+// last but not least
+void ScalarField::triangulate(TriMesh *mesh, scalar_t isolevel, scalar_t t, bool calc_normals)
+{
+       // Reset mesh and edges table
+       clear();
+
+       // Evaluate
+       evaluate_all(t);
+
+       // triangulate
+       for (unsigned int z=0; z<dimensions-1; z++)
+       {
+               for (unsigned int y=0; y<dimensions-1; y++)
+               {
+                       for (unsigned int x=0; x<dimensions-1; x++)
+                       {
+                               process_cell(x, y, z, isolevel);
+                       }
+               }
+       }
+
+       // Generate TriMesh
+       Vertex *varray = new Vertex[verts.size()];
+       Triangle *tarray = new Triangle[tris.size()];
+
+       for (unsigned int i=0; i<verts.size(); i++)
+       {
+               varray[i] = verts[i];
+       }
+
+       for (unsigned int i=0; i<tris.size(); i++)
+       {
+               tarray[i] = tris[i];
+       }
+
+       bool need_normals = calc_normals;
+       
+       // calculate normals if needed
+       if(need_normals) {
+               unsigned int vsz = verts.size();
+               if(get_normal) {
+                       for(unsigned int i=0; i<vsz; i++) {
+                               varray[i].normal = get_normal(varray[i].pos, t);
+                       }
+                       need_normals = false;
+               } else if(evaluate) {
+                       for(unsigned int i=0; i<vsz; i++) {
+                               varray[i].normal = def_eval_normals(varray[i].pos, t);
+                       }
+                       need_normals = false;
+               }
+       }
+       
+       mesh->set_data(varray, verts.size(), tarray, tris.size());
+
+       delete [] varray;
+       delete [] tarray;
+
+       // as a final resort, if we could not calculate normals any other way
+       // use the regular mesh normal calculation function.
+       if(need_normals) {
+               mesh->calculate_normals_by_index();
+       }
+}
+
+
diff --git a/src/3dengfx/src/3dengfx/scfield.hpp b/src/3dengfx/src/3dengfx/scfield.hpp
new file mode 100644 (file)
index 0000000..8cafd8e
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+This file is part of the 3dengfx, realtime visualization system.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+3dengfx is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+3dengfx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with 3dengfx; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* Scalar fields and polygonization
+ *
+ * Author: Mihalis Georgoulopoulos 2005
+ */
+
+#include <vector>
+#include "3dengfx/3denginefx_types.hpp"
+#include "n3dmath2/n3dmath2.hpp"
+#include "gfx/3dgeom.hpp"
+
+#ifndef _SCALAR_FIELD_HEADER_
+#define _SCALAR_FIELD_HEADER_
+
+class ScalarField
+{
+protected:
+       scalar_t *values;                                       // array that holds all values of the field
+       
+       unsigned int *edges_x, *edges_y, *edges_z;      // x- y- and z-aligned edges.
+                                                                                               // these arrays hold indices to the
+                                                                                               // vertex list, associated with the specific edge
+
+       unsigned int dimensions;                        // dimensions of the field
+       Vector3 from, to, cell_size;            // limits in space of the field
+
+       // Mesh storage
+       std::vector <Vertex> verts;
+       std::vector <Triangle> tris;
+
+       // Evaluators
+       scalar_t (*evaluate)(const Vector3 &vec, scalar_t t);
+       Vector3 (*get_normal)(const Vector3 &vec, scalar_t t);
+
+       // private methods
+       unsigned int add_vertex(const Vertex &vert);    // adds a vertex and returns its index
+       void clear();                           // clears the std::vectors that hold mesh data
+       void evaluate_all(scalar_t t);
+       void process_cell(int x, int y, int z, scalar_t isolevel);
+
+       unsigned int get_value_index(int x, int y, int z);
+       Vector3 def_eval_normals(const Vector3 &vec, scalar_t t);
+
+public:
+
+       // constructor
+       ScalarField();
+       ScalarField(unsigned int dimensions, const Vector3 &from, const Vector3 &to);
+       ~ScalarField();
+
+       void set_dimensions(unsigned int dimensions);
+       
+       // draw the 3d grid.
+       // if full, draws everything. If not, draws the bounding volume
+       void draw_field(bool full);
+
+       // Get / Set
+       void set_value(int x, int y, int z, scalar_t value);
+       scalar_t get_value(int x, int y, int z);
+
+       // get / set relative to cell
+       void set_value(int cx, int cy, int cz, int vert_index, scalar_t value);
+       scalar_t get_value(int cx, int cy, int cz, int vert_index);
+       
+       // edges are only addressed relative to a cell
+       void set_edge(int cx, int cy, int cz, int edge, unsigned int index);
+       unsigned int get_edge(int cx, int cy, int cz, int edge);
+
+       // Position in space
+       Vector3 get_position(int x, int y, int z);
+       Vector3 get_position(int cx, int cy, int cz, int vert_index);
+       void set_from_to(const Vector3 &from, const Vector3 &to);
+       Vector3 get_from();
+       Vector3 get_to();
+
+       // Evaluators
+       void set_evaluator(scalar_t (*evaluate)(const Vector3 &vec, scalar_t t));
+       void set_normal_evaluator(Vector3 (*get_normal)(const Vector3 &vec, scalar_t t));
+       
+       // last but not least 
+       void triangulate(TriMesh *mesh, scalar_t isolevel, scalar_t t, bool calc_normals);
+};
+
+#endif // ndef _SCALAR_FIELD_HEADER_
diff --git a/src/3dengfx/src/3dengfx/sdrman.cpp b/src/3dengfx/src/3dengfx/sdrman.cpp
new file mode 100644 (file)
index 0000000..8a52348
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+This file is part of the 3dengfx, 3d visualization system.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+3dengfx is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+3dengfx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with 3dengfx; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* Shader manager (shader manager)
+ * 
+ * author: John Tsiombikas 2005
+ */
+
+#include <string>
+#include <cstdio>
+#include <cstring>
+#include <cerrno>
+#include "3denginefx.hpp"
+#include "sdrman.hpp"
+#include "common/hashtable.hpp"
+#include "common/string_hash.hpp"
+#include "common/err_msg.h"
+#include "opengl.h"
+
+using std::string;
+using namespace glext;
+static HashTable<string, Shader> *shaders;
+
+static void delete_object(GLhandleARB obj) {
+       glDeleteObject(obj);
+}
+
+static void init_sdr_man() {
+       if(shaders) return;
+       shaders = new HashTable<string, Shader>;
+       shaders->set_hash_function(string_hash);
+       shaders->set_data_destructor(delete_object);
+}
+
+static inline bool check_shader_caps(int sdr_type, const char *name) {
+       if(!engfx_state::sys_caps.prog.shader_obj) {
+               error("Failed loading GLSL shader %s: system lacks GLSL capability", name);
+               return false;
+       }
+
+       if(sdr_type == PROG_VERTEX && !engfx_state::sys_caps.prog.glsl_vertex) {
+               error("Failed loading GLSL vertex shader %s: system lacks GLSL vertex shader capability", name);
+               return false;
+       }
+       
+       if(sdr_type == PROG_PIXEL && !engfx_state::sys_caps.prog.glsl_pixel) {
+               error("Failed loading GLSL pixel shader %s: system lacks GLSL pixel shader capability", name);
+               return false;
+       }
+
+       return true;
+}
+
+Shader add_shader_file(const char *fname, int sdr_type) {
+       FILE *fp = fopen(fname, "r");
+       if(!fp) {
+               error("Failed loading GLSL shader %s: %s\n", fname, strerror(errno));
+               return 0;
+       }
+
+       fseek(fp, 0, SEEK_END);
+       size_t src_size = ftell(fp);
+       fseek(fp, 0, SEEK_SET);
+
+       char *source = new char[src_size + 1];
+       src_size = fread(source, 1, src_size, fp);
+       source[src_size] = 0;
+       fclose(fp);
+
+       Shader sdr = add_shader_string(source, sdr_type, fname);
+       delete [] source;
+
+       return sdr;
+}
+
+Shader add_shader_string(const char *code, int sdr_type, const char *name) {
+       if(!shaders) init_sdr_man();
+       
+       if(!check_shader_caps(sdr_type, name)) return 0;
+
+       Shader sdr = glCreateShaderObject(sdr_type);
+       glShaderSource(sdr, 1, &code, 0);
+       glCompileShader(sdr);
+       
+       int success, info_len;
+       glGetObjectParameteriv(sdr, GL_OBJECT_COMPILE_STATUS_ARB, &success);
+       glGetObjectParameteriv(sdr, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_len);
+
+       char *info_str = 0;
+       
+       if(info_len) {
+               info_str = new char[info_len + 1];
+               glGetInfoLog(sdr, info_len, 0, info_str);
+       }
+       
+       if(success) {
+               if(info_len) {
+                       info("%s compiled: %s", name, info_str);
+                       delete [] info_str;
+               } else {
+                       info("%s compiled successfully", name);
+               }
+
+               shaders->insert(name ? name : tmpnam(0), sdr);
+       } else {
+               if(info_len) {
+                       error("%s compile failed: %s", name, info_str);
+                       delete [] info_str;
+               } else {
+                       error("%s compile failed", name);
+               }
+
+               glDeleteObject(sdr);
+               sdr = 0;
+       }
+
+       return sdr;
+}
+
+
+Shader get_shader(const char *name, int sdr_type) {
+       if(!shaders) init_sdr_man();
+       
+       Pair<string, Shader> *res = shaders->find(name);
+       if(res) return res->val;
+
+       return add_shader_file(name, sdr_type);
+}
+
+void destroy_shaders() {
+       info("Shutting down shader manager, destroying all shaders...");
+       delete shaders;
+       shaders = 0;
+}
diff --git a/src/3dengfx/src/3dengfx/sdrman.hpp b/src/3dengfx/src/3dengfx/sdrman.hpp
new file mode 100644 (file)
index 0000000..5682cc9
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+This file is part of the 3dengfx, 3d visualization system.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+3dengfx is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+3dengfx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with 3dengfx; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* Shader manager (shader manager)
+ * 
+ * author: John Tsiombikas 2005
+ */
+
+#ifndef _SDRMAN_HPP_
+#define _SDRMAN_HPP_
+
+#include "gfxprog.hpp"
+
+Shader add_shader_file(const char *fname, int sdr_type);
+Shader add_shader_string(const char *code, int sdr_type, const char *name = 0);
+Shader get_shader(const char *name, int sdr_type);
+void destroy_shaders();
+
+#endif // _SDRMAN_HPP_
diff --git a/src/3dengfx/src/3dengfx/sgi_glext.h b/src/3dengfx/src/3dengfx/sgi_glext.h
new file mode 100644 (file)
index 0000000..c0f636f
--- /dev/null
@@ -0,0 +1,6498 @@
+#ifndef SGI_GLEXT_H_
+#define SGI_GLEXT_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+** 
+** http://oss.sgi.com/projects/FreeB
+** 
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+** 
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2004 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+** 
+** Additional Notice Provisions: This software was created using the
+** OpenGL(R) version 1.2.1 Sample Implementation published by SGI, but has
+** not been independently verified as being compliant with the OpenGL(R)
+** version 1.2.1 Specification.
+*/
+
+#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)
+#define WIN32_LEAN_AND_MEAN 1
+#include <windows.h>
+#endif
+
+#ifndef APIENTRY
+#define APIENTRY
+#endif
+#ifndef APIENTRYP
+#define APIENTRYP APIENTRY *
+#endif
+#ifndef GLAPI
+#define GLAPI extern
+#endif
+
+/*************************************************************/
+
+/* Header file version number, required by OpenGL ABI for Linux */
+/* glext.h last updated 2005/06/20 */
+/* Current version at http://oss.sgi.com/projects/ogl-sample/registry/ */
+#ifdef GL_GLEXT_VERSION
+#undef GL_GLEXT_VERSION
+#define GL_GLEXT_VERSION 29
+#endif
+
+#ifndef GL_VERSION_1_2
+#define GL_UNSIGNED_BYTE_3_3_2            0x8032
+#define GL_UNSIGNED_SHORT_4_4_4_4         0x8033
+#define GL_UNSIGNED_SHORT_5_5_5_1         0x8034
+#define GL_UNSIGNED_INT_8_8_8_8           0x8035
+#define GL_UNSIGNED_INT_10_10_10_2        0x8036
+#define GL_RESCALE_NORMAL                 0x803A
+#define GL_TEXTURE_BINDING_3D             0x806A
+#define GL_PACK_SKIP_IMAGES               0x806B
+#define GL_PACK_IMAGE_HEIGHT              0x806C
+#define GL_UNPACK_SKIP_IMAGES             0x806D
+#define GL_UNPACK_IMAGE_HEIGHT            0x806E
+#define GL_TEXTURE_3D                     0x806F
+#define GL_PROXY_TEXTURE_3D               0x8070
+#define GL_TEXTURE_DEPTH                  0x8071
+#define GL_TEXTURE_WRAP_R                 0x8072
+#define GL_MAX_3D_TEXTURE_SIZE            0x8073
+#define GL_UNSIGNED_BYTE_2_3_3_REV        0x8362
+#define GL_UNSIGNED_SHORT_5_6_5           0x8363
+#define GL_UNSIGNED_SHORT_5_6_5_REV       0x8364
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV     0x8365
+#define GL_UNSIGNED_SHORT_1_5_5_5_REV     0x8366
+#define GL_UNSIGNED_INT_8_8_8_8_REV       0x8367
+#define GL_UNSIGNED_INT_2_10_10_10_REV    0x8368
+#define GL_BGR                            0x80E0
+#define GL_BGRA                           0x80E1
+#define GL_MAX_ELEMENTS_VERTICES          0x80E8
+#define GL_MAX_ELEMENTS_INDICES           0x80E9
+#define GL_CLAMP_TO_EDGE                  0x812F
+#define GL_TEXTURE_MIN_LOD                0x813A
+#define GL_TEXTURE_MAX_LOD                0x813B
+#define GL_TEXTURE_BASE_LEVEL             0x813C
+#define GL_TEXTURE_MAX_LEVEL              0x813D
+#define GL_LIGHT_MODEL_COLOR_CONTROL      0x81F8
+#define GL_SINGLE_COLOR                   0x81F9
+#define GL_SEPARATE_SPECULAR_COLOR        0x81FA
+#define GL_SMOOTH_POINT_SIZE_RANGE        0x0B12
+#define GL_SMOOTH_POINT_SIZE_GRANULARITY  0x0B13
+#define GL_SMOOTH_LINE_WIDTH_RANGE        0x0B22
+#define GL_SMOOTH_LINE_WIDTH_GRANULARITY  0x0B23
+#define GL_ALIASED_POINT_SIZE_RANGE       0x846D
+#define GL_ALIASED_LINE_WIDTH_RANGE       0x846E
+#endif
+
+#ifndef GL_ARB_imaging
+#define GL_CONSTANT_COLOR                 0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR       0x8002
+#define GL_CONSTANT_ALPHA                 0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA       0x8004
+#define GL_BLEND_COLOR                    0x8005
+#define GL_FUNC_ADD                       0x8006
+#define GL_MIN                            0x8007
+#define GL_MAX                            0x8008
+#define GL_BLEND_EQUATION                 0x8009
+#define GL_FUNC_SUBTRACT                  0x800A
+#define GL_FUNC_REVERSE_SUBTRACT          0x800B
+#define GL_CONVOLUTION_1D                 0x8010
+#define GL_CONVOLUTION_2D                 0x8011
+#define GL_SEPARABLE_2D                   0x8012
+#define GL_CONVOLUTION_BORDER_MODE        0x8013
+#define GL_CONVOLUTION_FILTER_SCALE       0x8014
+#define GL_CONVOLUTION_FILTER_BIAS        0x8015
+#define GL_REDUCE                         0x8016
+#define GL_CONVOLUTION_FORMAT             0x8017
+#define GL_CONVOLUTION_WIDTH              0x8018
+#define GL_CONVOLUTION_HEIGHT             0x8019
+#define GL_MAX_CONVOLUTION_WIDTH          0x801A
+#define GL_MAX_CONVOLUTION_HEIGHT         0x801B
+#define GL_POST_CONVOLUTION_RED_SCALE     0x801C
+#define GL_POST_CONVOLUTION_GREEN_SCALE   0x801D
+#define GL_POST_CONVOLUTION_BLUE_SCALE    0x801E
+#define GL_POST_CONVOLUTION_ALPHA_SCALE   0x801F
+#define GL_POST_CONVOLUTION_RED_BIAS      0x8020
+#define GL_POST_CONVOLUTION_GREEN_BIAS    0x8021
+#define GL_POST_CONVOLUTION_BLUE_BIAS     0x8022
+#define GL_POST_CONVOLUTION_ALPHA_BIAS    0x8023
+#define GL_HISTOGRAM                      0x8024
+#define GL_PROXY_HISTOGRAM                0x8025
+#define GL_HISTOGRAM_WIDTH                0x8026
+#define GL_HISTOGRAM_FORMAT               0x8027
+#define GL_HISTOGRAM_RED_SIZE             0x8028
+#define GL_HISTOGRAM_GREEN_SIZE           0x8029
+#define GL_HISTOGRAM_BLUE_SIZE            0x802A
+#define GL_HISTOGRAM_ALPHA_SIZE           0x802B
+#define GL_HISTOGRAM_LUMINANCE_SIZE       0x802C
+#define GL_HISTOGRAM_SINK                 0x802D
+#define GL_MINMAX                         0x802E
+#define GL_MINMAX_FORMAT                  0x802F
+#define GL_MINMAX_SINK                    0x8030
+#define GL_TABLE_TOO_LARGE                0x8031
+#define GL_COLOR_MATRIX                   0x80B1
+#define GL_COLOR_MATRIX_STACK_DEPTH       0x80B2
+#define GL_MAX_COLOR_MATRIX_STACK_DEPTH   0x80B3
+#define GL_POST_COLOR_MATRIX_RED_SCALE    0x80B4
+#define GL_POST_COLOR_MATRIX_GREEN_SCALE  0x80B5
+#define GL_POST_COLOR_MATRIX_BLUE_SCALE   0x80B6
+#define GL_POST_COLOR_MATRIX_ALPHA_SCALE  0x80B7
+#define GL_POST_COLOR_MATRIX_RED_BIAS     0x80B8
+#define GL_POST_COLOR_MATRIX_GREEN_BIAS   0x80B9
+#define GL_POST_COLOR_MATRIX_BLUE_BIAS    0x80BA
+#define GL_POST_COLOR_MATRIX_ALPHA_BIAS   0x80BB
+#define GL_COLOR_TABLE                    0x80D0
+#define GL_POST_CONVOLUTION_COLOR_TABLE   0x80D1
+#define GL_POST_COLOR_MATRIX_COLOR_TABLE  0x80D2
+#define GL_PROXY_COLOR_TABLE              0x80D3
+#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE 0x80D4
+#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE 0x80D5
+#define GL_COLOR_TABLE_SCALE              0x80D6
+#define GL_COLOR_TABLE_BIAS               0x80D7
+#define GL_COLOR_TABLE_FORMAT             0x80D8
+#define GL_COLOR_TABLE_WIDTH              0x80D9
+#define GL_COLOR_TABLE_RED_SIZE           0x80DA
+#define GL_COLOR_TABLE_GREEN_SIZE         0x80DB
+#define GL_COLOR_TABLE_BLUE_SIZE          0x80DC
+#define GL_COLOR_TABLE_ALPHA_SIZE         0x80DD
+#define GL_COLOR_TABLE_LUMINANCE_SIZE     0x80DE
+#define GL_COLOR_TABLE_INTENSITY_SIZE     0x80DF
+#define GL_CONSTANT_BORDER                0x8151
+#define GL_REPLICATE_BORDER               0x8153
+#define GL_CONVOLUTION_BORDER_COLOR       0x8154
+#endif
+
+#ifndef GL_VERSION_1_3
+#define GL_TEXTURE0                       0x84C0
+#define GL_TEXTURE1                       0x84C1
+#define GL_TEXTURE2                       0x84C2
+#define GL_TEXTURE3                       0x84C3
+#define GL_TEXTURE4                       0x84C4
+#define GL_TEXTURE5                       0x84C5
+#define GL_TEXTURE6                       0x84C6
+#define GL_TEXTURE7                       0x84C7
+#define GL_TEXTURE8                       0x84C8
+#define GL_TEXTURE9                       0x84C9
+#define GL_TEXTURE10                      0x84CA
+#define GL_TEXTURE11                      0x84CB
+#define GL_TEXTURE12                      0x84CC
+#define GL_TEXTURE13                      0x84CD
+#define GL_TEXTURE14                      0x84CE
+#define GL_TEXTURE15                      0x84CF
+#define GL_TEXTURE16                      0x84D0
+#define GL_TEXTURE17                      0x84D1
+#define GL_TEXTURE18                      0x84D2
+#define GL_TEXTURE19                      0x84D3
+#define GL_TEXTURE20                      0x84D4
+#define GL_TEXTURE21                      0x84D5
+#define GL_TEXTURE22                      0x84D6
+#define GL_TEXTURE23                      0x84D7
+#define GL_TEXTURE24                      0x84D8
+#define GL_TEXTURE25                      0x84D9
+#define GL_TEXTURE26                      0x84DA
+#define GL_TEXTURE27                      0x84DB
+#define GL_TEXTURE28                      0x84DC
+#define GL_TEXTURE29                      0x84DD
+#define GL_TEXTURE30                      0x84DE
+#define GL_TEXTURE31                      0x84DF
+#define GL_ACTIVE_TEXTURE                 0x84E0
+#define GL_CLIENT_ACTIVE_TEXTURE          0x84E1
+#define GL_MAX_TEXTURE_UNITS              0x84E2
+#define GL_TRANSPOSE_MODELVIEW_MATRIX     0x84E3
+#define GL_TRANSPOSE_PROJECTION_MATRIX    0x84E4
+#define GL_TRANSPOSE_TEXTURE_MATRIX       0x84E5
+#define GL_TRANSPOSE_COLOR_MATRIX         0x84E6
+#define GL_MULTISAMPLE                    0x809D
+#define GL_SAMPLE_ALPHA_TO_COVERAGE       0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE            0x809F
+#define GL_SAMPLE_COVERAGE                0x80A0
+#define GL_SAMPLE_BUFFERS                 0x80A8
+#define GL_SAMPLES                        0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE          0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT         0x80AB
+#define GL_MULTISAMPLE_BIT                0x20000000
+#define GL_NORMAL_MAP                     0x8511
+#define GL_REFLECTION_MAP                 0x8512
+#define GL_TEXTURE_CUBE_MAP               0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP       0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X    0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X    0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y    0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y    0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z    0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z    0x851A
+#define GL_PROXY_TEXTURE_CUBE_MAP         0x851B
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE      0x851C
+#define GL_COMPRESSED_ALPHA               0x84E9
+#define GL_COMPRESSED_LUMINANCE           0x84EA
+#define GL_COMPRESSED_LUMINANCE_ALPHA     0x84EB
+#define GL_COMPRESSED_INTENSITY           0x84EC
+#define GL_COMPRESSED_RGB                 0x84ED
+#define GL_COMPRESSED_RGBA                0x84EE
+#define GL_TEXTURE_COMPRESSION_HINT       0x84EF
+#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE  0x86A0
+#define GL_TEXTURE_COMPRESSED             0x86A1
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
+#define GL_COMPRESSED_TEXTURE_FORMATS     0x86A3
+#define GL_CLAMP_TO_BORDER                0x812D
+#define GL_COMBINE                        0x8570
+#define GL_COMBINE_RGB                    0x8571
+#define GL_COMBINE_ALPHA                  0x8572
+#define GL_SOURCE0_RGB                    0x8580
+#define GL_SOURCE1_RGB                    0x8581
+#define GL_SOURCE2_RGB                    0x8582
+#define GL_SOURCE0_ALPHA                  0x8588
+#define GL_SOURCE1_ALPHA                  0x8589
+#define GL_SOURCE2_ALPHA                  0x858A
+#define GL_OPERAND0_RGB                   0x8590
+#define GL_OPERAND1_RGB                   0x8591
+#define GL_OPERAND2_RGB                   0x8592
+#define GL_OPERAND0_ALPHA                 0x8598
+#define GL_OPERAND1_ALPHA                 0x8599
+#define GL_OPERAND2_ALPHA                 0x859A
+#define GL_RGB_SCALE                      0x8573
+#define GL_ADD_SIGNED                     0x8574
+#define GL_INTERPOLATE                    0x8575
+#define GL_SUBTRACT                       0x84E7
+#define GL_CONSTANT                       0x8576
+#define GL_PRIMARY_COLOR                  0x8577
+#define GL_PREVIOUS                       0x8578
+#define GL_DOT3_RGB                       0x86AE
+#define GL_DOT3_RGBA                      0x86AF
+#endif
+
+#ifndef GL_VERSION_1_4
+#define GL_BLEND_DST_RGB                  0x80C8
+#define GL_BLEND_SRC_RGB                  0x80C9
+#define GL_BLEND_DST_ALPHA                0x80CA
+#define GL_BLEND_SRC_ALPHA                0x80CB
+#define GL_POINT_SIZE_MIN                 0x8126
+#define GL_POINT_SIZE_MAX                 0x8127
+#define GL_POINT_FADE_THRESHOLD_SIZE      0x8128
+#define GL_POINT_DISTANCE_ATTENUATION     0x8129
+#define GL_GENERATE_MIPMAP                0x8191
+#define GL_GENERATE_MIPMAP_HINT           0x8192
+#define GL_DEPTH_COMPONENT16              0x81A5
+#define GL_DEPTH_COMPONENT24              0x81A6
+#define GL_DEPTH_COMPONENT32              0x81A7
+#define GL_MIRRORED_REPEAT                0x8370
+#define GL_FOG_COORDINATE_SOURCE          0x8450
+#define GL_FOG_COORDINATE                 0x8451
+#define GL_FRAGMENT_DEPTH                 0x8452
+#define GL_CURRENT_FOG_COORDINATE         0x8453
+#define GL_FOG_COORDINATE_ARRAY_TYPE      0x8454
+#define GL_FOG_COORDINATE_ARRAY_STRIDE    0x8455
+#define GL_FOG_COORDINATE_ARRAY_POINTER   0x8456
+#define GL_FOG_COORDINATE_ARRAY           0x8457
+#define GL_COLOR_SUM                      0x8458
+#define GL_CURRENT_SECONDARY_COLOR        0x8459
+#define GL_SECONDARY_COLOR_ARRAY_SIZE     0x845A
+#define GL_SECONDARY_COLOR_ARRAY_TYPE     0x845B
+#define GL_SECONDARY_COLOR_ARRAY_STRIDE   0x845C
+#define GL_SECONDARY_COLOR_ARRAY_POINTER  0x845D
+#define GL_SECONDARY_COLOR_ARRAY          0x845E
+#define GL_MAX_TEXTURE_LOD_BIAS           0x84FD
+#define GL_TEXTURE_FILTER_CONTROL         0x8500
+#define GL_TEXTURE_LOD_BIAS               0x8501
+#define GL_INCR_WRAP                      0x8507
+#define GL_DECR_WRAP                      0x8508
+#define GL_TEXTURE_DEPTH_SIZE             0x884A
+#define GL_DEPTH_TEXTURE_MODE             0x884B
+#define GL_TEXTURE_COMPARE_MODE           0x884C
+#define GL_TEXTURE_COMPARE_FUNC           0x884D
+#define GL_COMPARE_R_TO_TEXTURE           0x884E
+#endif
+
+#ifndef GL_VERSION_1_5
+#define GL_BUFFER_SIZE                    0x8764
+#define GL_BUFFER_USAGE                   0x8765
+#define GL_QUERY_COUNTER_BITS             0x8864
+#define GL_CURRENT_QUERY                  0x8865
+#define GL_QUERY_RESULT                   0x8866
+#define GL_QUERY_RESULT_AVAILABLE         0x8867
+#define GL_ARRAY_BUFFER                   0x8892
+#define GL_ELEMENT_ARRAY_BUFFER           0x8893
+#define GL_ARRAY_BUFFER_BINDING           0x8894
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING   0x8895
+#define GL_VERTEX_ARRAY_BUFFER_BINDING    0x8896
+#define GL_NORMAL_ARRAY_BUFFER_BINDING    0x8897
+#define GL_COLOR_ARRAY_BUFFER_BINDING     0x8898
+#define GL_INDEX_ARRAY_BUFFER_BINDING     0x8899
+#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING 0x889A
+#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING 0x889B
+#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING 0x889C
+#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING 0x889D
+#define GL_WEIGHT_ARRAY_BUFFER_BINDING    0x889E
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
+#define GL_READ_ONLY                      0x88B8
+#define GL_WRITE_ONLY                     0x88B9
+#define GL_READ_WRITE                     0x88BA
+#define GL_BUFFER_ACCESS                  0x88BB
+#define GL_BUFFER_MAPPED                  0x88BC
+#define GL_BUFFER_MAP_POINTER             0x88BD
+#define GL_STREAM_DRAW                    0x88E0
+#define GL_STREAM_READ                    0x88E1
+#define GL_STREAM_COPY                    0x88E2
+#define GL_STATIC_DRAW                    0x88E4
+#define GL_STATIC_READ                    0x88E5
+#define GL_STATIC_COPY                    0x88E6
+#define GL_DYNAMIC_DRAW                   0x88E8
+#define GL_DYNAMIC_READ                   0x88E9
+#define GL_DYNAMIC_COPY                   0x88EA
+#define GL_SAMPLES_PASSED                 0x8914
+#define GL_FOG_COORD_SRC                  GL_FOG_COORDINATE_SOURCE
+#define GL_FOG_COORD                      GL_FOG_COORDINATE
+#define GL_CURRENT_FOG_COORD              GL_CURRENT_FOG_COORDINATE
+#define GL_FOG_COORD_ARRAY_TYPE           GL_FOG_COORDINATE_ARRAY_TYPE
+#define GL_FOG_COORD_ARRAY_STRIDE         GL_FOG_COORDINATE_ARRAY_STRIDE
+#define GL_FOG_COORD_ARRAY_POINTER        GL_FOG_COORDINATE_ARRAY_POINTER
+#define GL_FOG_COORD_ARRAY                GL_FOG_COORDINATE_ARRAY
+#define GL_FOG_COORD_ARRAY_BUFFER_BINDING GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING
+#define GL_SRC0_RGB                       GL_SOURCE0_RGB
+#define GL_SRC1_RGB                       GL_SOURCE1_RGB
+#define GL_SRC2_RGB                       GL_SOURCE2_RGB
+#define GL_SRC0_ALPHA                     GL_SOURCE0_ALPHA
+#define GL_SRC1_ALPHA                     GL_SOURCE1_ALPHA
+#define GL_SRC2_ALPHA                     GL_SOURCE2_ALPHA
+#endif
+
+#ifndef GL_VERSION_2_0
+#define GL_BLEND_EQUATION_RGB             GL_BLEND_EQUATION
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED    0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE       0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE     0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE       0x8625
+#define GL_CURRENT_VERTEX_ATTRIB          0x8626
+#define GL_VERTEX_PROGRAM_POINT_SIZE      0x8642
+#define GL_VERTEX_PROGRAM_TWO_SIDE        0x8643
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER    0x8645
+#define GL_STENCIL_BACK_FUNC              0x8800
+#define GL_STENCIL_BACK_FAIL              0x8801
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL   0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS   0x8803
+#define GL_MAX_DRAW_BUFFERS               0x8824
+#define GL_DRAW_BUFFER0                   0x8825
+#define GL_DRAW_BUFFER1                   0x8826
+#define GL_DRAW_BUFFER2                   0x8827
+#define GL_DRAW_BUFFER3                   0x8828
+#define GL_DRAW_BUFFER4                   0x8829
+#define GL_DRAW_BUFFER5                   0x882A
+#define GL_DRAW_BUFFER6                   0x882B
+#define GL_DRAW_BUFFER7                   0x882C
+#define GL_DRAW_BUFFER8                   0x882D
+#define GL_DRAW_BUFFER9                   0x882E
+#define GL_DRAW_BUFFER10                  0x882F
+#define GL_DRAW_BUFFER11                  0x8830
+#define GL_DRAW_BUFFER12                  0x8831
+#define GL_DRAW_BUFFER13                  0x8832
+#define GL_DRAW_BUFFER14                  0x8833
+#define GL_DRAW_BUFFER15                  0x8834
+#define GL_BLEND_EQUATION_ALPHA           0x883D
+#define GL_POINT_SPRITE                   0x8861
+#define GL_COORD_REPLACE                  0x8862
+#define GL_MAX_VERTEX_ATTRIBS             0x8869
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
+#define GL_MAX_TEXTURE_COORDS             0x8871
+#define GL_MAX_TEXTURE_IMAGE_UNITS        0x8872
+#define GL_FRAGMENT_SHADER                0x8B30
+#define GL_VERTEX_SHADER                  0x8B31
+#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49
+#define GL_MAX_VERTEX_UNIFORM_COMPONENTS  0x8B4A
+#define GL_MAX_VARYING_FLOATS             0x8B4B
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
+#define GL_SHADER_TYPE                    0x8B4F
+#define GL_FLOAT_VEC2                     0x8B50
+#define GL_FLOAT_VEC3                     0x8B51
+#define GL_FLOAT_VEC4                     0x8B52
+#define GL_INT_VEC2                       0x8B53
+#define GL_INT_VEC3                       0x8B54
+#define GL_INT_VEC4                       0x8B55
+#define GL_BOOL                           0x8B56
+#define GL_BOOL_VEC2                      0x8B57
+#define GL_BOOL_VEC3                      0x8B58
+#define GL_BOOL_VEC4                      0x8B59
+#define GL_FLOAT_MAT2                     0x8B5A
+#define GL_FLOAT_MAT3                     0x8B5B
+#define GL_FLOAT_MAT4                     0x8B5C
+#define GL_SAMPLER_1D                     0x8B5D
+#define GL_SAMPLER_2D                     0x8B5E
+#define GL_SAMPLER_3D                     0x8B5F
+#define GL_SAMPLER_CUBE                   0x8B60
+#define GL_SAMPLER_1D_SHADOW              0x8B61
+#define GL_SAMPLER_2D_SHADOW              0x8B62
+#define GL_DELETE_STATUS                  0x8B80
+#define GL_COMPILE_STATUS                 0x8B81
+#define GL_LINK_STATUS                    0x8B82
+#define GL_VALIDATE_STATUS                0x8B83
+#define GL_INFO_LOG_LENGTH                0x8B84
+#define GL_ATTACHED_SHADERS               0x8B85
+#define GL_ACTIVE_UNIFORMS                0x8B86
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH      0x8B87
+#define GL_SHADER_SOURCE_LENGTH           0x8B88
+#define GL_ACTIVE_ATTRIBUTES              0x8B89
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH    0x8B8A
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B
+#define GL_SHADING_LANGUAGE_VERSION       0x8B8C
+#define GL_CURRENT_PROGRAM                0x8B8D
+#define GL_POINT_SPRITE_COORD_ORIGIN      0x8CA0
+#define GL_LOWER_LEFT                     0x8CA1
+#define GL_UPPER_LEFT                     0x8CA2
+#define GL_STENCIL_BACK_REF               0x8CA3
+#define GL_STENCIL_BACK_VALUE_MASK        0x8CA4
+#define GL_STENCIL_BACK_WRITEMASK         0x8CA5
+#endif
+
+#ifndef GL_ARB_multitexture
+#define GL_TEXTURE0_ARB                   0x84C0
+#define GL_TEXTURE1_ARB                   0x84C1
+#define GL_TEXTURE2_ARB                   0x84C2
+#define GL_TEXTURE3_ARB                   0x84C3
+#define GL_TEXTURE4_ARB                   0x84C4
+#define GL_TEXTURE5_ARB                   0x84C5
+#define GL_TEXTURE6_ARB                   0x84C6
+#define GL_TEXTURE7_ARB                   0x84C7
+#define GL_TEXTURE8_ARB                   0x84C8
+#define GL_TEXTURE9_ARB                   0x84C9
+#define GL_TEXTURE10_ARB                  0x84CA
+#define GL_TEXTURE11_ARB                  0x84CB
+#define GL_TEXTURE12_ARB                  0x84CC
+#define GL_TEXTURE13_ARB                  0x84CD
+#define GL_TEXTURE14_ARB                  0x84CE
+#define GL_TEXTURE15_ARB                  0x84CF
+#define GL_TEXTURE16_ARB                  0x84D0
+#define GL_TEXTURE17_ARB                  0x84D1
+#define GL_TEXTURE18_ARB                  0x84D2
+#define GL_TEXTURE19_ARB                  0x84D3
+#define GL_TEXTURE20_ARB                  0x84D4
+#define GL_TEXTURE21_ARB                  0x84D5
+#define GL_TEXTURE22_ARB                  0x84D6
+#define GL_TEXTURE23_ARB                  0x84D7
+#define GL_TEXTURE24_ARB                  0x84D8
+#define GL_TEXTURE25_ARB                  0x84D9
+#define GL_TEXTURE26_ARB                  0x84DA
+#define GL_TEXTURE27_ARB                  0x84DB
+#define GL_TEXTURE28_ARB                  0x84DC
+#define GL_TEXTURE29_ARB                  0x84DD
+#define GL_TEXTURE30_ARB                  0x84DE
+#define GL_TEXTURE31_ARB                  0x84DF
+#define GL_ACTIVE_TEXTURE_ARB             0x84E0
+#define GL_CLIENT_ACTIVE_TEXTURE_ARB      0x84E1
+#define GL_MAX_TEXTURE_UNITS_ARB          0x84E2
+#endif
+
+#ifndef GL_ARB_transpose_matrix
+#define GL_TRANSPOSE_MODELVIEW_MATRIX_ARB 0x84E3
+#define GL_TRANSPOSE_PROJECTION_MATRIX_ARB 0x84E4
+#define GL_TRANSPOSE_TEXTURE_MATRIX_ARB   0x84E5
+#define GL_TRANSPOSE_COLOR_MATRIX_ARB     0x84E6
+#endif
+
+#ifndef GL_ARB_multisample
+#define GL_MULTISAMPLE_ARB                0x809D
+#define GL_SAMPLE_ALPHA_TO_COVERAGE_ARB   0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE_ARB        0x809F
+#define GL_SAMPLE_COVERAGE_ARB            0x80A0
+#define GL_SAMPLE_BUFFERS_ARB             0x80A8
+#define GL_SAMPLES_ARB                    0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE_ARB      0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT_ARB     0x80AB
+#define GL_MULTISAMPLE_BIT_ARB            0x20000000
+#endif
+
+#ifndef GL_ARB_texture_env_add
+#endif
+
+#ifndef GL_ARB_texture_cube_map
+#define GL_NORMAL_MAP_ARB                 0x8511
+#define GL_REFLECTION_MAP_ARB             0x8512
+#define GL_TEXTURE_CUBE_MAP_ARB           0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP_ARB   0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x851A
+#define GL_PROXY_TEXTURE_CUBE_MAP_ARB     0x851B
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB  0x851C
+#endif
+
+#ifndef GL_ARB_texture_compression
+#define GL_COMPRESSED_ALPHA_ARB           0x84E9
+#define GL_COMPRESSED_LUMINANCE_ARB       0x84EA
+#define GL_COMPRESSED_LUMINANCE_ALPHA_ARB 0x84EB
+#define GL_COMPRESSED_INTENSITY_ARB       0x84EC
+#define GL_COMPRESSED_RGB_ARB             0x84ED
+#define GL_COMPRESSED_RGBA_ARB            0x84EE
+#define GL_TEXTURE_COMPRESSION_HINT_ARB   0x84EF
+#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB 0x86A0
+#define GL_TEXTURE_COMPRESSED_ARB         0x86A1
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A2
+#define GL_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A3
+#endif
+
+#ifndef GL_ARB_texture_border_clamp
+#define GL_CLAMP_TO_BORDER_ARB            0x812D
+#endif
+
+#ifndef GL_ARB_point_parameters
+#define GL_POINT_SIZE_MIN_ARB             0x8126
+#define GL_POINT_SIZE_MAX_ARB             0x8127
+#define GL_POINT_FADE_THRESHOLD_SIZE_ARB  0x8128
+#define GL_POINT_DISTANCE_ATTENUATION_ARB 0x8129
+#endif
+
+#ifndef GL_ARB_vertex_blend
+#define GL_MAX_VERTEX_UNITS_ARB           0x86A4
+#define GL_ACTIVE_VERTEX_UNITS_ARB        0x86A5
+#define GL_WEIGHT_SUM_UNITY_ARB           0x86A6
+#define GL_VERTEX_BLEND_ARB               0x86A7
+#define GL_CURRENT_WEIGHT_ARB             0x86A8
+#define GL_WEIGHT_ARRAY_TYPE_ARB          0x86A9
+#define GL_WEIGHT_ARRAY_STRIDE_ARB        0x86AA
+#define GL_WEIGHT_ARRAY_SIZE_ARB          0x86AB
+#define GL_WEIGHT_ARRAY_POINTER_ARB       0x86AC
+#define GL_WEIGHT_ARRAY_ARB               0x86AD
+#define GL_MODELVIEW0_ARB                 0x1700
+#define GL_MODELVIEW1_ARB                 0x850A
+#define GL_MODELVIEW2_ARB                 0x8722
+#define GL_MODELVIEW3_ARB                 0x8723
+#define GL_MODELVIEW4_ARB                 0x8724
+#define GL_MODELVIEW5_ARB                 0x8725
+#define GL_MODELVIEW6_ARB                 0x8726
+#define GL_MODELVIEW7_ARB                 0x8727
+#define GL_MODELVIEW8_ARB                 0x8728
+#define GL_MODELVIEW9_ARB                 0x8729
+#define GL_MODELVIEW10_ARB                0x872A
+#define GL_MODELVIEW11_ARB                0x872B
+#define GL_MODELVIEW12_ARB                0x872C
+#define GL_MODELVIEW13_ARB                0x872D
+#define GL_MODELVIEW14_ARB                0x872E
+#define GL_MODELVIEW15_ARB                0x872F
+#define GL_MODELVIEW16_ARB                0x8730
+#define GL_MODELVIEW17_ARB                0x8731
+#define GL_MODELVIEW18_ARB                0x8732
+#define GL_MODELVIEW19_ARB                0x8733
+#define GL_MODELVIEW20_ARB                0x8734
+#define GL_MODELVIEW21_ARB                0x8735
+#define GL_MODELVIEW22_ARB                0x8736
+#define GL_MODELVIEW23_ARB                0x8737
+#define GL_MODELVIEW24_ARB                0x8738
+#define GL_MODELVIEW25_ARB                0x8739
+#define GL_MODELVIEW26_ARB                0x873A
+#define GL_MODELVIEW27_ARB                0x873B
+#define GL_MODELVIEW28_ARB                0x873C
+#define GL_MODELVIEW29_ARB                0x873D
+#define GL_MODELVIEW30_ARB                0x873E
+#define GL_MODELVIEW31_ARB                0x873F
+#endif
+
+#ifndef GL_ARB_matrix_palette
+#define GL_MATRIX_PALETTE_ARB             0x8840
+#define GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB 0x8841
+#define GL_MAX_PALETTE_MATRICES_ARB       0x8842
+#define GL_CURRENT_PALETTE_MATRIX_ARB     0x8843
+#define GL_MATRIX_INDEX_ARRAY_ARB         0x8844
+#define GL_CURRENT_MATRIX_INDEX_ARB       0x8845
+#define GL_MATRIX_INDEX_ARRAY_SIZE_ARB    0x8846
+#define GL_MATRIX_INDEX_ARRAY_TYPE_ARB    0x8847
+#define GL_MATRIX_INDEX_ARRAY_STRIDE_ARB  0x8848
+#define GL_MATRIX_INDEX_ARRAY_POINTER_ARB 0x8849
+#endif
+
+#ifndef GL_ARB_texture_env_combine
+#define GL_COMBINE_ARB                    0x8570
+#define GL_COMBINE_RGB_ARB                0x8571
+#define GL_COMBINE_ALPHA_ARB              0x8572
+#define GL_SOURCE0_RGB_ARB                0x8580
+#define GL_SOURCE1_RGB_ARB                0x8581
+#define GL_SOURCE2_RGB_ARB                0x8582
+#define GL_SOURCE0_ALPHA_ARB              0x8588
+#define GL_SOURCE1_ALPHA_ARB              0x8589
+#define GL_SOURCE2_ALPHA_ARB              0x858A
+#define GL_OPERAND0_RGB_ARB               0x8590
+#define GL_OPERAND1_RGB_ARB               0x8591
+#define GL_OPERAND2_RGB_ARB               0x8592
+#define GL_OPERAND0_ALPHA_ARB             0x8598
+#define GL_OPERAND1_ALPHA_ARB             0x8599
+#define GL_OPERAND2_ALPHA_ARB             0x859A
+#define GL_RGB_SCALE_ARB                  0x8573
+#define GL_ADD_SIGNED_ARB                 0x8574
+#define GL_INTERPOLATE_ARB                0x8575
+#define GL_SUBTRACT_ARB                   0x84E7
+#define GL_CONSTANT_ARB                   0x8576
+#define GL_PRIMARY_COLOR_ARB              0x8577
+#define GL_PREVIOUS_ARB                   0x8578
+#endif
+
+#ifndef GL_ARB_texture_env_crossbar
+#endif
+
+#ifndef GL_ARB_texture_env_dot3
+#define GL_DOT3_RGB_ARB                   0x86AE
+#define GL_DOT3_RGBA_ARB                  0x86AF
+#endif
+
+#ifndef GL_ARB_texture_mirrored_repeat
+#define GL_MIRRORED_REPEAT_ARB            0x8370
+#endif
+
+#ifndef GL_ARB_depth_texture
+#define GL_DEPTH_COMPONENT16_ARB          0x81A5
+#define GL_DEPTH_COMPONENT24_ARB          0x81A6
+#define GL_DEPTH_COMPONENT32_ARB          0x81A7
+#define GL_TEXTURE_DEPTH_SIZE_ARB         0x884A
+#define GL_DEPTH_TEXTURE_MODE_ARB         0x884B
+#endif
+
+#ifndef GL_ARB_shadow
+#define GL_TEXTURE_COMPARE_MODE_ARB       0x884C
+#define GL_TEXTURE_COMPARE_FUNC_ARB       0x884D
+#define GL_COMPARE_R_TO_TEXTURE_ARB       0x884E
+#endif
+
+#ifndef GL_ARB_shadow_ambient
+#define GL_TEXTURE_COMPARE_FAIL_VALUE_ARB 0x80BF
+#endif
+
+#ifndef GL_ARB_window_pos
+#endif
+
+#ifndef GL_ARB_vertex_program
+#define GL_COLOR_SUM_ARB                  0x8458
+#define GL_VERTEX_PROGRAM_ARB             0x8620
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB 0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB   0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB 0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB   0x8625
+#define GL_CURRENT_VERTEX_ATTRIB_ARB      0x8626
+#define GL_PROGRAM_LENGTH_ARB             0x8627
+#define GL_PROGRAM_STRING_ARB             0x8628
+#define GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB 0x862E
+#define GL_MAX_PROGRAM_MATRICES_ARB       0x862F
+#define GL_CURRENT_MATRIX_STACK_DEPTH_ARB 0x8640
+#define GL_CURRENT_MATRIX_ARB             0x8641
+#define GL_VERTEX_PROGRAM_POINT_SIZE_ARB  0x8642
+#define GL_VERTEX_PROGRAM_TWO_SIDE_ARB    0x8643
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB 0x8645
+#define GL_PROGRAM_ERROR_POSITION_ARB     0x864B
+#define GL_PROGRAM_BINDING_ARB            0x8677
+#define GL_MAX_VERTEX_ATTRIBS_ARB         0x8869
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB 0x886A
+#define GL_PROGRAM_ERROR_STRING_ARB       0x8874
+#define GL_PROGRAM_FORMAT_ASCII_ARB       0x8875
+#define GL_PROGRAM_FORMAT_ARB             0x8876
+#define GL_PROGRAM_INSTRUCTIONS_ARB       0x88A0
+#define GL_MAX_PROGRAM_INSTRUCTIONS_ARB   0x88A1
+#define GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A2
+#define GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A3
+#define GL_PROGRAM_TEMPORARIES_ARB        0x88A4
+#define GL_MAX_PROGRAM_TEMPORARIES_ARB    0x88A5
+#define GL_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A6
+#define GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A7
+#define GL_PROGRAM_PARAMETERS_ARB         0x88A8
+#define GL_MAX_PROGRAM_PARAMETERS_ARB     0x88A9
+#define GL_PROGRAM_NATIVE_PARAMETERS_ARB  0x88AA
+#define GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AB
+#define GL_PROGRAM_ATTRIBS_ARB            0x88AC
+#define GL_MAX_PROGRAM_ATTRIBS_ARB        0x88AD
+#define GL_PROGRAM_NATIVE_ATTRIBS_ARB     0x88AE
+#define GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AF
+#define GL_PROGRAM_ADDRESS_REGISTERS_ARB  0x88B0
+#define GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B1
+#define GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B2
+#define GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B3
+#define GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB 0x88B4
+#define GL_MAX_PROGRAM_ENV_PARAMETERS_ARB 0x88B5
+#define GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB 0x88B6
+#define GL_TRANSPOSE_CURRENT_MATRIX_ARB   0x88B7
+#define GL_MATRIX0_ARB                    0x88C0
+#define GL_MATRIX1_ARB                    0x88C1
+#define GL_MATRIX2_ARB                    0x88C2
+#define GL_MATRIX3_ARB                    0x88C3
+#define GL_MATRIX4_ARB                    0x88C4
+#define GL_MATRIX5_ARB                    0x88C5
+#define GL_MATRIX6_ARB                    0x88C6
+#define GL_MATRIX7_ARB                    0x88C7
+#define GL_MATRIX8_ARB                    0x88C8
+#define GL_MATRIX9_ARB                    0x88C9
+#define GL_MATRIX10_ARB                   0x88CA
+#define GL_MATRIX11_ARB                   0x88CB
+#define GL_MATRIX12_ARB                   0x88CC
+#define GL_MATRIX13_ARB                   0x88CD
+#define GL_MATRIX14_ARB                   0x88CE
+#define GL_MATRIX15_ARB                   0x88CF
+#define GL_MATRIX16_ARB                   0x88D0
+#define GL_MATRIX17_ARB                   0x88D1
+#define GL_MATRIX18_ARB                   0x88D2
+#define GL_MATRIX19_ARB                   0x88D3
+#define GL_MATRIX20_ARB                   0x88D4
+#define GL_MATRIX21_ARB                   0x88D5
+#define GL_MATRIX22_ARB                   0x88D6
+#define GL_MATRIX23_ARB                   0x88D7
+#define GL_MATRIX24_ARB                   0x88D8
+#define GL_MATRIX25_ARB                   0x88D9
+#define GL_MATRIX26_ARB                   0x88DA
+#define GL_MATRIX27_ARB                   0x88DB
+#define GL_MATRIX28_ARB                   0x88DC
+#define GL_MATRIX29_ARB                   0x88DD
+#define GL_MATRIX30_ARB                   0x88DE
+#define GL_MATRIX31_ARB                   0x88DF
+#endif
+
+#ifndef GL_ARB_fragment_program
+#define GL_FRAGMENT_PROGRAM_ARB           0x8804
+#define GL_PROGRAM_ALU_INSTRUCTIONS_ARB   0x8805
+#define GL_PROGRAM_TEX_INSTRUCTIONS_ARB   0x8806
+#define GL_PROGRAM_TEX_INDIRECTIONS_ARB   0x8807
+#define GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x8808
+#define GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x8809
+#define GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x880A
+#define GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB 0x880B
+#define GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB 0x880C
+#define GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB 0x880D
+#define GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x880E
+#define GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x880F
+#define GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x8810
+#define GL_MAX_TEXTURE_COORDS_ARB         0x8871
+#define GL_MAX_TEXTURE_IMAGE_UNITS_ARB    0x8872
+#endif
+
+#ifndef GL_ARB_vertex_buffer_object
+#define GL_BUFFER_SIZE_ARB                0x8764
+#define GL_BUFFER_USAGE_ARB               0x8765
+#define GL_ARRAY_BUFFER_ARB               0x8892
+#define GL_ELEMENT_ARRAY_BUFFER_ARB       0x8893
+#define GL_ARRAY_BUFFER_BINDING_ARB       0x8894
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB 0x8895
+#define GL_VERTEX_ARRAY_BUFFER_BINDING_ARB 0x8896
+#define GL_NORMAL_ARRAY_BUFFER_BINDING_ARB 0x8897
+#define GL_COLOR_ARRAY_BUFFER_BINDING_ARB 0x8898
+#define GL_INDEX_ARRAY_BUFFER_BINDING_ARB 0x8899
+#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB 0x889A
+#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB 0x889B
+#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB 0x889C
+#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB 0x889D
+#define GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB 0x889E
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB 0x889F
+#define GL_READ_ONLY_ARB                  0x88B8
+#define GL_WRITE_ONLY_ARB                 0x88B9
+#define GL_READ_WRITE_ARB                 0x88BA
+#define GL_BUFFER_ACCESS_ARB              0x88BB
+#define GL_BUFFER_MAPPED_ARB              0x88BC
+#define GL_BUFFER_MAP_POINTER_ARB         0x88BD
+#define GL_STREAM_DRAW_ARB                0x88E0
+#define GL_STREAM_READ_ARB                0x88E1
+#define GL_STREAM_COPY_ARB                0x88E2
+#define GL_STATIC_DRAW_ARB                0x88E4
+#define GL_STATIC_READ_ARB                0x88E5
+#define GL_STATIC_COPY_ARB                0x88E6
+#define GL_DYNAMIC_DRAW_ARB               0x88E8
+#define GL_DYNAMIC_READ_ARB               0x88E9
+#define GL_DYNAMIC_COPY_ARB               0x88EA
+#endif
+
+#ifndef GL_ARB_occlusion_query
+#define GL_QUERY_COUNTER_BITS_ARB         0x8864
+#define GL_CURRENT_QUERY_ARB              0x8865
+#define GL_QUERY_RESULT_ARB               0x8866
+#define GL_QUERY_RESULT_AVAILABLE_ARB     0x8867
+#define GL_SAMPLES_PASSED_ARB             0x8914
+#endif
+
+#ifndef GL_ARB_shader_objects
+#define GL_PROGRAM_OBJECT_ARB             0x8B40
+#define GL_SHADER_OBJECT_ARB              0x8B48
+#define GL_OBJECT_TYPE_ARB                0x8B4E
+#define GL_OBJECT_SUBTYPE_ARB             0x8B4F
+#define GL_FLOAT_VEC2_ARB                 0x8B50
+#define GL_FLOAT_VEC3_ARB                 0x8B51
+#define GL_FLOAT_VEC4_ARB                 0x8B52
+#define GL_INT_VEC2_ARB                   0x8B53
+#define GL_INT_VEC3_ARB                   0x8B54
+#define GL_INT_VEC4_ARB                   0x8B55
+#define GL_BOOL_ARB                       0x8B56
+#define GL_BOOL_VEC2_ARB                  0x8B57
+#define GL_BOOL_VEC3_ARB                  0x8B58
+#define GL_BOOL_VEC4_ARB                  0x8B59
+#define GL_FLOAT_MAT2_ARB                 0x8B5A
+#define GL_FLOAT_MAT3_ARB                 0x8B5B
+#define GL_FLOAT_MAT4_ARB                 0x8B5C
+#define GL_SAMPLER_1D_ARB                 0x8B5D
+#define GL_SAMPLER_2D_ARB                 0x8B5E
+#define GL_SAMPLER_3D_ARB                 0x8B5F
+#define GL_SAMPLER_CUBE_ARB               0x8B60
+#define GL_SAMPLER_1D_SHADOW_ARB          0x8B61
+#define GL_SAMPLER_2D_SHADOW_ARB          0x8B62
+#define GL_SAMPLER_2D_RECT_ARB            0x8B63
+#define GL_SAMPLER_2D_RECT_SHADOW_ARB     0x8B64
+#define GL_OBJECT_DELETE_STATUS_ARB       0x8B80
+#define GL_OBJECT_COMPILE_STATUS_ARB      0x8B81
+#define GL_OBJECT_LINK_STATUS_ARB         0x8B82
+#define GL_OBJECT_VALIDATE_STATUS_ARB     0x8B83
+#define GL_OBJECT_INFO_LOG_LENGTH_ARB     0x8B84
+#define GL_OBJECT_ATTACHED_OBJECTS_ARB    0x8B85
+#define GL_OBJECT_ACTIVE_UNIFORMS_ARB     0x8B86
+#define GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB 0x8B87
+#define GL_OBJECT_SHADER_SOURCE_LENGTH_ARB 0x8B88
+#endif
+
+#ifndef GL_ARB_vertex_shader
+#define GL_VERTEX_SHADER_ARB              0x8B31
+#define GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB 0x8B4A
+#define GL_MAX_VARYING_FLOATS_ARB         0x8B4B
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB 0x8B4C
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB 0x8B4D
+#define GL_OBJECT_ACTIVE_ATTRIBUTES_ARB   0x8B89
+#define GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB 0x8B8A
+#endif
+
+#ifndef GL_ARB_fragment_shader
+#define GL_FRAGMENT_SHADER_ARB            0x8B30
+#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB 0x8B49
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB 0x8B8B
+#endif
+
+#ifndef GL_ARB_shading_language_100
+#define GL_SHADING_LANGUAGE_VERSION_ARB   0x8B8C
+#endif
+
+#ifndef GL_ARB_texture_non_power_of_two
+#endif
+
+#ifndef GL_ARB_point_sprite
+#define GL_POINT_SPRITE_ARB               0x8861
+#define GL_COORD_REPLACE_ARB              0x8862
+#endif
+
+#ifndef GL_ARB_fragment_program_shadow
+#endif
+
+#ifndef GL_ARB_draw_buffers
+#define GL_MAX_DRAW_BUFFERS_ARB           0x8824
+#define GL_DRAW_BUFFER0_ARB               0x8825
+#define GL_DRAW_BUFFER1_ARB               0x8826
+#define GL_DRAW_BUFFER2_ARB               0x8827
+#define GL_DRAW_BUFFER3_ARB               0x8828
+#define GL_DRAW_BUFFER4_ARB               0x8829
+#define GL_DRAW_BUFFER5_ARB               0x882A
+#define GL_DRAW_BUFFER6_ARB               0x882B
+#define GL_DRAW_BUFFER7_ARB               0x882C
+#define GL_DRAW_BUFFER8_ARB               0x882D
+#define GL_DRAW_BUFFER9_ARB               0x882E
+#define GL_DRAW_BUFFER10_ARB              0x882F
+#define GL_DRAW_BUFFER11_ARB              0x8830
+#define GL_DRAW_BUFFER12_ARB              0x8831
+#define GL_DRAW_BUFFER13_ARB              0x8832
+#define GL_DRAW_BUFFER14_ARB              0x8833
+#define GL_DRAW_BUFFER15_ARB              0x8834
+#endif
+
+#ifndef GL_ARB_texture_rectangle
+#define GL_TEXTURE_RECTANGLE_ARB          0x84F5
+#define GL_TEXTURE_BINDING_RECTANGLE_ARB  0x84F6
+#define GL_PROXY_TEXTURE_RECTANGLE_ARB    0x84F7
+#define GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB 0x84F8
+#endif
+
+#ifndef GL_ARB_color_buffer_float
+#define GL_RGBA_FLOAT_MODE_ARB            0x8820
+#define GL_CLAMP_VERTEX_COLOR_ARB         0x891A
+#define GL_CLAMP_FRAGMENT_COLOR_ARB       0x891B
+#define GL_CLAMP_READ_COLOR_ARB           0x891C
+#define GL_FIXED_ONLY_ARB                 0x891D
+#endif
+
+#ifndef GL_ARB_half_float_pixel
+#define GL_HALF_FLOAT_ARB                 0x140B
+#endif
+
+#ifndef GL_ARB_texture_float
+#define GL_TEXTURE_RED_TYPE_ARB           0x8C10
+#define GL_TEXTURE_GREEN_TYPE_ARB         0x8C11
+#define GL_TEXTURE_BLUE_TYPE_ARB          0x8C12
+#define GL_TEXTURE_ALPHA_TYPE_ARB         0x8C13
+#define GL_TEXTURE_LUMINANCE_TYPE_ARB     0x8C14
+#define GL_TEXTURE_INTENSITY_TYPE_ARB     0x8C15
+#define GL_TEXTURE_DEPTH_TYPE_ARB         0x8C16
+#define GL_UNSIGNED_NORMALIZED_ARB        0x8C17
+#define GL_RGBA32F_ARB                    0x8814
+#define GL_RGB32F_ARB                     0x8815
+#define GL_ALPHA32F_ARB                   0x8816
+#define GL_INTENSITY32F_ARB               0x8817
+#define GL_LUMINANCE32F_ARB               0x8818
+#define GL_LUMINANCE_ALPHA32F_ARB         0x8819
+#define GL_RGBA16F_ARB                    0x881A
+#define GL_RGB16F_ARB                     0x881B
+#define GL_ALPHA16F_ARB                   0x881C
+#define GL_INTENSITY16F_ARB               0x881D
+#define GL_LUMINANCE16F_ARB               0x881E
+#define GL_LUMINANCE_ALPHA16F_ARB         0x881F
+#endif
+
+#ifndef GL_ARB_pixel_buffer_object
+#define GL_PIXEL_PACK_BUFFER_ARB          0x88EB
+#define GL_PIXEL_UNPACK_BUFFER_ARB        0x88EC
+#define GL_PIXEL_PACK_BUFFER_BINDING_ARB  0x88ED
+#define GL_PIXEL_UNPACK_BUFFER_BINDING_ARB 0x88EF
+#endif
+
+#ifndef GL_EXT_abgr
+#define GL_ABGR_EXT                       0x8000
+#endif
+
+#ifndef GL_EXT_blend_color
+#define GL_CONSTANT_COLOR_EXT             0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR_EXT   0x8002
+#define GL_CONSTANT_ALPHA_EXT             0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA_EXT   0x8004
+#define GL_BLEND_COLOR_EXT                0x8005
+#endif
+
+#ifndef GL_EXT_polygon_offset
+#define GL_POLYGON_OFFSET_EXT             0x8037
+#define GL_POLYGON_OFFSET_FACTOR_EXT      0x8038
+#define GL_POLYGON_OFFSET_BIAS_EXT        0x8039
+#endif
+
+#ifndef GL_EXT_texture
+#define GL_ALPHA4_EXT                     0x803B
+#define GL_ALPHA8_EXT                     0x803C
+#define GL_ALPHA12_EXT                    0x803D
+#define GL_ALPHA16_EXT                    0x803E
+#define GL_LUMINANCE4_EXT                 0x803F
+#define GL_LUMINANCE8_EXT                 0x8040
+#define GL_LUMINANCE12_EXT                0x8041
+#define GL_LUMINANCE16_EXT                0x8042
+#define GL_LUMINANCE4_ALPHA4_EXT          0x8043
+#define GL_LUMINANCE6_ALPHA2_EXT          0x8044
+#define GL_LUMINANCE8_ALPHA8_EXT          0x8045
+#define GL_LUMINANCE12_ALPHA4_EXT         0x8046
+#define GL_LUMINANCE12_ALPHA12_EXT        0x8047
+#define GL_LUMINANCE16_ALPHA16_EXT        0x8048
+#define GL_INTENSITY_EXT                  0x8049
+#define GL_INTENSITY4_EXT                 0x804A
+#define GL_INTENSITY8_EXT                 0x804B
+#define GL_INTENSITY12_EXT                0x804C
+#define GL_INTENSITY16_EXT                0x804D
+#define GL_RGB2_EXT                       0x804E
+#define GL_RGB4_EXT                       0x804F
+#define GL_RGB5_EXT                       0x8050
+#define GL_RGB8_EXT                       0x8051
+#define GL_RGB10_EXT                      0x8052
+#define GL_RGB12_EXT                      0x8053
+#define GL_RGB16_EXT                      0x8054
+#define GL_RGBA2_EXT                      0x8055
+#define GL_RGBA4_EXT                      0x8056
+#define GL_RGB5_A1_EXT                    0x8057
+#define GL_RGBA8_EXT                      0x8058
+#define GL_RGB10_A2_EXT                   0x8059
+#define GL_RGBA12_EXT                     0x805A
+#define GL_RGBA16_EXT                     0x805B
+#define GL_TEXTURE_RED_SIZE_EXT           0x805C
+#define GL_TEXTURE_GREEN_SIZE_EXT         0x805D
+#define GL_TEXTURE_BLUE_SIZE_EXT          0x805E
+#define GL_TEXTURE_ALPHA_SIZE_EXT         0x805F
+#define GL_TEXTURE_LUMINANCE_SIZE_EXT     0x8060
+#define GL_TEXTURE_INTENSITY_SIZE_EXT     0x8061
+#define GL_REPLACE_EXT                    0x8062
+#define GL_PROXY_TEXTURE_1D_EXT           0x8063
+#define GL_PROXY_TEXTURE_2D_EXT           0x8064
+#define GL_TEXTURE_TOO_LARGE_EXT          0x8065
+#endif
+
+#ifndef GL_EXT_texture3D
+#define GL_PACK_SKIP_IMAGES_EXT           0x806B
+#define GL_PACK_IMAGE_HEIGHT_EXT          0x806C
+#define GL_UNPACK_SKIP_IMAGES_EXT         0x806D
+#define GL_UNPACK_IMAGE_HEIGHT_EXT        0x806E
+#define GL_TEXTURE_3D_EXT                 0x806F
+#define GL_PROXY_TEXTURE_3D_EXT           0x8070
+#define GL_TEXTURE_DEPTH_EXT              0x8071
+#define GL_TEXTURE_WRAP_R_EXT             0x8072
+#define GL_MAX_3D_TEXTURE_SIZE_EXT        0x8073
+#endif
+
+#ifndef GL_SGIS_texture_filter4
+#define GL_FILTER4_SGIS                   0x8146
+#define GL_TEXTURE_FILTER4_SIZE_SGIS      0x8147
+#endif
+
+#ifndef GL_EXT_subtexture
+#endif
+
+#ifndef GL_EXT_copy_texture
+#endif
+
+#ifndef GL_EXT_histogram
+#define GL_HISTOGRAM_EXT                  0x8024
+#define GL_PROXY_HISTOGRAM_EXT            0x8025
+#define GL_HISTOGRAM_WIDTH_EXT            0x8026
+#define GL_HISTOGRAM_FORMAT_EXT           0x8027
+#define GL_HISTOGRAM_RED_SIZE_EXT         0x8028
+#define GL_HISTOGRAM_GREEN_SIZE_EXT       0x8029
+#define GL_HISTOGRAM_BLUE_SIZE_EXT        0x802A
+#define GL_HISTOGRAM_ALPHA_SIZE_EXT       0x802B
+#define GL_HISTOGRAM_LUMINANCE_SIZE_EXT   0x802C
+#define GL_HISTOGRAM_SINK_EXT             0x802D
+#define GL_MINMAX_EXT                     0x802E
+#define GL_MINMAX_FORMAT_EXT              0x802F
+#define GL_MINMAX_SINK_EXT                0x8030
+#define GL_TABLE_TOO_LARGE_EXT            0x8031
+#endif
+
+#ifndef GL_EXT_convolution
+#define GL_CONVOLUTION_1D_EXT             0x8010
+#define GL_CONVOLUTION_2D_EXT             0x8011
+#define GL_SEPARABLE_2D_EXT               0x8012
+#define GL_CONVOLUTION_BORDER_MODE_EXT    0x8013
+#define GL_CONVOLUTION_FILTER_SCALE_EXT   0x8014
+#define GL_CONVOLUTION_FILTER_BIAS_EXT    0x8015
+#define GL_REDUCE_EXT                     0x8016
+#define GL_CONVOLUTION_FORMAT_EXT         0x8017
+#define GL_CONVOLUTION_WIDTH_EXT          0x8018
+#define GL_CONVOLUTION_HEIGHT_EXT         0x8019
+#define GL_MAX_CONVOLUTION_WIDTH_EXT      0x801A
+#define GL_MAX_CONVOLUTION_HEIGHT_EXT     0x801B
+#define GL_POST_CONVOLUTION_RED_SCALE_EXT 0x801C
+#define GL_POST_CONVOLUTION_GREEN_SCALE_EXT 0x801D
+#define GL_POST_CONVOLUTION_BLUE_SCALE_EXT 0x801E
+#define GL_POST_CONVOLUTION_ALPHA_SCALE_EXT 0x801F
+#define GL_POST_CONVOLUTION_RED_BIAS_EXT  0x8020
+#define GL_POST_CONVOLUTION_GREEN_BIAS_EXT 0x8021
+#define GL_POST_CONVOLUTION_BLUE_BIAS_EXT 0x8022
+#define GL_POST_CONVOLUTION_ALPHA_BIAS_EXT 0x8023
+#endif
+
+#ifndef GL_SGI_color_matrix
+#define GL_COLOR_MATRIX_SGI               0x80B1
+#define GL_COLOR_MATRIX_STACK_DEPTH_SGI   0x80B2
+#define GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B3
+#define GL_POST_COLOR_MATRIX_RED_SCALE_SGI 0x80B4
+#define GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI 0x80B5
+#define GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI 0x80B6
+#define GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI 0x80B7
+#define GL_POST_COLOR_MATRIX_RED_BIAS_SGI 0x80B8
+#define GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI 0x80B9
+#define GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI 0x80BA
+#define GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI 0x80BB
+#endif
+
+#ifndef GL_SGI_color_table
+#define GL_COLOR_TABLE_SGI                0x80D0
+#define GL_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D1
+#define GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D2
+#define GL_PROXY_COLOR_TABLE_SGI          0x80D3
+#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D4
+#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D5
+#define GL_COLOR_TABLE_SCALE_SGI          0x80D6
+#define GL_COLOR_TABLE_BIAS_SGI           0x80D7
+#define GL_COLOR_TABLE_FORMAT_SGI         0x80D8
+#define GL_COLOR_TABLE_WIDTH_SGI          0x80D9
+#define GL_COLOR_TABLE_RED_SIZE_SGI       0x80DA
+#define GL_COLOR_TABLE_GREEN_SIZE_SGI     0x80DB
+#define GL_COLOR_TABLE_BLUE_SIZE_SGI      0x80DC
+#define GL_COLOR_TABLE_ALPHA_SIZE_SGI     0x80DD
+#define GL_COLOR_TABLE_LUMINANCE_SIZE_SGI 0x80DE
+#define GL_COLOR_TABLE_INTENSITY_SIZE_SGI 0x80DF
+#endif
+
+#ifndef GL_SGIS_pixel_texture
+#define GL_PIXEL_TEXTURE_SGIS             0x8353
+#define GL_PIXEL_FRAGMENT_RGB_SOURCE_SGIS 0x8354
+#define GL_PIXEL_FRAGMENT_ALPHA_SOURCE_SGIS 0x8355
+#define GL_PIXEL_GROUP_COLOR_SGIS         0x8356
+#endif
+
+#ifndef GL_SGIX_pixel_texture
+#define GL_PIXEL_TEX_GEN_SGIX             0x8139
+#define GL_PIXEL_TEX_GEN_MODE_SGIX        0x832B
+#endif
+
+#ifndef GL_SGIS_texture4D
+#define GL_PACK_SKIP_VOLUMES_SGIS         0x8130
+#define GL_PACK_IMAGE_DEPTH_SGIS          0x8131
+#define GL_UNPACK_SKIP_VOLUMES_SGIS       0x8132
+#define GL_UNPACK_IMAGE_DEPTH_SGIS        0x8133
+#define GL_TEXTURE_4D_SGIS                0x8134
+#define GL_PROXY_TEXTURE_4D_SGIS          0x8135
+#define GL_TEXTURE_4DSIZE_SGIS            0x8136
+#define GL_TEXTURE_WRAP_Q_SGIS            0x8137
+#define GL_MAX_4D_TEXTURE_SIZE_SGIS       0x8138
+#define GL_TEXTURE_4D_BINDING_SGIS        0x814F
+#endif
+
+#ifndef GL_SGI_texture_color_table
+#define GL_TEXTURE_COLOR_TABLE_SGI        0x80BC
+#define GL_PROXY_TEXTURE_COLOR_TABLE_SGI  0x80BD
+#endif
+
+#ifndef GL_EXT_cmyka
+#define GL_CMYK_EXT                       0x800C
+#define GL_CMYKA_EXT                      0x800D
+#define GL_PACK_CMYK_HINT_EXT             0x800E
+#define GL_UNPACK_CMYK_HINT_EXT           0x800F
+#endif
+
+#ifndef GL_EXT_texture_object
+#define GL_TEXTURE_PRIORITY_EXT           0x8066
+#define GL_TEXTURE_RESIDENT_EXT           0x8067
+#define GL_TEXTURE_1D_BINDING_EXT         0x8068
+#define GL_TEXTURE_2D_BINDING_EXT         0x8069
+#define GL_TEXTURE_3D_BINDING_EXT         0x806A
+#endif
+
+#ifndef GL_SGIS_detail_texture
+#define GL_DETAIL_TEXTURE_2D_SGIS         0x8095
+#define GL_DETAIL_TEXTURE_2D_BINDING_SGIS 0x8096
+#define GL_LINEAR_DETAIL_SGIS             0x8097
+#define GL_LINEAR_DETAIL_ALPHA_SGIS       0x8098
+#define GL_LINEAR_DETAIL_COLOR_SGIS       0x8099
+#define GL_DETAIL_TEXTURE_LEVEL_SGIS      0x809A
+#define GL_DETAIL_TEXTURE_MODE_SGIS       0x809B
+#define GL_DETAIL_TEXTURE_FUNC_POINTS_SGIS 0x809C
+#endif
+
+#ifndef GL_SGIS_sharpen_texture
+#define GL_LINEAR_SHARPEN_SGIS            0x80AD
+#define GL_LINEAR_SHARPEN_ALPHA_SGIS      0x80AE
+#define GL_LINEAR_SHARPEN_COLOR_SGIS      0x80AF
+#define GL_SHARPEN_TEXTURE_FUNC_POINTS_SGIS 0x80B0
+#endif
+
+#ifndef GL_EXT_packed_pixels
+#define GL_UNSIGNED_BYTE_3_3_2_EXT        0x8032
+#define GL_UNSIGNED_SHORT_4_4_4_4_EXT     0x8033
+#define GL_UNSIGNED_SHORT_5_5_5_1_EXT     0x8034
+#define GL_UNSIGNED_INT_8_8_8_8_EXT       0x8035
+#define GL_UNSIGNED_INT_10_10_10_2_EXT    0x8036
+#endif
+
+#ifndef GL_SGIS_texture_lod
+#define GL_TEXTURE_MIN_LOD_SGIS           0x813A
+#define GL_TEXTURE_MAX_LOD_SGIS           0x813B
+#define GL_TEXTURE_BASE_LEVEL_SGIS        0x813C
+#define GL_TEXTURE_MAX_LEVEL_SGIS         0x813D
+#endif
+
+#ifndef GL_SGIS_multisample
+#define GL_MULTISAMPLE_SGIS               0x809D
+#define GL_SAMPLE_ALPHA_TO_MASK_SGIS      0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE_SGIS       0x809F
+#define GL_SAMPLE_MASK_SGIS               0x80A0
+#define GL_1PASS_SGIS                     0x80A1
+#define GL_2PASS_0_SGIS                   0x80A2
+#define GL_2PASS_1_SGIS                   0x80A3
+#define GL_4PASS_0_SGIS                   0x80A4
+#define GL_4PASS_1_SGIS                   0x80A5
+#define GL_4PASS_2_SGIS                   0x80A6
+#define GL_4PASS_3_SGIS                   0x80A7
+#define GL_SAMPLE_BUFFERS_SGIS            0x80A8
+#define GL_SAMPLES_SGIS                   0x80A9
+#define GL_SAMPLE_MASK_VALUE_SGIS         0x80AA
+#define GL_SAMPLE_MASK_INVERT_SGIS        0x80AB
+#define GL_SAMPLE_PATTERN_SGIS            0x80AC
+#endif
+
+#ifndef GL_EXT_rescale_normal
+#define GL_RESCALE_NORMAL_EXT             0x803A
+#endif
+
+#ifndef GL_EXT_vertex_array
+#define GL_VERTEX_ARRAY_EXT               0x8074
+#define GL_NORMAL_ARRAY_EXT               0x8075
+#define GL_COLOR_ARRAY_EXT                0x8076
+#define GL_INDEX_ARRAY_EXT                0x8077
+#define GL_TEXTURE_COORD_ARRAY_EXT        0x8078
+#define GL_EDGE_FLAG_ARRAY_EXT            0x8079
+#define GL_VERTEX_ARRAY_SIZE_EXT          0x807A
+#define GL_VERTEX_ARRAY_TYPE_EXT          0x807B
+#define GL_VERTEX_ARRAY_STRIDE_EXT        0x807C
+#define GL_VERTEX_ARRAY_COUNT_EXT         0x807D
+#define GL_NORMAL_ARRAY_TYPE_EXT          0x807E
+#define GL_NORMAL_ARRAY_STRIDE_EXT        0x807F
+#define GL_NORMAL_ARRAY_COUNT_EXT         0x8080
+#define GL_COLOR_ARRAY_SIZE_EXT           0x8081
+#define GL_COLOR_ARRAY_TYPE_EXT           0x8082
+#define GL_COLOR_ARRAY_STRIDE_EXT         0x8083
+#define GL_COLOR_ARRAY_COUNT_EXT          0x8084
+#define GL_INDEX_ARRAY_TYPE_EXT           0x8085
+#define GL_INDEX_ARRAY_STRIDE_EXT         0x8086
+#define GL_INDEX_ARRAY_COUNT_EXT          0x8087
+#define GL_TEXTURE_COORD_ARRAY_SIZE_EXT   0x8088
+#define GL_TEXTURE_COORD_ARRAY_TYPE_EXT   0x8089
+#define GL_TEXTURE_COORD_ARRAY_STRIDE_EXT 0x808A
+#define GL_TEXTURE_COORD_ARRAY_COUNT_EXT  0x808B
+#define GL_EDGE_FLAG_ARRAY_STRIDE_EXT     0x808C
+#define GL_EDGE_FLAG_ARRAY_COUNT_EXT      0x808D
+#define GL_VERTEX_ARRAY_POINTER_EXT       0x808E
+#define GL_NORMAL_ARRAY_POINTER_EXT       0x808F
+#define GL_COLOR_ARRAY_POINTER_EXT        0x8090
+#define GL_INDEX_ARRAY_POINTER_EXT        0x8091
+#define GL_TEXTURE_COORD_ARRAY_POINTER_EXT 0x8092
+#define GL_EDGE_FLAG_ARRAY_POINTER_EXT    0x8093
+#endif
+
+#ifndef GL_EXT_misc_attribute
+#endif
+
+#ifndef GL_SGIS_generate_mipmap
+#define GL_GENERATE_MIPMAP_SGIS           0x8191
+#define GL_GENERATE_MIPMAP_HINT_SGIS      0x8192
+#endif
+
+#ifndef GL_SGIX_clipmap
+#define GL_LINEAR_CLIPMAP_LINEAR_SGIX     0x8170
+#define GL_TEXTURE_CLIPMAP_CENTER_SGIX    0x8171
+#define GL_TEXTURE_CLIPMAP_FRAME_SGIX     0x8172
+#define GL_TEXTURE_CLIPMAP_OFFSET_SGIX    0x8173
+#define GL_TEXTURE_CLIPMAP_VIRTUAL_DEPTH_SGIX 0x8174
+#define GL_TEXTURE_CLIPMAP_LOD_OFFSET_SGIX 0x8175
+#define GL_TEXTURE_CLIPMAP_DEPTH_SGIX     0x8176
+#define GL_MAX_CLIPMAP_DEPTH_SGIX         0x8177
+#define GL_MAX_CLIPMAP_VIRTUAL_DEPTH_SGIX 0x8178
+#define GL_NEAREST_CLIPMAP_NEAREST_SGIX   0x844D
+#define GL_NEAREST_CLIPMAP_LINEAR_SGIX    0x844E
+#define GL_LINEAR_CLIPMAP_NEAREST_SGIX    0x844F
+#endif
+
+#ifndef GL_SGIX_shadow
+#define GL_TEXTURE_COMPARE_SGIX           0x819A
+#define GL_TEXTURE_COMPARE_OPERATOR_SGIX  0x819B
+#define GL_TEXTURE_LEQUAL_R_SGIX          0x819C
+#define GL_TEXTURE_GEQUAL_R_SGIX          0x819D
+#endif
+
+#ifndef GL_SGIS_texture_edge_clamp
+#define GL_CLAMP_TO_EDGE_SGIS             0x812F
+#endif
+
+#ifndef GL_SGIS_texture_border_clamp
+#define GL_CLAMP_TO_BORDER_SGIS           0x812D
+#endif
+
+#ifndef GL_EXT_blend_minmax
+#define GL_FUNC_ADD_EXT                   0x8006
+#define GL_MIN_EXT                        0x8007
+#define GL_MAX_EXT                        0x8008
+#define GL_BLEND_EQUATION_EXT             0x8009
+#endif
+
+#ifndef GL_EXT_blend_subtract
+#define GL_FUNC_SUBTRACT_EXT              0x800A
+#define GL_FUNC_REVERSE_SUBTRACT_EXT      0x800B
+#endif
+
+#ifndef GL_EXT_blend_logic_op
+#endif
+
+#ifndef GL_SGIX_interlace
+#define GL_INTERLACE_SGIX                 0x8094
+#endif
+
+#ifndef GL_SGIX_pixel_tiles
+#define GL_PIXEL_TILE_BEST_ALIGNMENT_SGIX 0x813E
+#define GL_PIXEL_TILE_CACHE_INCREMENT_SGIX 0x813F
+#define GL_PIXEL_TILE_WIDTH_SGIX          0x8140
+#define GL_PIXEL_TILE_HEIGHT_SGIX         0x8141
+#define GL_PIXEL_TILE_GRID_WIDTH_SGIX     0x8142
+#define GL_PIXEL_TILE_GRID_HEIGHT_SGIX    0x8143
+#define GL_PIXEL_TILE_GRID_DEPTH_SGIX     0x8144
+#define GL_PIXEL_TILE_CACHE_SIZE_SGIX     0x8145
+#endif
+
+#ifndef GL_SGIS_texture_select
+#define GL_DUAL_ALPHA4_SGIS               0x8110
+#define GL_DUAL_ALPHA8_SGIS               0x8111
+#define GL_DUAL_ALPHA12_SGIS              0x8112
+#define GL_DUAL_ALPHA16_SGIS              0x8113
+#define GL_DUAL_LUMINANCE4_SGIS           0x8114
+#define GL_DUAL_LUMINANCE8_SGIS           0x8115
+#define GL_DUAL_LUMINANCE12_SGIS          0x8116
+#define GL_DUAL_LUMINANCE16_SGIS          0x8117
+#define GL_DUAL_INTENSITY4_SGIS           0x8118
+#define GL_DUAL_INTENSITY8_SGIS           0x8119
+#define GL_DUAL_INTENSITY12_SGIS          0x811A
+#define GL_DUAL_INTENSITY16_SGIS          0x811B
+#define GL_DUAL_LUMINANCE_ALPHA4_SGIS     0x811C
+#define GL_DUAL_LUMINANCE_ALPHA8_SGIS     0x811D
+#define GL_QUAD_ALPHA4_SGIS               0x811E
+#define GL_QUAD_ALPHA8_SGIS               0x811F
+#define GL_QUAD_LUMINANCE4_SGIS           0x8120
+#define GL_QUAD_LUMINANCE8_SGIS           0x8121
+#define GL_QUAD_INTENSITY4_SGIS           0x8122
+#define GL_QUAD_INTENSITY8_SGIS           0x8123
+#define GL_DUAL_TEXTURE_SELECT_SGIS       0x8124
+#define GL_QUAD_TEXTURE_SELECT_SGIS       0x8125
+#endif
+
+#ifndef GL_SGIX_sprite
+#define GL_SPRITE_SGIX                    0x8148
+#define GL_SPRITE_MODE_SGIX               0x8149
+#define GL_SPRITE_AXIS_SGIX               0x814A
+#define GL_SPRITE_TRANSLATION_SGIX        0x814B
+#define GL_SPRITE_AXIAL_SGIX              0x814C
+#define GL_SPRITE_OBJECT_ALIGNED_SGIX     0x814D
+#define GL_SPRITE_EYE_ALIGNED_SGIX        0x814E
+#endif
+
+#ifndef GL_SGIX_texture_multi_buffer
+#define GL_TEXTURE_MULTI_BUFFER_HINT_SGIX 0x812E
+#endif
+
+#ifndef GL_EXT_point_parameters
+#define GL_POINT_SIZE_MIN_EXT             0x8126
+#define GL_POINT_SIZE_MAX_EXT             0x8127
+#define GL_POINT_FADE_THRESHOLD_SIZE_EXT  0x8128
+#define GL_DISTANCE_ATTENUATION_EXT       0x8129
+#endif
+
+#ifndef GL_SGIS_point_parameters
+#define GL_POINT_SIZE_MIN_SGIS            0x8126
+#define GL_POINT_SIZE_MAX_SGIS            0x8127
+#define GL_POINT_FADE_THRESHOLD_SIZE_SGIS 0x8128
+#define GL_DISTANCE_ATTENUATION_SGIS      0x8129
+#endif
+
+#ifndef GL_SGIX_instruments
+#define GL_INSTRUMENT_BUFFER_POINTER_SGIX 0x8180
+#define GL_INSTRUMENT_MEASUREMENTS_SGIX   0x8181
+#endif
+
+#ifndef GL_SGIX_texture_scale_bias
+#define GL_POST_TEXTURE_FILTER_BIAS_SGIX  0x8179
+#define GL_POST_TEXTURE_FILTER_SCALE_SGIX 0x817A
+#define GL_POST_TEXTURE_FILTER_BIAS_RANGE_SGIX 0x817B
+#define GL_POST_TEXTURE_FILTER_SCALE_RANGE_SGIX 0x817C
+#endif
+
+#ifndef GL_SGIX_framezoom
+#define GL_FRAMEZOOM_SGIX                 0x818B
+#define GL_FRAMEZOOM_FACTOR_SGIX          0x818C
+#define GL_MAX_FRAMEZOOM_FACTOR_SGIX      0x818D
+#endif
+
+#ifndef GL_SGIX_tag_sample_buffer
+#endif
+
+#ifndef GL_FfdMaskSGIX
+#define GL_TEXTURE_DEFORMATION_BIT_SGIX   0x00000001
+#define GL_GEOMETRY_DEFORMATION_BIT_SGIX  0x00000002
+#endif
+
+#ifndef GL_SGIX_polynomial_ffd
+#define GL_GEOMETRY_DEFORMATION_SGIX      0x8194
+#define GL_TEXTURE_DEFORMATION_SGIX       0x8195
+#define GL_DEFORMATIONS_MASK_SGIX         0x8196
+#define GL_MAX_DEFORMATION_ORDER_SGIX     0x8197
+#endif
+
+#ifndef GL_SGIX_reference_plane
+#define GL_REFERENCE_PLANE_SGIX           0x817D
+#define GL_REFERENCE_PLANE_EQUATION_SGIX  0x817E
+#endif
+
+#ifndef GL_SGIX_flush_raster
+#endif
+
+#ifndef GL_SGIX_depth_texture
+#define GL_DEPTH_COMPONENT16_SGIX         0x81A5
+#define GL_DEPTH_COMPONENT24_SGIX         0x81A6
+#define GL_DEPTH_COMPONENT32_SGIX         0x81A7
+#endif
+
+#ifndef GL_SGIS_fog_function
+#define GL_FOG_FUNC_SGIS                  0x812A
+#define GL_FOG_FUNC_POINTS_SGIS           0x812B
+#define GL_MAX_FOG_FUNC_POINTS_SGIS       0x812C
+#endif
+
+#ifndef GL_SGIX_fog_offset
+#define GL_FOG_OFFSET_SGIX                0x8198
+#define GL_FOG_OFFSET_VALUE_SGIX          0x8199
+#endif
+
+#ifndef GL_HP_image_transform
+#define GL_IMAGE_SCALE_X_HP               0x8155
+#define GL_IMAGE_SCALE_Y_HP               0x8156
+#define GL_IMAGE_TRANSLATE_X_HP           0x8157
+#define GL_IMAGE_TRANSLATE_Y_HP           0x8158
+#define GL_IMAGE_ROTATE_ANGLE_HP          0x8159
+#define GL_IMAGE_ROTATE_ORIGIN_X_HP       0x815A
+#define GL_IMAGE_ROTATE_ORIGIN_Y_HP       0x815B
+#define GL_IMAGE_MAG_FILTER_HP            0x815C
+#define GL_IMAGE_MIN_FILTER_HP            0x815D
+#define GL_IMAGE_CUBIC_WEIGHT_HP          0x815E
+#define GL_CUBIC_HP                       0x815F
+#define GL_AVERAGE_HP                     0x8160
+#define GL_IMAGE_TRANSFORM_2D_HP          0x8161
+#define GL_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP 0x8162
+#define GL_PROXY_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP 0x8163
+#endif
+
+#ifndef GL_HP_convolution_border_modes
+#define GL_IGNORE_BORDER_HP               0x8150
+#define GL_CONSTANT_BORDER_HP             0x8151
+#define GL_REPLICATE_BORDER_HP            0x8153
+#define GL_CONVOLUTION_BORDER_COLOR_HP    0x8154
+#endif
+
+#ifndef GL_INGR_palette_buffer
+#endif
+
+#ifndef GL_SGIX_texture_add_env
+#define GL_TEXTURE_ENV_BIAS_SGIX          0x80BE
+#endif
+
+#ifndef GL_EXT_color_subtable
+#endif
+
+#ifndef GL_PGI_vertex_hints
+#define GL_VERTEX_DATA_HINT_PGI           0x1A22A
+#define GL_VERTEX_CONSISTENT_HINT_PGI     0x1A22B
+#define GL_MATERIAL_SIDE_HINT_PGI         0x1A22C
+#define GL_MAX_VERTEX_HINT_PGI            0x1A22D
+#define GL_COLOR3_BIT_PGI                 0x00010000
+#define GL_COLOR4_BIT_PGI                 0x00020000
+#define GL_EDGEFLAG_BIT_PGI               0x00040000
+#define GL_INDEX_BIT_PGI                  0x00080000
+#define GL_MAT_AMBIENT_BIT_PGI            0x00100000
+#define GL_MAT_AMBIENT_AND_DIFFUSE_BIT_PGI 0x00200000
+#define GL_MAT_DIFFUSE_BIT_PGI            0x00400000
+#define GL_MAT_EMISSION_BIT_PGI           0x00800000
+#define GL_MAT_COLOR_INDEXES_BIT_PGI      0x01000000
+#define GL_MAT_SHININESS_BIT_PGI          0x02000000
+#define GL_MAT_SPECULAR_BIT_PGI           0x04000000
+#define GL_NORMAL_BIT_PGI                 0x08000000
+#define GL_TEXCOORD1_BIT_PGI              0x10000000
+#define GL_TEXCOORD2_BIT_PGI              0x20000000
+#define GL_TEXCOORD3_BIT_PGI              0x40000000
+#define GL_TEXCOORD4_BIT_PGI              0x80000000
+#define GL_VERTEX23_BIT_PGI               0x00000004
+#define GL_VERTEX4_BIT_PGI                0x00000008
+#endif
+
+#ifndef GL_PGI_misc_hints
+#define GL_PREFER_DOUBLEBUFFER_HINT_PGI   0x1A1F8
+#define GL_CONSERVE_MEMORY_HINT_PGI       0x1A1FD
+#define GL_RECLAIM_MEMORY_HINT_PGI        0x1A1FE
+#define GL_NATIVE_GRAPHICS_HANDLE_PGI     0x1A202
+#define GL_NATIVE_GRAPHICS_BEGIN_HINT_PGI 0x1A203
+#define GL_NATIVE_GRAPHICS_END_HINT_PGI   0x1A204
+#define GL_ALWAYS_FAST_HINT_PGI           0x1A20C
+#define GL_ALWAYS_SOFT_HINT_PGI           0x1A20D
+#define GL_ALLOW_DRAW_OBJ_HINT_PGI        0x1A20E
+#define GL_ALLOW_DRAW_WIN_HINT_PGI        0x1A20F
+#define GL_ALLOW_DRAW_FRG_HINT_PGI        0x1A210
+#define GL_ALLOW_DRAW_MEM_HINT_PGI        0x1A211
+#define GL_STRICT_DEPTHFUNC_HINT_PGI      0x1A216
+#define GL_STRICT_LIGHTING_HINT_PGI       0x1A217
+#define GL_STRICT_SCISSOR_HINT_PGI        0x1A218
+#define GL_FULL_STIPPLE_HINT_PGI          0x1A219
+#define GL_CLIP_NEAR_HINT_PGI             0x1A220
+#define GL_CLIP_FAR_HINT_PGI              0x1A221
+#define GL_WIDE_LINE_HINT_PGI             0x1A222
+#define GL_BACK_NORMALS_HINT_PGI          0x1A223
+#endif
+
+#ifndef GL_EXT_paletted_texture
+#define GL_COLOR_INDEX1_EXT               0x80E2
+#define GL_COLOR_INDEX2_EXT               0x80E3
+#define GL_COLOR_INDEX4_EXT               0x80E4
+#define GL_COLOR_INDEX8_EXT               0x80E5
+#define GL_COLOR_INDEX12_EXT              0x80E6
+#define GL_COLOR_INDEX16_EXT              0x80E7
+#define GL_TEXTURE_INDEX_SIZE_EXT         0x80ED
+#endif
+
+#ifndef GL_EXT_clip_volume_hint
+#define GL_CLIP_VOLUME_CLIPPING_HINT_EXT  0x80F0
+#endif
+
+#ifndef GL_SGIX_list_priority
+#define GL_LIST_PRIORITY_SGIX             0x8182
+#endif
+
+#ifndef GL_SGIX_ir_instrument1
+#define GL_IR_INSTRUMENT1_SGIX            0x817F
+#endif
+
+#ifndef GL_SGIX_calligraphic_fragment
+#define GL_CALLIGRAPHIC_FRAGMENT_SGIX     0x8183
+#endif
+
+#ifndef GL_SGIX_texture_lod_bias
+#define GL_TEXTURE_LOD_BIAS_S_SGIX        0x818E
+#define GL_TEXTURE_LOD_BIAS_T_SGIX        0x818F
+#define GL_TEXTURE_LOD_BIAS_R_SGIX        0x8190
+#endif
+
+#ifndef GL_SGIX_shadow_ambient
+#define GL_SHADOW_AMBIENT_SGIX            0x80BF
+#endif
+
+#ifndef GL_EXT_index_texture
+#endif
+
+#ifndef GL_EXT_index_material
+#define GL_INDEX_MATERIAL_EXT             0x81B8
+#define GL_INDEX_MATERIAL_PARAMETER_EXT   0x81B9
+#define GL_INDEX_MATERIAL_FACE_EXT        0x81BA
+#endif
+
+#ifndef GL_EXT_index_func
+#define GL_INDEX_TEST_EXT                 0x81B5
+#define GL_INDEX_TEST_FUNC_EXT            0x81B6
+#define GL_INDEX_TEST_REF_EXT             0x81B7
+#endif
+
+#ifndef GL_EXT_index_array_formats
+#define GL_IUI_V2F_EXT                    0x81AD
+#define GL_IUI_V3F_EXT                    0x81AE
+#define GL_IUI_N3F_V2F_EXT                0x81AF
+#define GL_IUI_N3F_V3F_EXT                0x81B0
+#define GL_T2F_IUI_V2F_EXT                0x81B1
+#define GL_T2F_IUI_V3F_EXT                0x81B2
+#define GL_T2F_IUI_N3F_V2F_EXT            0x81B3
+#define GL_T2F_IUI_N3F_V3F_EXT            0x81B4
+#endif
+
+#ifndef GL_EXT_compiled_vertex_array
+#define GL_ARRAY_ELEMENT_LOCK_FIRST_EXT   0x81A8
+#define GL_ARRAY_ELEMENT_LOCK_COUNT_EXT   0x81A9
+#endif
+
+#ifndef GL_EXT_cull_vertex
+#define GL_CULL_VERTEX_EXT                0x81AA
+#define GL_CULL_VERTEX_EYE_POSITION_EXT   0x81AB
+#define GL_CULL_VERTEX_OBJECT_POSITION_EXT 0x81AC
+#endif
+
+#ifndef GL_SGIX_ycrcb
+#define GL_YCRCB_422_SGIX                 0x81BB
+#define GL_YCRCB_444_SGIX                 0x81BC
+#endif
+
+#ifndef GL_SGIX_fragment_lighting
+#define GL_FRAGMENT_LIGHTING_SGIX         0x8400
+#define GL_FRAGMENT_COLOR_MATERIAL_SGIX   0x8401
+#define GL_FRAGMENT_COLOR_MATERIAL_FACE_SGIX 0x8402
+#define GL_FRAGMENT_COLOR_MATERIAL_PARAMETER_SGIX 0x8403
+#define GL_MAX_FRAGMENT_LIGHTS_SGIX       0x8404
+#define GL_MAX_ACTIVE_LIGHTS_SGIX         0x8405
+#define GL_CURRENT_RASTER_NORMAL_SGIX     0x8406
+#define GL_LIGHT_ENV_MODE_SGIX            0x8407
+#define GL_FRAGMENT_LIGHT_MODEL_LOCAL_VIEWER_SGIX 0x8408
+#define GL_FRAGMENT_LIGHT_MODEL_TWO_SIDE_SGIX 0x8409
+#define GL_FRAGMENT_LIGHT_MODEL_AMBIENT_SGIX 0x840A
+#define GL_FRAGMENT_LIGHT_MODEL_NORMAL_INTERPOLATION_SGIX 0x840B
+#define GL_FRAGMENT_LIGHT0_SGIX           0x840C
+#define GL_FRAGMENT_LIGHT1_SGIX           0x840D
+#define GL_FRAGMENT_LIGHT2_SGIX           0x840E
+#define GL_FRAGMENT_LIGHT3_SGIX           0x840F
+#define GL_FRAGMENT_LIGHT4_SGIX           0x8410
+#define GL_FRAGMENT_LIGHT5_SGIX           0x8411
+#define GL_FRAGMENT_LIGHT6_SGIX           0x8412
+#define GL_FRAGMENT_LIGHT7_SGIX           0x8413
+#endif
+
+#ifndef GL_IBM_rasterpos_clip
+#define GL_RASTER_POSITION_UNCLIPPED_IBM  0x19262
+#endif
+
+#ifndef GL_HP_texture_lighting
+#define GL_TEXTURE_LIGHTING_MODE_HP       0x8167
+#define GL_TEXTURE_POST_SPECULAR_HP       0x8168
+#define GL_TEXTURE_PRE_SPECULAR_HP        0x8169
+#endif
+
+#ifndef GL_EXT_draw_range_elements
+#define GL_MAX_ELEMENTS_VERTICES_EXT      0x80E8
+#define GL_MAX_ELEMENTS_INDICES_EXT       0x80E9
+#endif
+
+#ifndef GL_WIN_phong_shading
+#define GL_PHONG_WIN                      0x80EA
+#define GL_PHONG_HINT_WIN                 0x80EB
+#endif
+
+#ifndef GL_WIN_specular_fog
+#define GL_FOG_SPECULAR_TEXTURE_WIN       0x80EC
+#endif
+
+#ifndef GL_EXT_light_texture
+#define GL_FRAGMENT_MATERIAL_EXT          0x8349
+#define GL_FRAGMENT_NORMAL_EXT            0x834A
+#define GL_FRAGMENT_COLOR_EXT             0x834C
+#define GL_ATTENUATION_EXT                0x834D
+#define GL_SHADOW_ATTENUATION_EXT         0x834E
+#define GL_TEXTURE_APPLICATION_MODE_EXT   0x834F
+#define GL_TEXTURE_LIGHT_EXT              0x8350
+#define GL_TEXTURE_MATERIAL_FACE_EXT      0x8351
+#define GL_TEXTURE_MATERIAL_PARAMETER_EXT 0x8352
+/* reuse GL_FRAGMENT_DEPTH_EXT */
+#endif
+
+#ifndef GL_SGIX_blend_alpha_minmax
+#define GL_ALPHA_MIN_SGIX                 0x8320
+#define GL_ALPHA_MAX_SGIX                 0x8321
+#endif
+
+#ifndef GL_SGIX_impact_pixel_texture
+#define GL_PIXEL_TEX_GEN_Q_CEILING_SGIX   0x8184
+#define GL_PIXEL_TEX_GEN_Q_ROUND_SGIX     0x8185
+#define GL_PIXEL_TEX_GEN_Q_FLOOR_SGIX     0x8186
+#define GL_PIXEL_TEX_GEN_ALPHA_REPLACE_SGIX 0x8187
+#define GL_PIXEL_TEX_GEN_ALPHA_NO_REPLACE_SGIX 0x8188
+#define GL_PIXEL_TEX_GEN_ALPHA_LS_SGIX    0x8189
+#define GL_PIXEL_TEX_GEN_ALPHA_MS_SGIX    0x818A
+#endif
+
+#ifndef GL_EXT_bgra
+#define GL_BGR_EXT                        0x80E0
+#define GL_BGRA_EXT                       0x80E1
+#endif
+
+#ifndef GL_SGIX_async
+#define GL_ASYNC_MARKER_SGIX              0x8329
+#endif
+
+#ifndef GL_SGIX_async_pixel
+#define GL_ASYNC_TEX_IMAGE_SGIX           0x835C
+#define GL_ASYNC_DRAW_PIXELS_SGIX         0x835D
+#define GL_ASYNC_READ_PIXELS_SGIX         0x835E
+#define GL_MAX_ASYNC_TEX_IMAGE_SGIX       0x835F
+#define GL_MAX_ASYNC_DRAW_PIXELS_SGIX     0x8360
+#define GL_MAX_ASYNC_READ_PIXELS_SGIX     0x8361
+#endif
+
+#ifndef GL_SGIX_async_histogram
+#define GL_ASYNC_HISTOGRAM_SGIX           0x832C
+#define GL_MAX_ASYNC_HISTOGRAM_SGIX       0x832D
+#endif
+
+#ifndef GL_INTEL_texture_scissor
+#endif
+
+#ifndef GL_INTEL_parallel_arrays
+#define GL_PARALLEL_ARRAYS_INTEL          0x83F4
+#define GL_VERTEX_ARRAY_PARALLEL_POINTERS_INTEL 0x83F5
+#define GL_NORMAL_ARRAY_PARALLEL_POINTERS_INTEL 0x83F6
+#define GL_COLOR_ARRAY_PARALLEL_POINTERS_INTEL 0x83F7
+#define GL_TEXTURE_COORD_ARRAY_PARALLEL_POINTERS_INTEL 0x83F8
+#endif
+
+#ifndef GL_HP_occlusion_test
+#define GL_OCCLUSION_TEST_HP              0x8165
+#define GL_OCCLUSION_TEST_RESULT_HP       0x8166
+#endif
+
+#ifndef GL_EXT_pixel_transform
+#define GL_PIXEL_TRANSFORM_2D_EXT         0x8330
+#define GL_PIXEL_MAG_FILTER_EXT           0x8331
+#define GL_PIXEL_MIN_FILTER_EXT           0x8332
+#define GL_PIXEL_CUBIC_WEIGHT_EXT         0x8333
+#define GL_CUBIC_EXT                      0x8334
+#define GL_AVERAGE_EXT                    0x8335
+#define GL_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8336
+#define GL_MAX_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8337
+#define GL_PIXEL_TRANSFORM_2D_MATRIX_EXT  0x8338
+#endif
+
+#ifndef GL_EXT_pixel_transform_color_table
+#endif
+
+#ifndef GL_EXT_shared_texture_palette
+#define GL_SHARED_TEXTURE_PALETTE_EXT     0x81FB
+#endif
+
+#ifndef GL_EXT_separate_specular_color
+#define GL_LIGHT_MODEL_COLOR_CONTROL_EXT  0x81F8
+#define GL_SINGLE_COLOR_EXT               0x81F9
+#define GL_SEPARATE_SPECULAR_COLOR_EXT    0x81FA
+#endif
+
+#ifndef GL_EXT_secondary_color
+#define GL_COLOR_SUM_EXT                  0x8458
+#define GL_CURRENT_SECONDARY_COLOR_EXT    0x8459
+#define GL_SECONDARY_COLOR_ARRAY_SIZE_EXT 0x845A
+#define GL_SECONDARY_COLOR_ARRAY_TYPE_EXT 0x845B
+#define GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT 0x845C
+#define GL_SECONDARY_COLOR_ARRAY_POINTER_EXT 0x845D
+#define GL_SECONDARY_COLOR_ARRAY_EXT      0x845E
+#endif
+
+#ifndef GL_EXT_texture_perturb_normal
+#define GL_PERTURB_EXT                    0x85AE
+#define GL_TEXTURE_NORMAL_EXT             0x85AF
+#endif
+
+#ifndef GL_EXT_multi_draw_arrays
+#endif
+
+#ifndef GL_EXT_fog_coord
+#define GL_FOG_COORDINATE_SOURCE_EXT      0x8450
+#define GL_FOG_COORDINATE_EXT             0x8451
+#define GL_FRAGMENT_DEPTH_EXT             0x8452
+#define GL_CURRENT_FOG_COORDINATE_EXT     0x8453
+#define GL_FOG_COORDINATE_ARRAY_TYPE_EXT  0x8454
+#define GL_FOG_COORDINATE_ARRAY_STRIDE_EXT 0x8455
+#define GL_FOG_COORDINATE_ARRAY_POINTER_EXT 0x8456
+#define GL_FOG_COORDINATE_ARRAY_EXT       0x8457
+#endif
+
+#ifndef GL_REND_screen_coordinates
+#define GL_SCREEN_COORDINATES_REND        0x8490
+#define GL_INVERTED_SCREEN_W_REND         0x8491
+#endif
+
+#ifndef GL_EXT_coordinate_frame
+#define GL_TANGENT_ARRAY_EXT              0x8439
+#define GL_BINORMAL_ARRAY_EXT             0x843A
+#define GL_CURRENT_TANGENT_EXT            0x843B
+#define GL_CURRENT_BINORMAL_EXT           0x843C
+#define GL_TANGENT_ARRAY_TYPE_EXT         0x843E
+#define GL_TANGENT_ARRAY_STRIDE_EXT       0x843F
+#define GL_BINORMAL_ARRAY_TYPE_EXT        0x8440
+#define GL_BINORMAL_ARRAY_STRIDE_EXT      0x8441
+#define GL_TANGENT_ARRAY_POINTER_EXT      0x8442
+#define GL_BINORMAL_ARRAY_POINTER_EXT     0x8443
+#define GL_MAP1_TANGENT_EXT               0x8444
+#define GL_MAP2_TANGENT_EXT               0x8445
+#define GL_MAP1_BINORMAL_EXT              0x8446
+#define GL_MAP2_BINORMAL_EXT              0x8447
+#endif
+
+#ifndef GL_EXT_texture_env_combine
+#define GL_COMBINE_EXT                    0x8570
+#define GL_COMBINE_RGB_EXT                0x8571
+#define GL_COMBINE_ALPHA_EXT              0x8572
+#define GL_RGB_SCALE_EXT                  0x8573
+#define GL_ADD_SIGNED_EXT                 0x8574
+#define GL_INTERPOLATE_EXT                0x8575
+#define GL_CONSTANT_EXT                   0x8576
+#define GL_PRIMARY_COLOR_EXT              0x8577
+#define GL_PREVIOUS_EXT                   0x8578
+#define GL_SOURCE0_RGB_EXT                0x8580
+#define GL_SOURCE1_RGB_EXT                0x8581
+#define GL_SOURCE2_RGB_EXT                0x8582
+#define GL_SOURCE0_ALPHA_EXT              0x8588
+#define GL_SOURCE1_ALPHA_EXT              0x8589
+#define GL_SOURCE2_ALPHA_EXT              0x858A
+#define GL_OPERAND0_RGB_EXT               0x8590
+#define GL_OPERAND1_RGB_EXT               0x8591
+#define GL_OPERAND2_RGB_EXT               0x8592
+#define GL_OPERAND0_ALPHA_EXT             0x8598
+#define GL_OPERAND1_ALPHA_EXT             0x8599
+#define GL_OPERAND2_ALPHA_EXT             0x859A
+#endif
+
+#ifndef GL_APPLE_specular_vector
+#define GL_LIGHT_MODEL_SPECULAR_VECTOR_APPLE 0x85B0
+#endif
+
+#ifndef GL_APPLE_transform_hint
+#define GL_TRANSFORM_HINT_APPLE           0x85B1
+#endif
+
+#ifndef GL_SGIX_fog_scale
+#define GL_FOG_SCALE_SGIX                 0x81FC
+#define GL_FOG_SCALE_VALUE_SGIX           0x81FD
+#endif
+
+#ifndef GL_SUNX_constant_data
+#define GL_UNPACK_CONSTANT_DATA_SUNX      0x81D5
+#define GL_TEXTURE_CONSTANT_DATA_SUNX     0x81D6
+#endif
+
+#ifndef GL_SUN_global_alpha
+#define GL_GLOBAL_ALPHA_SUN               0x81D9
+#define GL_GLOBAL_ALPHA_FACTOR_SUN        0x81DA
+#endif
+
+#ifndef GL_SUN_triangle_list
+#define GL_RESTART_SUN                    0x0001
+#define GL_REPLACE_MIDDLE_SUN             0x0002
+#define GL_REPLACE_OLDEST_SUN             0x0003
+#define GL_TRIANGLE_LIST_SUN              0x81D7
+#define GL_REPLACEMENT_CODE_SUN           0x81D8
+#define GL_REPLACEMENT_CODE_ARRAY_SUN     0x85C0
+#define GL_REPLACEMENT_CODE_ARRAY_TYPE_SUN 0x85C1
+#define GL_REPLACEMENT_CODE_ARRAY_STRIDE_SUN 0x85C2
+#define GL_REPLACEMENT_CODE_ARRAY_POINTER_SUN 0x85C3
+#define GL_R1UI_V3F_SUN                   0x85C4
+#define GL_R1UI_C4UB_V3F_SUN              0x85C5
+#define GL_R1UI_C3F_V3F_SUN               0x85C6
+#define GL_R1UI_N3F_V3F_SUN               0x85C7
+#define GL_R1UI_C4F_N3F_V3F_SUN           0x85C8
+#define GL_R1UI_T2F_V3F_SUN               0x85C9
+#define GL_R1UI_T2F_N3F_V3F_SUN           0x85CA
+#define GL_R1UI_T2F_C4F_N3F_V3F_SUN       0x85CB
+#endif
+
+#ifndef GL_SUN_vertex
+#endif
+
+#ifndef GL_EXT_blend_func_separate
+#define GL_BLEND_DST_RGB_EXT              0x80C8
+#define GL_BLEND_SRC_RGB_EXT              0x80C9
+#define GL_BLEND_DST_ALPHA_EXT            0x80CA
+#define GL_BLEND_SRC_ALPHA_EXT            0x80CB
+#endif
+
+#ifndef GL_INGR_color_clamp
+#define GL_RED_MIN_CLAMP_INGR             0x8560
+#define GL_GREEN_MIN_CLAMP_INGR           0x8561
+#define GL_BLUE_MIN_CLAMP_INGR            0x8562
+#define GL_ALPHA_MIN_CLAMP_INGR           0x8563
+#define GL_RED_MAX_CLAMP_INGR             0x8564
+#define GL_GREEN_MAX_CLAMP_INGR           0x8565
+#define GL_BLUE_MAX_CLAMP_INGR            0x8566
+#define GL_ALPHA_MAX_CLAMP_INGR           0x8567
+#endif
+
+#ifndef GL_INGR_interlace_read
+#define GL_INTERLACE_READ_INGR            0x8568
+#endif
+
+#ifndef GL_EXT_stencil_wrap
+#define GL_INCR_WRAP_EXT                  0x8507
+#define GL_DECR_WRAP_EXT                  0x8508
+#endif
+
+#ifndef GL_EXT_422_pixels
+#define GL_422_EXT                        0x80CC
+#define GL_422_REV_EXT                    0x80CD
+#define GL_422_AVERAGE_EXT                0x80CE
+#define GL_422_REV_AVERAGE_EXT            0x80CF
+#endif
+
+#ifndef GL_NV_texgen_reflection
+#define GL_NORMAL_MAP_NV                  0x8511
+#define GL_REFLECTION_MAP_NV              0x8512
+#endif
+
+#ifndef GL_EXT_texture_cube_map
+#define GL_NORMAL_MAP_EXT                 0x8511
+#define GL_REFLECTION_MAP_EXT             0x8512
+#define GL_TEXTURE_CUBE_MAP_EXT           0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP_EXT   0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT 0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT 0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT 0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT 0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT 0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT 0x851A
+#define GL_PROXY_TEXTURE_CUBE_MAP_EXT     0x851B
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_EXT  0x851C
+#endif
+
+#ifndef GL_SUN_convolution_border_modes
+#define GL_WRAP_BORDER_SUN                0x81D4
+#endif
+
+#ifndef GL_EXT_texture_env_add
+#endif
+
+#ifndef GL_EXT_texture_lod_bias
+#define GL_MAX_TEXTURE_LOD_BIAS_EXT       0x84FD
+#define GL_TEXTURE_FILTER_CONTROL_EXT     0x8500
+#define GL_TEXTURE_LOD_BIAS_EXT           0x8501
+#endif
+
+#ifndef GL_EXT_texture_filter_anisotropic
+#define GL_TEXTURE_MAX_ANISOTROPY_EXT     0x84FE
+#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
+#endif
+
+#ifndef GL_EXT_vertex_weighting
+#define GL_MODELVIEW0_STACK_DEPTH_EXT     GL_MODELVIEW_STACK_DEPTH
+#define GL_MODELVIEW1_STACK_DEPTH_EXT     0x8502
+#define GL_MODELVIEW0_MATRIX_EXT          GL_MODELVIEW_MATRIX
+#define GL_MODELVIEW1_MATRIX_EXT          0x8506
+#define GL_VERTEX_WEIGHTING_EXT           0x8509
+#define GL_MODELVIEW0_EXT                 GL_MODELVIEW
+#define GL_MODELVIEW1_EXT                 0x850A
+#define GL_CURRENT_VERTEX_WEIGHT_EXT      0x850B
+#define GL_VERTEX_WEIGHT_ARRAY_EXT        0x850C
+#define GL_VERTEX_WEIGHT_ARRAY_SIZE_EXT   0x850D
+#define GL_VERTEX_WEIGHT_ARRAY_TYPE_EXT   0x850E
+#define GL_VERTEX_WEIGHT_ARRAY_STRIDE_EXT 0x850F
+#define GL_VERTEX_WEIGHT_ARRAY_POINTER_EXT 0x8510
+#endif
+
+#ifndef GL_NV_light_max_exponent
+#define GL_MAX_SHININESS_NV               0x8504
+#define GL_MAX_SPOT_EXPONENT_NV           0x8505
+#endif
+
+#ifndef GL_NV_vertex_array_range
+#define GL_VERTEX_ARRAY_RANGE_NV          0x851D
+#define GL_VERTEX_ARRAY_RANGE_LENGTH_NV   0x851E
+#define GL_VERTEX_ARRAY_RANGE_VALID_NV    0x851F
+#define GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_NV 0x8520
+#define GL_VERTEX_ARRAY_RANGE_POINTER_NV  0x8521
+#endif
+
+#ifndef GL_NV_register_combiners
+#define GL_REGISTER_COMBINERS_NV          0x8522
+#define GL_VARIABLE_A_NV                  0x8523
+#define GL_VARIABLE_B_NV                  0x8524
+#define GL_VARIABLE_C_NV                  0x8525
+#define GL_VARIABLE_D_NV                  0x8526
+#define GL_VARIABLE_E_NV                  0x8527
+#define GL_VARIABLE_F_NV                  0x8528
+#define GL_VARIABLE_G_NV                  0x8529
+#define GL_CONSTANT_COLOR0_NV             0x852A
+#define GL_CONSTANT_COLOR1_NV             0x852B
+#define GL_PRIMARY_COLOR_NV               0x852C
+#define GL_SECONDARY_COLOR_NV             0x852D
+#define GL_SPARE0_NV                      0x852E
+#define GL_SPARE1_NV                      0x852F
+#define GL_DISCARD_NV                     0x8530
+#define GL_E_TIMES_F_NV                   0x8531
+#define GL_SPARE0_PLUS_SECONDARY_COLOR_NV 0x8532
+#define GL_UNSIGNED_IDENTITY_NV           0x8536
+#define GL_UNSIGNED_INVERT_NV             0x8537
+#define GL_EXPAND_NORMAL_NV               0x8538
+#define GL_EXPAND_NEGATE_NV               0x8539
+#define GL_HALF_BIAS_NORMAL_NV            0x853A
+#define GL_HALF_BIAS_NEGATE_NV            0x853B
+#define GL_SIGNED_IDENTITY_NV             0x853C
+#define GL_SIGNED_NEGATE_NV               0x853D
+#define GL_SCALE_BY_TWO_NV                0x853E
+#define GL_SCALE_BY_FOUR_NV               0x853F
+#define GL_SCALE_BY_ONE_HALF_NV           0x8540
+#define GL_BIAS_BY_NEGATIVE_ONE_HALF_NV   0x8541
+#define GL_COMBINER_INPUT_NV              0x8542
+#define GL_COMBINER_MAPPING_NV            0x8543
+#define GL_COMBINER_COMPONENT_USAGE_NV    0x8544
+#define GL_COMBINER_AB_DOT_PRODUCT_NV     0x8545
+#define GL_COMBINER_CD_DOT_PRODUCT_NV     0x8546
+#define GL_COMBINER_MUX_SUM_NV            0x8547
+#define GL_COMBINER_SCALE_NV              0x8548
+#define GL_COMBINER_BIAS_NV               0x8549
+#define GL_COMBINER_AB_OUTPUT_NV          0x854A
+#define GL_COMBINER_CD_OUTPUT_NV          0x854B
+#define GL_COMBINER_SUM_OUTPUT_NV         0x854C
+#define GL_MAX_GENERAL_COMBINERS_NV       0x854D
+#define GL_NUM_GENERAL_COMBINERS_NV       0x854E
+#define GL_COLOR_SUM_CLAMP_NV             0x854F
+#define GL_COMBINER0_NV                   0x8550
+#define GL_COMBINER1_NV                   0x8551
+#define GL_COMBINER2_NV                   0x8552
+#define GL_COMBINER3_NV                   0x8553
+#define GL_COMBINER4_NV                   0x8554
+#define GL_COMBINER5_NV                   0x8555
+#define GL_COMBINER6_NV                   0x8556
+#define GL_COMBINER7_NV                   0x8557
+/* reuse GL_TEXTURE0_ARB */
+/* reuse GL_TEXTURE1_ARB */
+/* reuse GL_ZERO */
+/* reuse GL_NONE */
+/* reuse GL_FOG */
+#endif
+
+#ifndef GL_NV_fog_distance
+#define GL_FOG_DISTANCE_MODE_NV           0x855A
+#define GL_EYE_RADIAL_NV                  0x855B
+#define GL_EYE_PLANE_ABSOLUTE_NV          0x855C
+/* reuse GL_EYE_PLANE */
+#endif
+
+#ifndef GL_NV_texgen_emboss
+#define GL_EMBOSS_LIGHT_NV                0x855D
+#define GL_EMBOSS_CONSTANT_NV             0x855E
+#define GL_EMBOSS_MAP_NV                  0x855F
+#endif
+
+#ifndef GL_NV_blend_square
+#endif
+
+#ifndef GL_NV_texture_env_combine4
+#define GL_COMBINE4_NV                    0x8503
+#define GL_SOURCE3_RGB_NV                 0x8583
+#define GL_SOURCE3_ALPHA_NV               0x858B
+#define GL_OPERAND3_RGB_NV                0x8593
+#define GL_OPERAND3_ALPHA_NV              0x859B
+#endif
+
+#ifndef GL_MESA_resize_buffers
+#endif
+
+#ifndef GL_MESA_window_pos
+#endif
+
+#ifndef GL_EXT_texture_compression_s3tc
+#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT   0x83F0
+#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT  0x83F1
+#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT  0x83F2
+#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT  0x83F3
+#endif
+
+#ifndef GL_IBM_cull_vertex
+#define GL_CULL_VERTEX_IBM                103050
+#endif
+
+#ifndef GL_IBM_multimode_draw_arrays
+#endif
+
+#ifndef GL_IBM_vertex_array_lists
+#define GL_VERTEX_ARRAY_LIST_IBM          103070
+#define GL_NORMAL_ARRAY_LIST_IBM          103071
+#define GL_COLOR_ARRAY_LIST_IBM           103072
+#define GL_INDEX_ARRAY_LIST_IBM           103073
+#define GL_TEXTURE_COORD_ARRAY_LIST_IBM   103074
+#define GL_EDGE_FLAG_ARRAY_LIST_IBM       103075
+#define GL_FOG_COORDINATE_ARRAY_LIST_IBM  103076
+#define GL_SECONDARY_COLOR_ARRAY_LIST_IBM 103077
+#define GL_VERTEX_ARRAY_LIST_STRIDE_IBM   103080
+#define GL_NORMAL_ARRAY_LIST_STRIDE_IBM   103081
+#define GL_COLOR_ARRAY_LIST_STRIDE_IBM    103082
+#define GL_INDEX_ARRAY_LIST_STRIDE_IBM    103083
+#define GL_TEXTURE_COORD_ARRAY_LIST_STRIDE_IBM 103084
+#define GL_EDGE_FLAG_ARRAY_LIST_STRIDE_IBM 103085
+#define GL_FOG_COORDINATE_ARRAY_LIST_STRIDE_IBM 103086
+#define GL_SECONDARY_COLOR_ARRAY_LIST_STRIDE_IBM 103087
+#endif
+
+#ifndef GL_SGIX_subsample
+#define GL_PACK_SUBSAMPLE_RATE_SGIX       0x85A0
+#define GL_UNPACK_SUBSAMPLE_RATE_SGIX     0x85A1
+#define GL_PIXEL_SUBSAMPLE_4444_SGIX      0x85A2
+#define GL_PIXEL_SUBSAMPLE_2424_SGIX      0x85A3
+#define GL_PIXEL_SUBSAMPLE_4242_SGIX      0x85A4
+#endif
+
+#ifndef GL_SGIX_ycrcb_subsample
+#endif
+
+#ifndef GL_SGIX_ycrcba
+#define GL_YCRCB_SGIX                     0x8318
+#define GL_YCRCBA_SGIX                    0x8319
+#endif
+
+#ifndef GL_SGI_depth_pass_instrument
+#define GL_DEPTH_PASS_INSTRUMENT_SGIX     0x8310
+#define GL_DEPTH_PASS_INSTRUMENT_COUNTERS_SGIX 0x8311
+#define GL_DEPTH_PASS_INSTRUMENT_MAX_SGIX 0x8312
+#endif
+
+#ifndef GL_3DFX_texture_compression_FXT1
+#define GL_COMPRESSED_RGB_FXT1_3DFX       0x86B0
+#define GL_COMPRESSED_RGBA_FXT1_3DFX      0x86B1
+#endif
+
+#ifndef GL_3DFX_multisample
+#define GL_MULTISAMPLE_3DFX               0x86B2
+#define GL_SAMPLE_BUFFERS_3DFX            0x86B3
+#define GL_SAMPLES_3DFX                   0x86B4
+#define GL_MULTISAMPLE_BIT_3DFX           0x20000000
+#endif
+
+#ifndef GL_3DFX_tbuffer
+#endif
+
+#ifndef GL_EXT_multisample
+#define GL_MULTISAMPLE_EXT                0x809D
+#define GL_SAMPLE_ALPHA_TO_MASK_EXT       0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE_EXT        0x809F
+#define GL_SAMPLE_MASK_EXT                0x80A0
+#define GL_1PASS_EXT                      0x80A1
+#define GL_2PASS_0_EXT                    0x80A2
+#define GL_2PASS_1_EXT                    0x80A3
+#define GL_4PASS_0_EXT                    0x80A4
+#define GL_4PASS_1_EXT                    0x80A5
+#define GL_4PASS_2_EXT                    0x80A6
+#define GL_4PASS_3_EXT                    0x80A7
+#define GL_SAMPLE_BUFFERS_EXT             0x80A8
+#define GL_SAMPLES_EXT                    0x80A9
+#define GL_SAMPLE_MASK_VALUE_EXT          0x80AA
+#define GL_SAMPLE_MASK_INVERT_EXT         0x80AB
+#define GL_SAMPLE_PATTERN_EXT             0x80AC
+#define GL_MULTISAMPLE_BIT_EXT            0x20000000
+#endif
+
+#ifndef GL_SGIX_vertex_preclip
+#define GL_VERTEX_PRECLIP_SGIX            0x83EE
+#define GL_VERTEX_PRECLIP_HINT_SGIX       0x83EF
+#endif
+
+#ifndef GL_SGIX_convolution_accuracy
+#define GL_CONVOLUTION_HINT_SGIX          0x8316
+#endif
+
+#ifndef GL_SGIX_resample
+#define GL_PACK_RESAMPLE_SGIX             0x842C
+#define GL_UNPACK_RESAMPLE_SGIX           0x842D
+#define GL_RESAMPLE_REPLICATE_SGIX        0x842E
+#define GL_RESAMPLE_ZERO_FILL_SGIX        0x842F
+#define GL_RESAMPLE_DECIMATE_SGIX         0x8430
+#endif
+
+#ifndef GL_SGIS_point_line_texgen
+#define GL_EYE_DISTANCE_TO_POINT_SGIS     0x81F0
+#define GL_OBJECT_DISTANCE_TO_POINT_SGIS  0x81F1
+#define GL_EYE_DISTANCE_TO_LINE_SGIS      0x81F2
+#define GL_OBJECT_DISTANCE_TO_LINE_SGIS   0x81F3
+#define GL_EYE_POINT_SGIS                 0x81F4
+#define GL_OBJECT_POINT_SGIS              0x81F5
+#define GL_EYE_LINE_SGIS                  0x81F6
+#define GL_OBJECT_LINE_SGIS               0x81F7
+#endif
+
+#ifndef GL_SGIS_texture_color_mask
+#define GL_TEXTURE_COLOR_WRITEMASK_SGIS   0x81EF
+#endif
+
+#ifndef GL_EXT_texture_env_dot3
+#define GL_DOT3_RGB_EXT                   0x8740
+#define GL_DOT3_RGBA_EXT                  0x8741
+#endif
+
+#ifndef GL_ATI_texture_mirror_once
+#define GL_MIRROR_CLAMP_ATI               0x8742
+#define GL_MIRROR_CLAMP_TO_EDGE_ATI       0x8743
+#endif
+
+#ifndef GL_NV_fence
+#define GL_ALL_COMPLETED_NV               0x84F2
+#define GL_FENCE_STATUS_NV                0x84F3
+#define GL_FENCE_CONDITION_NV             0x84F4
+#endif
+
+#ifndef GL_IBM_texture_mirrored_repeat
+#define GL_MIRRORED_REPEAT_IBM            0x8370
+#endif
+
+#ifndef GL_NV_evaluators
+#define GL_EVAL_2D_NV                     0x86C0
+#define GL_EVAL_TRIANGULAR_2D_NV          0x86C1
+#define GL_MAP_TESSELLATION_NV            0x86C2
+#define GL_MAP_ATTRIB_U_ORDER_NV          0x86C3
+#define GL_MAP_ATTRIB_V_ORDER_NV          0x86C4
+#define GL_EVAL_FRACTIONAL_TESSELLATION_NV 0x86C5
+#define GL_EVAL_VERTEX_ATTRIB0_NV         0x86C6
+#define GL_EVAL_VERTEX_ATTRIB1_NV         0x86C7
+#define GL_EVAL_VERTEX_ATTRIB2_NV         0x86C8
+#define GL_EVAL_VERTEX_ATTRIB3_NV         0x86C9
+#define GL_EVAL_VERTEX_ATTRIB4_NV         0x86CA
+#define GL_EVAL_VERTEX_ATTRIB5_NV         0x86CB
+#define GL_EVAL_VERTEX_ATTRIB6_NV         0x86CC
+#define GL_EVAL_VERTEX_ATTRIB7_NV         0x86CD
+#define GL_EVAL_VERTEX_ATTRIB8_NV         0x86CE
+#define GL_EVAL_VERTEX_ATTRIB9_NV         0x86CF
+#define GL_EVAL_VERTEX_ATTRIB10_NV        0x86D0
+#define GL_EVAL_VERTEX_ATTRIB11_NV        0x86D1
+#define GL_EVAL_VERTEX_ATTRIB12_NV        0x86D2
+#define GL_EVAL_VERTEX_ATTRIB13_NV        0x86D3
+#define GL_EVAL_VERTEX_ATTRIB14_NV        0x86D4
+#define GL_EVAL_VERTEX_ATTRIB15_NV        0x86D5
+#define GL_MAX_MAP_TESSELLATION_NV        0x86D6
+#define GL_MAX_RATIONAL_EVAL_ORDER_NV     0x86D7
+#endif
+
+#ifndef GL_NV_packed_depth_stencil
+#define GL_DEPTH_STENCIL_NV               0x84F9
+#define GL_UNSIGNED_INT_24_8_NV           0x84FA
+#endif
+
+#ifndef GL_NV_register_combiners2
+#define GL_PER_STAGE_CONSTANTS_NV         0x8535
+#endif
+
+#ifndef GL_NV_texture_compression_vtc
+#endif
+
+#ifndef GL_NV_texture_rectangle
+#define GL_TEXTURE_RECTANGLE_NV           0x84F5
+#define GL_TEXTURE_BINDING_RECTANGLE_NV   0x84F6
+#define GL_PROXY_TEXTURE_RECTANGLE_NV     0x84F7
+#define GL_MAX_RECTANGLE_TEXTURE_SIZE_NV  0x84F8
+#endif
+
+#ifndef GL_NV_texture_shader
+#define GL_OFFSET_TEXTURE_RECTANGLE_NV    0x864C
+#define GL_OFFSET_TEXTURE_RECTANGLE_SCALE_NV 0x864D
+#define GL_DOT_PRODUCT_TEXTURE_RECTANGLE_NV 0x864E
+#define GL_RGBA_UNSIGNED_DOT_PRODUCT_MAPPING_NV 0x86D9
+#define GL_UNSIGNED_INT_S8_S8_8_8_NV      0x86DA
+#define GL_UNSIGNED_INT_8_8_S8_S8_REV_NV  0x86DB
+#define GL_DSDT_MAG_INTENSITY_NV          0x86DC
+#define GL_SHADER_CONSISTENT_NV           0x86DD
+#define GL_TEXTURE_SHADER_NV              0x86DE
+#define GL_SHADER_OPERATION_NV            0x86DF
+#define GL_CULL_MODES_NV                  0x86E0
+#define GL_OFFSET_TEXTURE_MATRIX_NV       0x86E1
+#define GL_OFFSET_TEXTURE_SCALE_NV        0x86E2
+#define GL_OFFSET_TEXTURE_BIAS_NV         0x86E3
+#define GL_OFFSET_TEXTURE_2D_MATRIX_NV    GL_OFFSET_TEXTURE_MATRIX_NV
+#define GL_OFFSET_TEXTURE_2D_SCALE_NV     GL_OFFSET_TEXTURE_SCALE_NV
+#define GL_OFFSET_TEXTURE_2D_BIAS_NV      GL_OFFSET_TEXTURE_BIAS_NV
+#define GL_PREVIOUS_TEXTURE_INPUT_NV      0x86E4
+#define GL_CONST_EYE_NV                   0x86E5
+#define GL_PASS_THROUGH_NV                0x86E6
+#define GL_CULL_FRAGMENT_NV               0x86E7
+#define GL_OFFSET_TEXTURE_2D_NV           0x86E8
+#define GL_DEPENDENT_AR_TEXTURE_2D_NV     0x86E9
+#define GL_DEPENDENT_GB_TEXTURE_2D_NV     0x86EA
+#define GL_DOT_PRODUCT_NV                 0x86EC
+#define GL_DOT_PRODUCT_DEPTH_REPLACE_NV   0x86ED
+#define GL_DOT_PRODUCT_TEXTURE_2D_NV      0x86EE
+#define GL_DOT_PRODUCT_TEXTURE_CUBE_MAP_NV 0x86F0
+#define GL_DOT_PRODUCT_DIFFUSE_CUBE_MAP_NV 0x86F1
+#define GL_DOT_PRODUCT_REFLECT_CUBE_MAP_NV 0x86F2
+#define GL_DOT_PRODUCT_CONST_EYE_REFLECT_CUBE_MAP_NV 0x86F3
+#define GL_HILO_NV                        0x86F4
+#define GL_DSDT_NV                        0x86F5
+#define GL_DSDT_MAG_NV                    0x86F6
+#define GL_DSDT_MAG_VIB_NV                0x86F7
+#define GL_HILO16_NV                      0x86F8
+#define GL_SIGNED_HILO_NV                 0x86F9
+#define GL_SIGNED_HILO16_NV               0x86FA
+#define GL_SIGNED_RGBA_NV                 0x86FB
+#define GL_SIGNED_RGBA8_NV                0x86FC
+#define GL_SIGNED_RGB_NV                  0x86FE
+#define GL_SIGNED_RGB8_NV                 0x86FF
+#define GL_SIGNED_LUMINANCE_NV            0x8701
+#define GL_SIGNED_LUMINANCE8_NV           0x8702
+#define GL_SIGNED_LUMINANCE_ALPHA_NV      0x8703
+#define GL_SIGNED_LUMINANCE8_ALPHA8_NV    0x8704
+#define GL_SIGNED_ALPHA_NV                0x8705
+#define GL_SIGNED_ALPHA8_NV               0x8706
+#define GL_SIGNED_INTENSITY_NV            0x8707
+#define GL_SIGNED_INTENSITY8_NV           0x8708
+#define GL_DSDT8_NV                       0x8709
+#define GL_DSDT8_MAG8_NV                  0x870A
+#define GL_DSDT8_MAG8_INTENSITY8_NV       0x870B
+#define GL_SIGNED_RGB_UNSIGNED_ALPHA_NV   0x870C
+#define GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV 0x870D
+#define GL_HI_SCALE_NV                    0x870E
+#define GL_LO_SCALE_NV                    0x870F
+#define GL_DS_SCALE_NV                    0x8710
+#define GL_DT_SCALE_NV                    0x8711
+#define GL_MAGNITUDE_SCALE_NV             0x8712
+#define GL_VIBRANCE_SCALE_NV              0x8713
+#define GL_HI_BIAS_NV                     0x8714
+#define GL_LO_BIAS_NV                     0x8715
+#define GL_DS_BIAS_NV                     0x8716
+#define GL_DT_BIAS_NV                     0x8717
+#define GL_MAGNITUDE_BIAS_NV              0x8718
+#define GL_VIBRANCE_BIAS_NV               0x8719
+#define GL_TEXTURE_BORDER_VALUES_NV       0x871A
+#define GL_TEXTURE_HI_SIZE_NV             0x871B
+#define GL_TEXTURE_LO_SIZE_NV             0x871C
+#define GL_TEXTURE_DS_SIZE_NV             0x871D
+#define GL_TEXTURE_DT_SIZE_NV             0x871E
+#define GL_TEXTURE_MAG_SIZE_NV            0x871F
+#endif
+
+#ifndef GL_NV_texture_shader2
+#define GL_DOT_PRODUCT_TEXTURE_3D_NV      0x86EF
+#endif
+
+#ifndef GL_NV_vertex_array_range2
+#define GL_VERTEX_ARRAY_RANGE_WITHOUT_FLUSH_NV 0x8533
+#endif
+
+#ifndef GL_NV_vertex_program
+#define GL_VERTEX_PROGRAM_NV              0x8620
+#define GL_VERTEX_STATE_PROGRAM_NV        0x8621
+#define GL_ATTRIB_ARRAY_SIZE_NV           0x8623
+#define GL_ATTRIB_ARRAY_STRIDE_NV         0x8624
+#define GL_ATTRIB_ARRAY_TYPE_NV           0x8625
+#define GL_CURRENT_ATTRIB_NV              0x8626
+#define GL_PROGRAM_LENGTH_NV              0x8627
+#define GL_PROGRAM_STRING_NV              0x8628
+#define GL_MODELVIEW_PROJECTION_NV        0x8629
+#define GL_IDENTITY_NV                    0x862A
+#define GL_INVERSE_NV                     0x862B
+#define GL_TRANSPOSE_NV                   0x862C
+#define GL_INVERSE_TRANSPOSE_NV           0x862D
+#define GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV 0x862E
+#define GL_MAX_TRACK_MATRICES_NV          0x862F
+#define GL_MATRIX0_NV                     0x8630
+#define GL_MATRIX1_NV                     0x8631
+#define GL_MATRIX2_NV                     0x8632
+#define GL_MATRIX3_NV                     0x8633
+#define GL_MATRIX4_NV                     0x8634
+#define GL_MATRIX5_NV                     0x8635
+#define GL_MATRIX6_NV                     0x8636
+#define GL_MATRIX7_NV                     0x8637
+#define GL_CURRENT_MATRIX_STACK_DEPTH_NV  0x8640
+#define GL_CURRENT_MATRIX_NV              0x8641
+#define GL_VERTEX_PROGRAM_POINT_SIZE_NV   0x8642
+#define GL_VERTEX_PROGRAM_TWO_SIDE_NV     0x8643
+#define GL_PROGRAM_PARAMETER_NV           0x8644
+#define GL_ATTRIB_ARRAY_POINTER_NV        0x8645
+#define GL_PROGRAM_TARGET_NV              0x8646
+#define GL_PROGRAM_RESIDENT_NV            0x8647
+#define GL_TRACK_MATRIX_NV                0x8648
+#define GL_TRACK_MATRIX_TRANSFORM_NV      0x8649
+#define GL_VERTEX_PROGRAM_BINDING_NV      0x864A
+#define GL_PROGRAM_ERROR_POSITION_NV      0x864B
+#define GL_VERTEX_ATTRIB_ARRAY0_NV        0x8650
+#define GL_VERTEX_ATTRIB_ARRAY1_NV        0x8651
+#define GL_VERTEX_ATTRIB_ARRAY2_NV        0x8652
+#define GL_VERTEX_ATTRIB_ARRAY3_NV        0x8653
+#define GL_VERTEX_ATTRIB_ARRAY4_NV        0x8654
+#define GL_VERTEX_ATTRIB_ARRAY5_NV        0x8655
+#define GL_VERTEX_ATTRIB_ARRAY6_NV        0x8656
+#define GL_VERTEX_ATTRIB_ARRAY7_NV        0x8657
+#define GL_VERTEX_ATTRIB_ARRAY8_NV        0x8658
+#define GL_VERTEX_ATTRIB_ARRAY9_NV        0x8659
+#define GL_VERTEX_ATTRIB_ARRAY10_NV       0x865A
+#define GL_VERTEX_ATTRIB_ARRAY11_NV       0x865B
+#define GL_VERTEX_ATTRIB_ARRAY12_NV       0x865C
+#define GL_VERTEX_ATTRIB_ARRAY13_NV       0x865D
+#define GL_VERTEX_ATTRIB_ARRAY14_NV       0x865E
+#define GL_VERTEX_ATTRIB_ARRAY15_NV       0x865F
+#define GL_MAP1_VERTEX_ATTRIB0_4_NV       0x8660
+#define GL_MAP1_VERTEX_ATTRIB1_4_NV       0x8661
+#define GL_MAP1_VERTEX_ATTRIB2_4_NV       0x8662
+#define GL_MAP1_VERTEX_ATTRIB3_4_NV       0x8663
+#define GL_MAP1_VERTEX_ATTRIB4_4_NV       0x8664
+#define GL_MAP1_VERTEX_ATTRIB5_4_NV       0x8665
+#define GL_MAP1_VERTEX_ATTRIB6_4_NV       0x8666
+#define GL_MAP1_VERTEX_ATTRIB7_4_NV       0x8667
+#define GL_MAP1_VERTEX_ATTRIB8_4_NV       0x8668
+#define GL_MAP1_VERTEX_ATTRIB9_4_NV       0x8669
+#define GL_MAP1_VERTEX_ATTRIB10_4_NV      0x866A
+#define GL_MAP1_VERTEX_ATTRIB11_4_NV      0x866B
+#define GL_MAP1_VERTEX_ATTRIB12_4_NV      0x866C
+#define GL_MAP1_VERTEX_ATTRIB13_4_NV      0x866D
+#define GL_MAP1_VERTEX_ATTRIB14_4_NV      0x866E
+#define GL_MAP1_VERTEX_ATTRIB15_4_NV      0x866F
+#define GL_MAP2_VERTEX_ATTRIB0_4_NV       0x8670
+#define GL_MAP2_VERTEX_ATTRIB1_4_NV       0x8671
+#define GL_MAP2_VERTEX_ATTRIB2_4_NV       0x8672
+#define GL_MAP2_VERTEX_ATTRIB3_4_NV       0x8673
+#define GL_MAP2_VERTEX_ATTRIB4_4_NV       0x8674
+#define GL_MAP2_VERTEX_ATTRIB5_4_NV       0x8675
+#define GL_MAP2_VERTEX_ATTRIB6_4_NV       0x8676
+#define GL_MAP2_VERTEX_ATTRIB7_4_NV       0x8677
+#define GL_MAP2_VERTEX_ATTRIB8_4_NV       0x8678
+#define GL_MAP2_VERTEX_ATTRIB9_4_NV       0x8679
+#define GL_MAP2_VERTEX_ATTRIB10_4_NV      0x867A
+#define GL_MAP2_VERTEX_ATTRIB11_4_NV      0x867B
+#define GL_MAP2_VERTEX_ATTRIB12_4_NV      0x867C
+#define GL_MAP2_VERTEX_ATTRIB13_4_NV      0x867D
+#define GL_MAP2_VERTEX_ATTRIB14_4_NV      0x867E
+#define GL_MAP2_VERTEX_ATTRIB15_4_NV      0x867F
+#endif
+
+#ifndef GL_SGIX_texture_coordinate_clamp
+#define GL_TEXTURE_MAX_CLAMP_S_SGIX       0x8369
+#define GL_TEXTURE_MAX_CLAMP_T_SGIX       0x836A
+#define GL_TEXTURE_MAX_CLAMP_R_SGIX       0x836B
+#endif
+
+#ifndef GL_SGIX_scalebias_hint
+#define GL_SCALEBIAS_HINT_SGIX            0x8322
+#endif
+
+#ifndef GL_OML_interlace
+#define GL_INTERLACE_OML                  0x8980
+#define GL_INTERLACE_READ_OML             0x8981
+#endif
+
+#ifndef GL_OML_subsample
+#define GL_FORMAT_SUBSAMPLE_24_24_OML     0x8982
+#define GL_FORMAT_SUBSAMPLE_244_244_OML   0x8983
+#endif
+
+#ifndef GL_OML_resample
+#define GL_PACK_RESAMPLE_OML              0x8984
+#define GL_UNPACK_RESAMPLE_OML            0x8985
+#define GL_RESAMPLE_REPLICATE_OML         0x8986
+#define GL_RESAMPLE_ZERO_FILL_OML         0x8987
+#define GL_RESAMPLE_AVERAGE_OML           0x8988
+#define GL_RESAMPLE_DECIMATE_OML          0x8989
+#endif
+
+#ifndef GL_NV_copy_depth_to_color
+#define GL_DEPTH_STENCIL_TO_RGBA_NV       0x886E
+#define GL_DEPTH_STENCIL_TO_BGRA_NV       0x886F
+#endif
+
+#ifndef GL_ATI_envmap_bumpmap
+#define GL_BUMP_ROT_MATRIX_ATI            0x8775
+#define GL_BUMP_ROT_MATRIX_SIZE_ATI       0x8776
+#define GL_BUMP_NUM_TEX_UNITS_ATI         0x8777
+#define GL_BUMP_TEX_UNITS_ATI             0x8778
+#define GL_DUDV_ATI                       0x8779
+#define GL_DU8DV8_ATI                     0x877A
+#define GL_BUMP_ENVMAP_ATI                0x877B
+#define GL_BUMP_TARGET_ATI                0x877C
+#endif
+
+#ifndef GL_ATI_fragment_shader
+#define GL_FRAGMENT_SHADER_ATI            0x8920
+#define GL_REG_0_ATI                      0x8921
+#define GL_REG_1_ATI                      0x8922
+#define GL_REG_2_ATI                      0x8923
+#define GL_REG_3_ATI                      0x8924
+#define GL_REG_4_ATI                      0x8925
+#define GL_REG_5_ATI                      0x8926
+#define GL_REG_6_ATI                      0x8927
+#define GL_REG_7_ATI                      0x8928
+#define GL_REG_8_ATI                      0x8929
+#define GL_REG_9_ATI                      0x892A
+#define GL_REG_10_ATI                     0x892B
+#define GL_REG_11_ATI                     0x892C
+#define GL_REG_12_ATI                     0x892D
+#define GL_REG_13_ATI                     0x892E
+#define GL_REG_14_ATI                     0x892F
+#define GL_REG_15_ATI                     0x8930
+#define GL_REG_16_ATI                     0x8931
+#define GL_REG_17_ATI                     0x8932
+#define GL_REG_18_ATI                     0x8933
+#define GL_REG_19_ATI                     0x8934
+#define GL_REG_20_ATI                     0x8935
+#define GL_REG_21_ATI                     0x8936
+#define GL_REG_22_ATI                     0x8937
+#define GL_REG_23_ATI                     0x8938
+#define GL_REG_24_ATI                     0x8939
+#define GL_REG_25_ATI                     0x893A
+#define GL_REG_26_ATI                     0x893B
+#define GL_REG_27_ATI                     0x893C
+#define GL_REG_28_ATI                     0x893D
+#define GL_REG_29_ATI                     0x893E
+#define GL_REG_30_ATI                     0x893F
+#define GL_REG_31_ATI                     0x8940
+#define GL_CON_0_ATI                      0x8941
+#define GL_CON_1_ATI                      0x8942
+#define GL_CON_2_ATI                      0x8943
+#define GL_CON_3_ATI                      0x8944
+#define GL_CON_4_ATI                      0x8945
+#define GL_CON_5_ATI                      0x8946
+#define GL_CON_6_ATI                      0x8947
+#define GL_CON_7_ATI                      0x8948
+#define GL_CON_8_ATI                      0x8949
+#define GL_CON_9_ATI                      0x894A
+#define GL_CON_10_ATI                     0x894B
+#define GL_CON_11_ATI                     0x894C
+#define GL_CON_12_ATI                     0x894D
+#define GL_CON_13_ATI                     0x894E
+#define GL_CON_14_ATI                     0x894F
+#define GL_CON_15_ATI                     0x8950
+#define GL_CON_16_ATI                     0x8951
+#define GL_CON_17_ATI                     0x8952
+#define GL_CON_18_ATI                     0x8953
+#define GL_CON_19_ATI                     0x8954
+#define GL_CON_20_ATI                     0x8955
+#define GL_CON_21_ATI                     0x8956
+#define GL_CON_22_ATI                     0x8957
+#define GL_CON_23_ATI                     0x8958
+#define GL_CON_24_ATI                     0x8959
+#define GL_CON_25_ATI                     0x895A
+#define GL_CON_26_ATI                     0x895B
+#define GL_CON_27_ATI                     0x895C
+#define GL_CON_28_ATI                     0x895D
+#define GL_CON_29_ATI                     0x895E
+#define GL_CON_30_ATI                     0x895F
+#define GL_CON_31_ATI                     0x8960
+#define GL_MOV_ATI                        0x8961
+#define GL_ADD_ATI                        0x8963
+#define GL_MUL_ATI                        0x8964
+#define GL_SUB_ATI                        0x8965
+#define GL_DOT3_ATI                       0x8966
+#define GL_DOT4_ATI                       0x8967
+#define GL_MAD_ATI                        0x8968
+#define GL_LERP_ATI                       0x8969
+#define GL_CND_ATI                        0x896A
+#define GL_CND0_ATI                       0x896B
+#define GL_DOT2_ADD_ATI                   0x896C
+#define GL_SECONDARY_INTERPOLATOR_ATI     0x896D
+#define GL_NUM_FRAGMENT_REGISTERS_ATI     0x896E
+#define GL_NUM_FRAGMENT_CONSTANTS_ATI     0x896F
+#define GL_NUM_PASSES_ATI                 0x8970
+#define GL_NUM_INSTRUCTIONS_PER_PASS_ATI  0x8971
+#define GL_NUM_INSTRUCTIONS_TOTAL_ATI     0x8972
+#define GL_NUM_INPUT_INTERPOLATOR_COMPONENTS_ATI 0x8973
+#define GL_NUM_LOOPBACK_COMPONENTS_ATI    0x8974
+#define GL_COLOR_ALPHA_PAIRING_ATI        0x8975
+#define GL_SWIZZLE_STR_ATI                0x8976
+#define GL_SWIZZLE_STQ_ATI                0x8977
+#define GL_SWIZZLE_STR_DR_ATI             0x8978
+#define GL_SWIZZLE_STQ_DQ_ATI             0x8979
+#define GL_SWIZZLE_STRQ_ATI               0x897A
+#define GL_SWIZZLE_STRQ_DQ_ATI            0x897B
+#define GL_RED_BIT_ATI                    0x00000001
+#define GL_GREEN_BIT_ATI                  0x00000002
+#define GL_BLUE_BIT_ATI                   0x00000004
+#define GL_2X_BIT_ATI                     0x00000001
+#define GL_4X_BIT_ATI                     0x00000002
+#define GL_8X_BIT_ATI                     0x00000004
+#define GL_HALF_BIT_ATI                   0x00000008
+#define GL_QUARTER_BIT_ATI                0x00000010
+#define GL_EIGHTH_BIT_ATI                 0x00000020
+#define GL_SATURATE_BIT_ATI               0x00000040
+#define GL_COMP_BIT_ATI                   0x00000002
+#define GL_NEGATE_BIT_ATI                 0x00000004
+#define GL_BIAS_BIT_ATI                   0x00000008
+#endif
+
+#ifndef GL_ATI_pn_triangles
+#define GL_PN_TRIANGLES_ATI               0x87F0
+#define GL_MAX_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F1
+#define GL_PN_TRIANGLES_POINT_MODE_ATI    0x87F2
+#define GL_PN_TRIANGLES_NORMAL_MODE_ATI   0x87F3
+#define GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F4
+#define GL_PN_TRIANGLES_POINT_MODE_LINEAR_ATI 0x87F5
+#define GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI 0x87F6
+#define GL_PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI 0x87F7
+#define GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI 0x87F8
+#endif
+
+#ifndef GL_ATI_vertex_array_object
+#define GL_STATIC_ATI                     0x8760
+#define GL_DYNAMIC_ATI                    0x8761
+#define GL_PRESERVE_ATI                   0x8762
+#define GL_DISCARD_ATI                    0x8763
+#define GL_OBJECT_BUFFER_SIZE_ATI         0x8764
+#define GL_OBJECT_BUFFER_USAGE_ATI        0x8765
+#define GL_ARRAY_OBJECT_BUFFER_ATI        0x8766
+#define GL_ARRAY_OBJECT_OFFSET_ATI        0x8767
+#endif
+
+#ifndef GL_EXT_vertex_shader
+#define GL_VERTEX_SHADER_EXT              0x8780
+#define GL_VERTEX_SHADER_BINDING_EXT      0x8781
+#define GL_OP_INDEX_EXT                   0x8782
+#define GL_OP_NEGATE_EXT                  0x8783
+#define GL_OP_DOT3_EXT                    0x8784
+#define GL_OP_DOT4_EXT                    0x8785
+#define GL_OP_MUL_EXT                     0x8786
+#define GL_OP_ADD_EXT                     0x8787
+#define GL_OP_MADD_EXT                    0x8788
+#define GL_OP_FRAC_EXT                    0x8789
+#define GL_OP_MAX_EXT                     0x878A
+#define GL_OP_MIN_EXT                     0x878B
+#define GL_OP_SET_GE_EXT                  0x878C
+#define GL_OP_SET_LT_EXT                  0x878D
+#define GL_OP_CLAMP_EXT                   0x878E
+#define GL_OP_FLOOR_EXT                   0x878F
+#define GL_OP_ROUND_EXT                   0x8790
+#define GL_OP_EXP_BASE_2_EXT              0x8791
+#define GL_OP_LOG_BASE_2_EXT              0x8792
+#define GL_OP_POWER_EXT                   0x8793
+#define GL_OP_RECIP_EXT                   0x8794
+#define GL_OP_RECIP_SQRT_EXT              0x8795
+#define GL_OP_SUB_EXT                     0x8796
+#define GL_OP_CROSS_PRODUCT_EXT           0x8797
+#define GL_OP_MULTIPLY_MATRIX_EXT         0x8798
+#define GL_OP_MOV_EXT                     0x8799
+#define GL_OUTPUT_VERTEX_EXT              0x879A
+#define GL_OUTPUT_COLOR0_EXT              0x879B
+#define GL_OUTPUT_COLOR1_EXT              0x879C
+#define GL_OUTPUT_TEXTURE_COORD0_EXT      0x879D
+#define GL_OUTPUT_TEXTURE_COORD1_EXT      0x879E
+#define GL_OUTPUT_TEXTURE_COORD2_EXT      0x879F
+#define GL_OUTPUT_TEXTURE_COORD3_EXT      0x87A0
+#define GL_OUTPUT_TEXTURE_COORD4_EXT      0x87A1
+#define GL_OUTPUT_TEXTURE_COORD5_EXT      0x87A2
+#define GL_OUTPUT_TEXTURE_COORD6_EXT      0x87A3
+#define GL_OUTPUT_TEXTURE_COORD7_EXT      0x87A4
+#define GL_OUTPUT_TEXTURE_COORD8_EXT      0x87A5
+#define GL_OUTPUT_TEXTURE_COORD9_EXT      0x87A6
+#define GL_OUTPUT_TEXTURE_COORD10_EXT     0x87A7
+#define GL_OUTPUT_TEXTURE_COORD11_EXT     0x87A8
+#define GL_OUTPUT_TEXTURE_COORD12_EXT     0x87A9
+#define GL_OUTPUT_TEXTURE_COORD13_EXT     0x87AA
+#define GL_OUTPUT_TEXTURE_COORD14_EXT     0x87AB
+#define GL_OUTPUT_TEXTURE_COORD15_EXT     0x87AC
+#define GL_OUTPUT_TEXTURE_COORD16_EXT     0x87AD
+#define GL_OUTPUT_TEXTURE_COORD17_EXT     0x87AE
+#define GL_OUTPUT_TEXTURE_COORD18_EXT     0x87AF
+#define GL_OUTPUT_TEXTURE_COORD19_EXT     0x87B0
+#define GL_OUTPUT_TEXTURE_COORD20_EXT     0x87B1
+#define GL_OUTPUT_TEXTURE_COORD21_EXT     0x87B2
+#define GL_OUTPUT_TEXTURE_COORD22_EXT     0x87B3
+#define GL_OUTPUT_TEXTURE_COORD23_EXT     0x87B4
+#define GL_OUTPUT_TEXTURE_COORD24_EXT     0x87B5
+#define GL_OUTPUT_TEXTURE_COORD25_EXT     0x87B6
+#define GL_OUTPUT_TEXTURE_COORD26_EXT     0x87B7
+#define GL_OUTPUT_TEXTURE_COORD27_EXT     0x87B8
+#define GL_OUTPUT_TEXTURE_COORD28_EXT     0x87B9
+#define GL_OUTPUT_TEXTURE_COORD29_EXT     0x87BA
+#define GL_OUTPUT_TEXTURE_COORD30_EXT     0x87BB
+#define GL_OUTPUT_TEXTURE_COORD31_EXT     0x87BC
+#define GL_OUTPUT_FOG_EXT                 0x87BD
+#define GL_SCALAR_EXT                     0x87BE
+#define GL_VECTOR_EXT                     0x87BF
+#define GL_MATRIX_EXT                     0x87C0
+#define GL_VARIANT_EXT                    0x87C1
+#define GL_INVARIANT_EXT                  0x87C2
+#define GL_LOCAL_CONSTANT_EXT             0x87C3
+#define GL_LOCAL_EXT                      0x87C4
+#define GL_MAX_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87C5
+#define GL_MAX_VERTEX_SHADER_VARIANTS_EXT 0x87C6
+#define GL_MAX_VERTEX_SHADER_INVARIANTS_EXT 0x87C7
+#define GL_MAX_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87C8
+#define GL_MAX_VERTEX_SHADER_LOCALS_EXT   0x87C9
+#define GL_MAX_OPTIMIZED_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CA
+#define GL_MAX_OPTIMIZED_VERTEX_SHADER_VARIANTS_EXT 0x87CB
+#define GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87CC
+#define GL_MAX_OPTIMIZED_VERTEX_SHADER_INVARIANTS_EXT 0x87CD
+#define GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCALS_EXT 0x87CE
+#define GL_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CF
+#define GL_VERTEX_SHADER_VARIANTS_EXT     0x87D0
+#define GL_VERTEX_SHADER_INVARIANTS_EXT   0x87D1
+#define GL_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87D2
+#define GL_VERTEX_SHADER_LOCALS_EXT       0x87D3
+#define GL_VERTEX_SHADER_OPTIMIZED_EXT    0x87D4
+#define GL_X_EXT                          0x87D5
+#define GL_Y_EXT                          0x87D6
+#define GL_Z_EXT                          0x87D7
+#define GL_W_EXT                          0x87D8
+#define GL_NEGATIVE_X_EXT                 0x87D9
+#define GL_NEGATIVE_Y_EXT                 0x87DA
+#define GL_NEGATIVE_Z_EXT                 0x87DB
+#define GL_NEGATIVE_W_EXT                 0x87DC
+#define GL_ZERO_EXT                       0x87DD
+#define GL_ONE_EXT                        0x87DE
+#define GL_NEGATIVE_ONE_EXT               0x87DF
+#define GL_NORMALIZED_RANGE_EXT           0x87E0
+#define GL_FULL_RANGE_EXT                 0x87E1
+#define GL_CURRENT_VERTEX_EXT             0x87E2
+#define GL_MVP_MATRIX_EXT                 0x87E3
+#define GL_VARIANT_VALUE_EXT              0x87E4
+#define GL_VARIANT_DATATYPE_EXT           0x87E5
+#define GL_VARIANT_ARRAY_STRIDE_EXT       0x87E6
+#define GL_VARIANT_ARRAY_TYPE_EXT         0x87E7
+#define GL_VARIANT_ARRAY_EXT              0x87E8
+#define GL_VARIANT_ARRAY_POINTER_EXT      0x87E9
+#define GL_INVARIANT_VALUE_EXT            0x87EA
+#define GL_INVARIANT_DATATYPE_EXT         0x87EB
+#define GL_LOCAL_CONSTANT_VALUE_EXT       0x87EC
+#define GL_LOCAL_CONSTANT_DATATYPE_EXT    0x87ED
+#endif
+
+#ifndef GL_ATI_vertex_streams
+#define GL_MAX_VERTEX_STREAMS_ATI         0x876B
+#define GL_VERTEX_STREAM0_ATI             0x876C
+#define GL_VERTEX_STREAM1_ATI             0x876D
+#define GL_VERTEX_STREAM2_ATI             0x876E
+#define GL_VERTEX_STREAM3_ATI             0x876F
+#define GL_VERTEX_STREAM4_ATI             0x8770
+#define GL_VERTEX_STREAM5_ATI             0x8771
+#define GL_VERTEX_STREAM6_ATI             0x8772
+#define GL_VERTEX_STREAM7_ATI             0x8773
+#define GL_VERTEX_SOURCE_ATI              0x8774
+#endif
+
+#ifndef GL_ATI_element_array
+#define GL_ELEMENT_ARRAY_ATI              0x8768
+#define GL_ELEMENT_ARRAY_TYPE_ATI         0x8769
+#define GL_ELEMENT_ARRAY_POINTER_ATI      0x876A
+#endif
+
+#ifndef GL_SUN_mesh_array
+#define GL_QUAD_MESH_SUN                  0x8614
+#define GL_TRIANGLE_MESH_SUN              0x8615
+#endif
+
+#ifndef GL_SUN_slice_accum
+#define GL_SLICE_ACCUM_SUN                0x85CC
+#endif
+
+#ifndef GL_NV_multisample_filter_hint
+#define GL_MULTISAMPLE_FILTER_HINT_NV     0x8534
+#endif
+
+#ifndef GL_NV_depth_clamp
+#define GL_DEPTH_CLAMP_NV                 0x864F
+#endif
+
+#ifndef GL_NV_occlusion_query
+#define GL_PIXEL_COUNTER_BITS_NV          0x8864
+#define GL_CURRENT_OCCLUSION_QUERY_ID_NV  0x8865
+#define GL_PIXEL_COUNT_NV                 0x8866
+#define GL_PIXEL_COUNT_AVAILABLE_NV       0x8867
+#endif
+
+#ifndef GL_NV_point_sprite
+#define GL_POINT_SPRITE_NV                0x8861
+#define GL_COORD_REPLACE_NV               0x8862
+#define GL_POINT_SPRITE_R_MODE_NV         0x8863
+#endif
+
+#ifndef GL_NV_texture_shader3
+#define GL_OFFSET_PROJECTIVE_TEXTURE_2D_NV 0x8850
+#define GL_OFFSET_PROJECTIVE_TEXTURE_2D_SCALE_NV 0x8851
+#define GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8852
+#define GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_SCALE_NV 0x8853
+#define GL_OFFSET_HILO_TEXTURE_2D_NV      0x8854
+#define GL_OFFSET_HILO_TEXTURE_RECTANGLE_NV 0x8855
+#define GL_OFFSET_HILO_PROJECTIVE_TEXTURE_2D_NV 0x8856
+#define GL_OFFSET_HILO_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8857
+#define GL_DEPENDENT_HILO_TEXTURE_2D_NV   0x8858
+#define GL_DEPENDENT_RGB_TEXTURE_3D_NV    0x8859
+#define GL_DEPENDENT_RGB_TEXTURE_CUBE_MAP_NV 0x885A
+#define GL_DOT_PRODUCT_PASS_THROUGH_NV    0x885B
+#define GL_DOT_PRODUCT_TEXTURE_1D_NV      0x885C
+#define GL_DOT_PRODUCT_AFFINE_DEPTH_REPLACE_NV 0x885D
+#define GL_HILO8_NV                       0x885E
+#define GL_SIGNED_HILO8_NV                0x885F
+#define GL_FORCE_BLUE_TO_ONE_NV           0x8860
+#endif
+
+#ifndef GL_NV_vertex_program1_1
+#endif
+
+#ifndef GL_EXT_shadow_funcs
+#endif
+
+#ifndef GL_EXT_stencil_two_side
+#define GL_STENCIL_TEST_TWO_SIDE_EXT      0x8910
+#define GL_ACTIVE_STENCIL_FACE_EXT        0x8911
+#endif
+
+#ifndef GL_ATI_text_fragment_shader
+#define GL_TEXT_FRAGMENT_SHADER_ATI       0x8200
+#endif
+
+#ifndef GL_APPLE_client_storage
+#define GL_UNPACK_CLIENT_STORAGE_APPLE    0x85B2
+#endif
+
+#ifndef GL_APPLE_element_array
+#define GL_ELEMENT_ARRAY_APPLE            0x8768
+#define GL_ELEMENT_ARRAY_TYPE_APPLE       0x8769
+#define GL_ELEMENT_ARRAY_POINTER_APPLE    0x876A
+#endif
+
+#ifndef GL_APPLE_fence
+#define GL_DRAW_PIXELS_APPLE              0x8A0A
+#define GL_FENCE_APPLE                    0x8A0B
+#endif
+
+#ifndef GL_APPLE_vertex_array_object
+#define GL_VERTEX_ARRAY_BINDING_APPLE     0x85B5
+#endif
+
+#ifndef GL_APPLE_vertex_array_range
+#define GL_VERTEX_ARRAY_RANGE_APPLE       0x851D
+#define GL_VERTEX_ARRAY_RANGE_LENGTH_APPLE 0x851E
+#define GL_VERTEX_ARRAY_STORAGE_HINT_APPLE 0x851F
+#define GL_VERTEX_ARRAY_RANGE_POINTER_APPLE 0x8521
+#define GL_STORAGE_CACHED_APPLE           0x85BE
+#define GL_STORAGE_SHARED_APPLE           0x85BF
+#endif
+
+#ifndef GL_APPLE_ycbcr_422
+#define GL_YCBCR_422_APPLE                0x85B9
+#define GL_UNSIGNED_SHORT_8_8_APPLE       0x85BA
+#define GL_UNSIGNED_SHORT_8_8_REV_APPLE   0x85BB
+#endif
+
+#ifndef GL_S3_s3tc
+#define GL_RGB_S3TC                       0x83A0
+#define GL_RGB4_S3TC                      0x83A1
+#define GL_RGBA_S3TC                      0x83A2
+#define GL_RGBA4_S3TC                     0x83A3
+#endif
+
+#ifndef GL_ATI_draw_buffers
+#define GL_MAX_DRAW_BUFFERS_ATI           0x8824
+#define GL_DRAW_BUFFER0_ATI               0x8825
+#define GL_DRAW_BUFFER1_ATI               0x8826
+#define GL_DRAW_BUFFER2_ATI               0x8827
+#define GL_DRAW_BUFFER3_ATI               0x8828
+#define GL_DRAW_BUFFER4_ATI               0x8829
+#define GL_DRAW_BUFFER5_ATI               0x882A
+#define GL_DRAW_BUFFER6_ATI               0x882B
+#define GL_DRAW_BUFFER7_ATI               0x882C
+#define GL_DRAW_BUFFER8_ATI               0x882D
+#define GL_DRAW_BUFFER9_ATI               0x882E
+#define GL_DRAW_BUFFER10_ATI              0x882F
+#define GL_DRAW_BUFFER11_ATI              0x8830
+#define GL_DRAW_BUFFER12_ATI              0x8831
+#define GL_DRAW_BUFFER13_ATI              0x8832
+#define GL_DRAW_BUFFER14_ATI              0x8833
+#define GL_DRAW_BUFFER15_ATI              0x8834
+#endif
+
+#ifndef GL_ATI_pixel_format_float
+#define GL_TYPE_RGBA_FLOAT_ATI            0x8820
+#define GL_COLOR_CLEAR_UNCLAMPED_VALUE_ATI 0x8835
+#endif
+
+#ifndef GL_ATI_texture_env_combine3
+#define GL_MODULATE_ADD_ATI               0x8744
+#define GL_MODULATE_SIGNED_ADD_ATI        0x8745
+#define GL_MODULATE_SUBTRACT_ATI          0x8746
+#endif
+
+#ifndef GL_ATI_texture_float
+#define GL_RGBA_FLOAT32_ATI               0x8814
+#define GL_RGB_FLOAT32_ATI                0x8815
+#define GL_ALPHA_FLOAT32_ATI              0x8816
+#define GL_INTENSITY_FLOAT32_ATI          0x8817
+#define GL_LUMINANCE_FLOAT32_ATI          0x8818
+#define GL_LUMINANCE_ALPHA_FLOAT32_ATI    0x8819
+#define GL_RGBA_FLOAT16_ATI               0x881A
+#define GL_RGB_FLOAT16_ATI                0x881B
+#define GL_ALPHA_FLOAT16_ATI              0x881C
+#define GL_INTENSITY_FLOAT16_ATI          0x881D
+#define GL_LUMINANCE_FLOAT16_ATI          0x881E
+#define GL_LUMINANCE_ALPHA_FLOAT16_ATI    0x881F
+#endif
+
+#ifndef GL_NV_float_buffer
+#define GL_FLOAT_R_NV                     0x8880
+#define GL_FLOAT_RG_NV                    0x8881
+#define GL_FLOAT_RGB_NV                   0x8882
+#define GL_FLOAT_RGBA_NV                  0x8883
+#define GL_FLOAT_R16_NV                   0x8884
+#define GL_FLOAT_R32_NV                   0x8885
+#define GL_FLOAT_RG16_NV                  0x8886
+#define GL_FLOAT_RG32_NV                  0x8887
+#define GL_FLOAT_RGB16_NV                 0x8888
+#define GL_FLOAT_RGB32_NV                 0x8889
+#define GL_FLOAT_RGBA16_NV                0x888A
+#define GL_FLOAT_RGBA32_NV                0x888B
+#define GL_TEXTURE_FLOAT_COMPONENTS_NV    0x888C
+#define GL_FLOAT_CLEAR_COLOR_VALUE_NV     0x888D
+#define GL_FLOAT_RGBA_MODE_NV             0x888E
+#endif
+
+#ifndef GL_NV_fragment_program
+#define GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV 0x8868
+#define GL_FRAGMENT_PROGRAM_NV            0x8870
+#define GL_MAX_TEXTURE_COORDS_NV          0x8871
+#define GL_MAX_TEXTURE_IMAGE_UNITS_NV     0x8872
+#define GL_FRAGMENT_PROGRAM_BINDING_NV    0x8873
+#define GL_PROGRAM_ERROR_STRING_NV        0x8874
+#endif
+
+#ifndef GL_NV_half_float
+#define GL_HALF_FLOAT_NV                  0x140B
+#endif
+
+#ifndef GL_NV_pixel_data_range
+#define GL_WRITE_PIXEL_DATA_RANGE_NV      0x8878
+#define GL_READ_PIXEL_DATA_RANGE_NV       0x8879
+#define GL_WRITE_PIXEL_DATA_RANGE_LENGTH_NV 0x887A
+#define GL_READ_PIXEL_DATA_RANGE_LENGTH_NV 0x887B
+#define GL_WRITE_PIXEL_DATA_RANGE_POINTER_NV 0x887C
+#define GL_READ_PIXEL_DATA_RANGE_POINTER_NV 0x887D
+#endif
+
+#ifndef GL_NV_primitive_restart
+#define GL_PRIMITIVE_RESTART_NV           0x8558
+#define GL_PRIMITIVE_RESTART_INDEX_NV     0x8559
+#endif
+
+#ifndef GL_NV_texture_expand_normal
+#define GL_TEXTURE_UNSIGNED_REMAP_MODE_NV 0x888F
+#endif
+
+#ifndef GL_NV_vertex_program2
+#endif
+
+#ifndef GL_ATI_map_object_buffer
+#endif
+
+#ifndef GL_ATI_separate_stencil
+#define GL_STENCIL_BACK_FUNC_ATI          0x8800
+#define GL_STENCIL_BACK_FAIL_ATI          0x8801
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL_ATI 0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS_ATI 0x8803
+#endif
+
+#ifndef GL_ATI_vertex_attrib_array_object
+#endif
+
+#ifndef GL_OES_read_format
+#define GL_IMPLEMENTATION_COLOR_READ_TYPE_OES 0x8B9A
+#define GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES 0x8B9B
+#endif
+
+#ifndef GL_EXT_depth_bounds_test
+#define GL_DEPTH_BOUNDS_TEST_EXT          0x8890
+#define GL_DEPTH_BOUNDS_EXT               0x8891
+#endif
+
+#ifndef GL_EXT_texture_mirror_clamp
+#define GL_MIRROR_CLAMP_EXT               0x8742
+#define GL_MIRROR_CLAMP_TO_EDGE_EXT       0x8743
+#define GL_MIRROR_CLAMP_TO_BORDER_EXT     0x8912
+#endif
+
+#ifndef GL_EXT_blend_equation_separate
+#define GL_BLEND_EQUATION_RGB_EXT         GL_BLEND_EQUATION
+#define GL_BLEND_EQUATION_ALPHA_EXT       0x883D
+#endif
+
+#ifndef GL_MESA_pack_invert
+#define GL_PACK_INVERT_MESA               0x8758
+#endif
+
+#ifndef GL_MESA_ycbcr_texture
+#define GL_UNSIGNED_SHORT_8_8_MESA        0x85BA
+#define GL_UNSIGNED_SHORT_8_8_REV_MESA    0x85BB
+#define GL_YCBCR_MESA                     0x8757
+#endif
+
+#ifndef GL_EXT_pixel_buffer_object
+#define GL_PIXEL_PACK_BUFFER_EXT          0x88EB
+#define GL_PIXEL_UNPACK_BUFFER_EXT        0x88EC
+#define GL_PIXEL_PACK_BUFFER_BINDING_EXT  0x88ED
+#define GL_PIXEL_UNPACK_BUFFER_BINDING_EXT 0x88EF
+#endif
+
+#ifndef GL_NV_fragment_program_option
+#endif
+
+#ifndef GL_NV_fragment_program2
+#define GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV 0x88F4
+#define GL_MAX_PROGRAM_CALL_DEPTH_NV      0x88F5
+#define GL_MAX_PROGRAM_IF_DEPTH_NV        0x88F6
+#define GL_MAX_PROGRAM_LOOP_DEPTH_NV      0x88F7
+#define GL_MAX_PROGRAM_LOOP_COUNT_NV      0x88F8
+#endif
+
+#ifndef GL_NV_vertex_program2_option
+/* reuse GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV */
+/* reuse GL_MAX_PROGRAM_CALL_DEPTH_NV */
+#endif
+
+#ifndef GL_NV_vertex_program3
+/* reuse GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB */
+#endif
+
+#ifndef GL_EXT_framebuffer_object
+#define GL_INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506
+#define GL_MAX_RENDERBUFFER_SIZE_EXT      0x84E8
+#define GL_FRAMEBUFFER_BINDING_EXT        0x8CA6
+#define GL_RENDERBUFFER_BINDING_EXT       0x8CA7
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT 0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT 0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT 0x8CD3
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT 0x8CD4
+#define GL_FRAMEBUFFER_COMPLETE_EXT       0x8CD5
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT 0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT 0x8CD8
+#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT 0x8CD9
+#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT 0x8CDA
+#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT 0x8CDB
+#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT 0x8CDC
+#define GL_FRAMEBUFFER_UNSUPPORTED_EXT    0x8CDD
+#define GL_MAX_COLOR_ATTACHMENTS_EXT      0x8CDF
+#define GL_COLOR_ATTACHMENT0_EXT          0x8CE0
+#define GL_COLOR_ATTACHMENT1_EXT          0x8CE1
+#define GL_COLOR_ATTACHMENT2_EXT          0x8CE2
+#define GL_COLOR_ATTACHMENT3_EXT          0x8CE3
+#define GL_COLOR_ATTACHMENT4_EXT          0x8CE4
+#define GL_COLOR_ATTACHMENT5_EXT          0x8CE5
+#define GL_COLOR_ATTACHMENT6_EXT          0x8CE6
+#define GL_COLOR_ATTACHMENT7_EXT          0x8CE7
+#define GL_COLOR_ATTACHMENT8_EXT          0x8CE8
+#define GL_COLOR_ATTACHMENT9_EXT          0x8CE9
+#define GL_COLOR_ATTACHMENT10_EXT         0x8CEA
+#define GL_COLOR_ATTACHMENT11_EXT         0x8CEB
+#define GL_COLOR_ATTACHMENT12_EXT         0x8CEC
+#define GL_COLOR_ATTACHMENT13_EXT         0x8CED
+#define GL_COLOR_ATTACHMENT14_EXT         0x8CEE
+#define GL_COLOR_ATTACHMENT15_EXT         0x8CEF
+#define GL_DEPTH_ATTACHMENT_EXT           0x8D00
+#define GL_STENCIL_ATTACHMENT_EXT         0x8D20
+#define GL_FRAMEBUFFER_EXT                0x8D40
+#define GL_RENDERBUFFER_EXT               0x8D41
+#define GL_RENDERBUFFER_WIDTH_EXT         0x8D42
+#define GL_RENDERBUFFER_HEIGHT_EXT        0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT_EXT 0x8D44
+#define GL_STENCIL_INDEX1_EXT             0x8D46
+#define GL_STENCIL_INDEX4_EXT             0x8D47
+#define GL_STENCIL_INDEX8_EXT             0x8D48
+#define GL_STENCIL_INDEX16_EXT            0x8D49
+#define GL_RENDERBUFFER_RED_SIZE_EXT      0x8D50
+#define GL_RENDERBUFFER_GREEN_SIZE_EXT    0x8D51
+#define GL_RENDERBUFFER_BLUE_SIZE_EXT     0x8D52
+#define GL_RENDERBUFFER_ALPHA_SIZE_EXT    0x8D53
+#define GL_RENDERBUFFER_DEPTH_SIZE_EXT    0x8D54
+#define GL_RENDERBUFFER_STENCIL_SIZE_EXT  0x8D55
+#endif
+
+#ifndef GL_GREMEDY_string_marker
+#endif
+
+
+/*************************************************************/
+
+#include <stddef.h>
+#ifndef GL_VERSION_2_0
+/* GL type for program/shader text */
+typedef char GLchar;                   /* native character */
+#endif
+
+#ifndef GL_VERSION_1_5
+/* GL types for handling large vertex buffer objects */
+typedef ptrdiff_t GLintptr;
+typedef ptrdiff_t GLsizeiptr;
+#endif
+
+#ifndef GL_ARB_vertex_buffer_object
+/* GL types for handling large vertex buffer objects */
+typedef ptrdiff_t GLintptrARB;
+typedef ptrdiff_t GLsizeiptrARB;
+#endif
+
+#ifndef GL_ARB_shader_objects
+/* GL types for handling shader object handles and program/shader text */
+typedef char GLcharARB;                /* native character */
+typedef unsigned int GLhandleARB;      /* shader object handle */
+#endif
+
+/* GL types for "half" precision (s10e5) float data in host memory */
+#ifndef GL_ARB_half_float_pixel
+typedef unsigned short GLhalfARB;
+#endif
+
+#ifndef GL_NV_half_float
+typedef unsigned short GLhalfNV;
+#endif
+
+#ifndef GL_VERSION_1_2
+#define GL_VERSION_1_2 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendColor (GLclampf, GLclampf, GLclampf, GLclampf);
+GLAPI void APIENTRY glBlendEquation (GLenum);
+GLAPI void APIENTRY glDrawRangeElements (GLenum, GLuint, GLuint, GLsizei, GLenum, const GLvoid *);
+GLAPI void APIENTRY glColorTable (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *);
+GLAPI void APIENTRY glColorTableParameterfv (GLenum, GLenum, const GLfloat *);
+GLAPI void APIENTRY glColorTableParameteriv (GLenum, GLenum, const GLint *);
+GLAPI void APIENTRY glCopyColorTable (GLenum, GLenum, GLint, GLint, GLsizei);
+GLAPI void APIENTRY glGetColorTable (GLenum, GLenum, GLenum, GLvoid *);
+GLAPI void APIENTRY glGetColorTableParameterfv (GLenum, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetColorTableParameteriv (GLenum, GLenum, GLint *);
+GLAPI void APIENTRY glColorSubTable (GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *);
+GLAPI void APIENTRY glCopyColorSubTable (GLenum, GLsizei, GLint, GLint, GLsizei);
+GLAPI void APIENTRY glConvolutionFilter1D (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *);
+GLAPI void APIENTRY glConvolutionFilter2D (GLenum, GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *);
+GLAPI void APIENTRY glConvolutionParameterf (GLenum, GLenum, GLfloat);
+GLAPI void APIENTRY glConvolutionParameterfv (GLenum, GLenum, const GLfloat *);
+GLAPI void APIENTRY glConvolutionParameteri (GLenum, GLenum, GLint);
+GLAPI void APIENTRY glConvolutionParameteriv (GLenum, GLenum, const GLint *);
+GLAPI void APIENTRY glCopyConvolutionFilter1D (GLenum, GLenum, GLint, GLint, GLsizei);
+GLAPI void APIENTRY glCopyConvolutionFilter2D (GLenum, GLenum, GLint, GLint, GLsizei, GLsizei);
+GLAPI void APIENTRY glGetConvolutionFilter (GLenum, GLenum, GLenum, GLvoid *);
+GLAPI void APIENTRY glGetConvolutionParameterfv (GLenum, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetConvolutionParameteriv (GLenum, GLenum, GLint *);
+GLAPI void APIENTRY glGetSeparableFilter (GLenum, GLenum, GLenum, GLvoid *, GLvoid *, GLvoid *);
+GLAPI void APIENTRY glSeparableFilter2D (GLenum, GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *, const GLvoid *);
+GLAPI void APIENTRY glGetHistogram (GLenum, GLboolean, GLenum, GLenum, GLvoid *);
+GLAPI void APIENTRY glGetHistogramParameterfv (GLenum, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetHistogramParameteriv (GLenum, GLenum, GLint *);
+GLAPI void APIENTRY glGetMinmax (GLenum, GLboolean, GLenum, GLenum, GLvoid *);
+GLAPI void APIENTRY glGetMinmaxParameterfv (GLenum, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetMinmaxParameteriv (GLenum, GLenum, GLint *);
+GLAPI void APIENTRY glHistogram (GLenum, GLsizei, GLenum, GLboolean);
+GLAPI void APIENTRY glMinmax (GLenum, GLenum, GLboolean);
+GLAPI void APIENTRY glResetHistogram (GLenum);
+GLAPI void APIENTRY glResetMinmax (GLenum);
+GLAPI void APIENTRY glTexImage3D (GLenum, GLint, GLint, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *);
+GLAPI void APIENTRY glTexSubImage3D (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *);
+GLAPI void APIENTRY glCopyTexSubImage3D (GLenum, GLint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLBLENDCOLORPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+typedef void (APIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode);
+typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices);
+typedef void (APIENTRYP PFNGLCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table);
+typedef void (APIENTRYP PFNGLCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLCOPYCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+typedef void (APIENTRYP PFNGLGETCOLORTABLEPROC) (GLenum target, GLenum format, GLenum type, GLvoid *table);
+typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOPYCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width);
+typedef void (APIENTRYP PFNGLCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image);
+typedef void (APIENTRYP PFNGLCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat params);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERIPROC) (GLenum target, GLenum pname, GLint params);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLCOPYCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+typedef void (APIENTRYP PFNGLCOPYCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLGETCONVOLUTIONFILTERPROC) (GLenum target, GLenum format, GLenum type, GLvoid *image);
+typedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETSEPARABLEFILTERPROC) (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span);
+typedef void (APIENTRYP PFNGLSEPARABLEFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column);
+typedef void (APIENTRYP PFNGLGETHISTOGRAMPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values);
+typedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETMINMAXPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values);
+typedef void (APIENTRYP PFNGLGETMINMAXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETMINMAXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLHISTOGRAMPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink);
+typedef void (APIENTRYP PFNGLMINMAXPROC) (GLenum target, GLenum internalformat, GLboolean sink);
+typedef void (APIENTRYP PFNGLRESETHISTOGRAMPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLRESETMINMAXPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (APIENTRYP PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+#endif
+
+#ifndef GL_VERSION_1_3
+#define GL_VERSION_1_3 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glActiveTexture (GLenum);
+GLAPI void APIENTRY glClientActiveTexture (GLenum);
+GLAPI void APIENTRY glMultiTexCoord1d (GLenum, GLdouble);
+GLAPI void APIENTRY glMultiTexCoord1dv (GLenum, const GLdouble *);
+GLAPI void APIENTRY glMultiTexCoord1f (GLenum, GLfloat);
+GLAPI void APIENTRY glMultiTexCoord1fv (GLenum, const GLfloat *);
+GLAPI void APIENTRY glMultiTexCoord1i (GLenum, GLint);
+GLAPI void APIENTRY glMultiTexCoord1iv (GLenum, const GLint *);
+GLAPI void APIENTRY glMultiTexCoord1s (GLenum, GLshort);
+GLAPI void APIENTRY glMultiTexCoord1sv (GLenum, const GLshort *);
+GLAPI void APIENTRY glMultiTexCoord2d (GLenum, GLdouble, GLdouble);
+GLAPI void APIENTRY glMultiTexCoord2dv (GLenum, const GLdouble *);
+GLAPI void APIENTRY glMultiTexCoord2f (GLenum, GLfloat, GLfloat);
+GLAPI void APIENTRY glMultiTexCoord2fv (GLenum, const GLfloat *);
+GLAPI void APIENTRY glMultiTexCoord2i (GLenum, GLint, GLint);
+GLAPI void APIENTRY glMultiTexCoord2iv (GLenum, const GLint *);
+GLAPI void APIENTRY glMultiTexCoord2s (GLenum, GLshort, GLshort);
+GLAPI void APIENTRY glMultiTexCoord2sv (GLenum, const GLshort *);
+GLAPI void APIENTRY glMultiTexCoord3d (GLenum, GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glMultiTexCoord3dv (GLenum, const GLdouble *);
+GLAPI void APIENTRY glMultiTexCoord3f (GLenum, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glMultiTexCoord3fv (GLenum, const GLfloat *);
+GLAPI void APIENTRY glMultiTexCoord3i (GLenum, GLint, GLint, GLint);
+GLAPI void APIENTRY glMultiTexCoord3iv (GLenum, const GLint *);
+GLAPI void APIENTRY glMultiTexCoord3s (GLenum, GLshort, GLshort, GLshort);
+GLAPI void APIENTRY glMultiTexCoord3sv (GLenum, const GLshort *);
+GLAPI void APIENTRY glMultiTexCoord4d (GLenum, GLdouble, GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glMultiTexCoord4dv (GLenum, const GLdouble *);
+GLAPI void APIENTRY glMultiTexCoord4f (GLenum, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glMultiTexCoord4fv (GLenum, const GLfloat *);
+GLAPI void APIENTRY glMultiTexCoord4i (GLenum, GLint, GLint, GLint, GLint);
+GLAPI void APIENTRY glMultiTexCoord4iv (GLenum, const GLint *);
+GLAPI void APIENTRY glMultiTexCoord4s (GLenum, GLshort, GLshort, GLshort, GLshort);
+GLAPI void APIENTRY glMultiTexCoord4sv (GLenum, const GLshort *);
+GLAPI void APIENTRY glLoadTransposeMatrixf (const GLfloat *);
+GLAPI void APIENTRY glLoadTransposeMatrixd (const GLdouble *);
+GLAPI void APIENTRY glMultTransposeMatrixf (const GLfloat *);
+GLAPI void APIENTRY glMultTransposeMatrixd (const GLdouble *);
+GLAPI void APIENTRY glSampleCoverage (GLclampf, GLboolean);
+GLAPI void APIENTRY glCompressedTexImage3D (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *);
+GLAPI void APIENTRY glCompressedTexImage2D (GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *);
+GLAPI void APIENTRY glCompressedTexImage1D (GLenum, GLint, GLenum, GLsizei, GLint, GLsizei, const GLvoid *);
+GLAPI void APIENTRY glCompressedTexSubImage3D (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *);
+GLAPI void APIENTRY glCompressedTexSubImage2D (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *);
+GLAPI void APIENTRY glCompressedTexSubImage1D (GLenum, GLint, GLint, GLsizei, GLenum, GLsizei, const GLvoid *);
+GLAPI void APIENTRY glGetCompressedTexImage (GLenum, GLint, GLvoid *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture);
+typedef void (APIENTRYP PFNGLCLIENTACTIVETEXTUREPROC) (GLenum texture);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1DPROC) (GLenum target, GLdouble s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1DVPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1FPROC) (GLenum target, GLfloat s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1FVPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1IPROC) (GLenum target, GLint s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1IVPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1SPROC) (GLenum target, GLshort s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1SVPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2DPROC) (GLenum target, GLdouble s, GLdouble t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2DVPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2FPROC) (GLenum target, GLfloat s, GLfloat t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2FVPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2IPROC) (GLenum target, GLint s, GLint t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2IVPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2SPROC) (GLenum target, GLshort s, GLshort t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2SVPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3DPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3DVPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3FVPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3IPROC) (GLenum target, GLint s, GLint t, GLint r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3IVPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3SPROC) (GLenum target, GLshort s, GLshort t, GLshort r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3SVPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4DPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4DVPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4FVPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4IPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4IVPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4SPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4SVPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXFPROC) (const GLfloat *m);
+typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXDPROC) (const GLdouble *m);
+typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXFPROC) (const GLfloat *m);
+typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXDPROC) (const GLdouble *m);
+typedef void (APIENTRYP PFNGLSAMPLECOVERAGEPROC) (GLclampf value, GLboolean invert);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE1DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXIMAGEPROC) (GLenum target, GLint level, GLvoid *img);
+#endif
+
+#ifndef GL_VERSION_1_4
+#define GL_VERSION_1_4 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendFuncSeparate (GLenum, GLenum, GLenum, GLenum);
+GLAPI void APIENTRY glFogCoordf (GLfloat);
+GLAPI void APIENTRY glFogCoordfv (const GLfloat *);
+GLAPI void APIENTRY glFogCoordd (GLdouble);
+GLAPI void APIENTRY glFogCoorddv (const GLdouble *);
+GLAPI void APIENTRY glFogCoordPointer (GLenum, GLsizei, const GLvoid *);
+GLAPI void APIENTRY glMultiDrawArrays (GLenum, GLint *, GLsizei *, GLsizei);
+GLAPI void APIENTRY glMultiDrawElements (GLenum, const GLsizei *, GLenum, const GLvoid* *, GLsizei);
+GLAPI void APIENTRY glPointParameterf (GLenum, GLfloat);
+GLAPI void APIENTRY glPointParameterfv (GLenum, const GLfloat *);
+GLAPI void APIENTRY glPointParameteri (GLenum, GLint);
+GLAPI void APIENTRY glPointParameteriv (GLenum, const GLint *);
+GLAPI void APIENTRY glSecondaryColor3b (GLbyte, GLbyte, GLbyte);
+GLAPI void APIENTRY glSecondaryColor3bv (const GLbyte *);
+GLAPI void APIENTRY glSecondaryColor3d (GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glSecondaryColor3dv (const GLdouble *);
+GLAPI void APIENTRY glSecondaryColor3f (GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glSecondaryColor3fv (const GLfloat *);
+GLAPI void APIENTRY glSecondaryColor3i (GLint, GLint, GLint);
+GLAPI void APIENTRY glSecondaryColor3iv (const GLint *);
+GLAPI void APIENTRY glSecondaryColor3s (GLshort, GLshort, GLshort);
+GLAPI void APIENTRY glSecondaryColor3sv (const GLshort *);
+GLAPI void APIENTRY glSecondaryColor3ub (GLubyte, GLubyte, GLubyte);
+GLAPI void APIENTRY glSecondaryColor3ubv (const GLubyte *);
+GLAPI void APIENTRY glSecondaryColor3ui (GLuint, GLuint, GLuint);
+GLAPI void APIENTRY glSecondaryColor3uiv (const GLuint *);
+GLAPI void APIENTRY glSecondaryColor3us (GLushort, GLushort, GLushort);
+GLAPI void APIENTRY glSecondaryColor3usv (const GLushort *);
+GLAPI void APIENTRY glSecondaryColorPointer (GLint, GLenum, GLsizei, const GLvoid *);
+GLAPI void APIENTRY glWindowPos2d (GLdouble, GLdouble);
+GLAPI void APIENTRY glWindowPos2dv (const GLdouble *);
+GLAPI void APIENTRY glWindowPos2f (GLfloat, GLfloat);
+GLAPI void APIENTRY glWindowPos2fv (const GLfloat *);
+GLAPI void APIENTRY glWindowPos2i (GLint, GLint);
+GLAPI void APIENTRY glWindowPos2iv (const GLint *);
+GLAPI void APIENTRY glWindowPos2s (GLshort, GLshort);
+GLAPI void APIENTRY glWindowPos2sv (const GLshort *);
+GLAPI void APIENTRY glWindowPos3d (GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glWindowPos3dv (const GLdouble *);
+GLAPI void APIENTRY glWindowPos3f (GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glWindowPos3fv (const GLfloat *);
+GLAPI void APIENTRY glWindowPos3i (GLint, GLint, GLint);
+GLAPI void APIENTRY glWindowPos3iv (const GLint *);
+GLAPI void APIENTRY glWindowPos3s (GLshort, GLshort, GLshort);
+GLAPI void APIENTRY glWindowPos3sv (const GLshort *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+typedef void (APIENTRYP PFNGLFOGCOORDFPROC) (GLfloat coord);
+typedef void (APIENTRYP PFNGLFOGCOORDFVPROC) (const GLfloat *coord);
+typedef void (APIENTRYP PFNGLFOGCOORDDPROC) (GLdouble coord);
+typedef void (APIENTRYP PFNGLFOGCOORDDVPROC) (const GLdouble *coord);
+typedef void (APIENTRYP PFNGLFOGCOORDPOINTERPROC) (GLenum type, GLsizei stride, const GLvoid *pointer);
+typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSPROC) (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount);
+typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFVPROC) (GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERIPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERIVPROC) (GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3BPROC) (GLbyte red, GLbyte green, GLbyte blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3BVPROC) (const GLbyte *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3DPROC) (GLdouble red, GLdouble green, GLdouble blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3DVPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3FPROC) (GLfloat red, GLfloat green, GLfloat blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3FVPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3IPROC) (GLint red, GLint green, GLint blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3IVPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3SPROC) (GLshort red, GLshort green, GLshort blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3SVPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBPROC) (GLubyte red, GLubyte green, GLubyte blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBVPROC) (const GLubyte *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIPROC) (GLuint red, GLuint green, GLuint blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIVPROC) (const GLuint *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3USPROC) (GLushort red, GLushort green, GLushort blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3USVPROC) (const GLushort *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLORPOINTERPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+typedef void (APIENTRYP PFNGLWINDOWPOS2DPROC) (GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2DVPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2FPROC) (GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2FVPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2IPROC) (GLint x, GLint y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2IVPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2SPROC) (GLshort x, GLshort y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2SVPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3DPROC) (GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3DVPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3FPROC) (GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3FVPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3IPROC) (GLint x, GLint y, GLint z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3IVPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3SPROC) (GLshort x, GLshort y, GLshort z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3SVPROC) (const GLshort *v);
+#endif
+
+#ifndef GL_VERSION_1_5
+#define GL_VERSION_1_5 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGenQueries (GLsizei, GLuint *);
+GLAPI void APIENTRY glDeleteQueries (GLsizei, const GLuint *);
+GLAPI GLboolean APIENTRY glIsQuery (GLuint);
+GLAPI void APIENTRY glBeginQuery (GLenum, GLuint);
+GLAPI void APIENTRY glEndQuery (GLenum);
+GLAPI void APIENTRY glGetQueryiv (GLenum, GLenum, GLint *);
+GLAPI void APIENTRY glGetQueryObjectiv (GLuint, GLenum, GLint *);
+GLAPI void APIENTRY glGetQueryObjectuiv (GLuint, GLenum, GLuint *);
+GLAPI void APIENTRY glBindBuffer (GLenum, GLuint);
+GLAPI void APIENTRY glDeleteBuffers (GLsizei, const GLuint *);
+GLAPI void APIENTRY glGenBuffers (GLsizei, GLuint *);
+GLAPI GLboolean APIENTRY glIsBuffer (GLuint);
+GLAPI void APIENTRY glBufferData (GLenum, GLsizeiptr, const GLvoid *, GLenum);
+GLAPI void APIENTRY glBufferSubData (GLenum, GLintptr, GLsizeiptr, const GLvoid *);
+GLAPI void APIENTRY glGetBufferSubData (GLenum, GLintptr, GLsizeiptr, GLvoid *);
+GLAPI GLvoid* APIENTRY glMapBuffer (GLenum, GLenum);
+GLAPI GLboolean APIENTRY glUnmapBuffer (GLenum);
+GLAPI void APIENTRY glGetBufferParameteriv (GLenum, GLenum, GLint *);
+GLAPI void APIENTRY glGetBufferPointerv (GLenum, GLenum, GLvoid* *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLGENQUERIESPROC) (GLsizei n, GLuint *ids);
+typedef void (APIENTRYP PFNGLDELETEQUERIESPROC) (GLsizei n, const GLuint *ids);
+typedef GLboolean (APIENTRYP PFNGLISQUERYPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLBEGINQUERYPROC) (GLenum target, GLuint id);
+typedef void (APIENTRYP PFNGLENDQUERYPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLGETQUERYIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTIVPROC) (GLuint id, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTUIVPROC) (GLuint id, GLenum pname, GLuint *params);
+typedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
+typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers);
+typedef void (APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);
+typedef GLboolean (APIENTRYP PFNGLISBUFFERPROC) (GLuint buffer);
+typedef void (APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage);
+typedef void (APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data);
+typedef void (APIENTRYP PFNGLGETBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, GLvoid *data);
+typedef GLvoid* (APIENTRYP PFNGLMAPBUFFERPROC) (GLenum target, GLenum access);
+typedef GLboolean (APIENTRYP PFNGLUNMAPBUFFERPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETBUFFERPOINTERVPROC) (GLenum target, GLenum pname, GLvoid* *params);
+#endif
+
+#ifndef GL_VERSION_2_0
+#define GL_VERSION_2_0 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendEquationSeparate (GLenum, GLenum);
+GLAPI void APIENTRY glDrawBuffers (GLsizei, const GLenum *);
+GLAPI void APIENTRY glStencilOpSeparate (GLenum, GLenum, GLenum, GLenum);
+GLAPI void APIENTRY glStencilFuncSeparate (GLenum, GLenum, GLint, GLuint);
+GLAPI void APIENTRY glStencilMaskSeparate (GLenum, GLuint);
+GLAPI void APIENTRY glAttachShader (GLuint, GLuint);
+GLAPI void APIENTRY glBindAttribLocation (GLuint, GLuint, const GLchar *);
+GLAPI void APIENTRY glCompileShader (GLuint);
+GLAPI GLuint APIENTRY glCreateProgram (void);
+GLAPI GLuint APIENTRY glCreateShader (GLenum);
+GLAPI void APIENTRY glDeleteProgram (GLuint);
+GLAPI void APIENTRY glDeleteShader (GLuint);
+GLAPI void APIENTRY glDetachShader (GLuint, GLuint);
+GLAPI void APIENTRY glDisableVertexAttribArray (GLuint);
+GLAPI void APIENTRY glEnableVertexAttribArray (GLuint);
+GLAPI void APIENTRY glGetActiveAttrib (GLuint, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLchar *);
+GLAPI void APIENTRY glGetActiveUniform (GLuint, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLchar *);
+GLAPI void APIENTRY glGetAttachedShaders (GLuint, GLsizei, GLsizei *, GLuint *);
+GLAPI GLint APIENTRY glGetAttribLocation (GLuint, const GLchar *);
+GLAPI void APIENTRY glGetProgramiv (GLuint, GLenum, GLint *);
+GLAPI void APIENTRY glGetProgramInfoLog (GLuint, GLsizei, GLsizei *, GLchar *);
+GLAPI void APIENTRY glGetShaderiv (GLuint, GLenum, GLint *);
+GLAPI void APIENTRY glGetShaderInfoLog (GLuint, GLsizei, GLsizei *, GLchar *);
+GLAPI void APIENTRY glGetShaderSource (GLuint, GLsizei, GLsizei *, GLchar *);
+GLAPI GLint APIENTRY glGetUniformLocation (GLuint, const GLchar *);
+GLAPI void APIENTRY glGetUniformfv (GLuint, GLint, GLfloat *);
+GLAPI void APIENTRY glGetUniformiv (GLuint, GLint, GLint *);
+GLAPI void APIENTRY glGetVertexAttribdv (GLuint, GLenum, GLdouble *);
+GLAPI void APIENTRY glGetVertexAttribfv (GLuint, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetVertexAttribiv (GLuint, GLenum, GLint *);
+GLAPI void APIENTRY glGetVertexAttribPointerv (GLuint, GLenum, GLvoid* *);
+GLAPI GLboolean APIENTRY glIsProgram (GLuint);
+GLAPI GLboolean APIENTRY glIsShader (GLuint);
+GLAPI void APIENTRY glLinkProgram (GLuint);
+GLAPI void APIENTRY glShaderSource (GLuint, GLsizei, const GLchar* *, const GLint *);
+GLAPI void APIENTRY glUseProgram (GLuint);
+GLAPI void APIENTRY glUniform1f (GLint, GLfloat);
+GLAPI void APIENTRY glUniform2f (GLint, GLfloat, GLfloat);
+GLAPI void APIENTRY glUniform3f (GLint, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glUniform4f (GLint, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glUniform1i (GLint, GLint);
+GLAPI void APIENTRY glUniform2i (GLint, GLint, GLint);
+GLAPI void APIENTRY glUniform3i (GLint, GLint, GLint, GLint);
+GLAPI void APIENTRY glUniform4i (GLint, GLint, GLint, GLint, GLint);
+GLAPI void APIENTRY glUniform1fv (GLint, GLsizei, const GLfloat *);
+GLAPI void APIENTRY glUniform2fv (GLint, GLsizei, const GLfloat *);
+GLAPI void APIENTRY glUniform3fv (GLint, GLsizei, const GLfloat *);
+GLAPI void APIENTRY glUniform4fv (GLint, GLsizei, const GLfloat *);
+GLAPI void APIENTRY glUniform1iv (GLint, GLsizei, const GLint *);
+GLAPI void APIENTRY glUniform2iv (GLint, GLsizei, const GLint *);
+GLAPI void APIENTRY glUniform3iv (GLint, GLsizei, const GLint *);
+GLAPI void APIENTRY glUniform4iv (GLint, GLsizei, const GLint *);
+GLAPI void APIENTRY glUniformMatrix2fv (GLint, GLsizei, GLboolean, const GLfloat *);
+GLAPI void APIENTRY glUniformMatrix3fv (GLint, GLsizei, GLboolean, const GLfloat *);
+GLAPI void APIENTRY glUniformMatrix4fv (GLint, GLsizei, GLboolean, const GLfloat *);
+GLAPI void APIENTRY glValidateProgram (GLuint);
+GLAPI void APIENTRY glVertexAttrib1d (GLuint, GLdouble);
+GLAPI void APIENTRY glVertexAttrib1dv (GLuint, const GLdouble *);
+GLAPI void APIENTRY glVertexAttrib1f (GLuint, GLfloat);
+GLAPI void APIENTRY glVertexAttrib1fv (GLuint, const GLfloat *);
+GLAPI void APIENTRY glVertexAttrib1s (GLuint, GLshort);
+GLAPI void APIENTRY glVertexAttrib1sv (GLuint, const GLshort *);
+GLAPI void APIENTRY glVertexAttrib2d (GLuint, GLdouble, GLdouble);
+GLAPI void APIENTRY glVertexAttrib2dv (GLuint, const GLdouble *);
+GLAPI void APIENTRY glVertexAttrib2f (GLuint, GLfloat, GLfloat);
+GLAPI void APIENTRY glVertexAttrib2fv (GLuint, const GLfloat *);
+GLAPI void APIENTRY glVertexAttrib2s (GLuint, GLshort, GLshort);
+GLAPI void APIENTRY glVertexAttrib2sv (GLuint, const GLshort *);
+GLAPI void APIENTRY glVertexAttrib3d (GLuint, GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glVertexAttrib3dv (GLuint, const GLdouble *);
+GLAPI void APIENTRY glVertexAttrib3f (GLuint, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glVertexAttrib3fv (GLuint, const GLfloat *);
+GLAPI void APIENTRY glVertexAttrib3s (GLuint, GLshort, GLshort, GLshort);
+GLAPI void APIENTRY glVertexAttrib3sv (GLuint, const GLshort *);
+GLAPI void APIENTRY glVertexAttrib4Nbv (GLuint, const GLbyte *);
+GLAPI void APIENTRY glVertexAttrib4Niv (GLuint, const GLint *);
+GLAPI void APIENTRY glVertexAttrib4Nsv (GLuint, const GLshort *);
+GLAPI void APIENTRY glVertexAttrib4Nub (GLuint, GLubyte, GLubyte, GLubyte, GLubyte);
+GLAPI void APIENTRY glVertexAttrib4Nubv (GLuint, const GLubyte *);
+GLAPI void APIENTRY glVertexAttrib4Nuiv (GLuint, const GLuint *);
+GLAPI void APIENTRY glVertexAttrib4Nusv (GLuint, const GLushort *);
+GLAPI void APIENTRY glVertexAttrib4bv (GLuint, const GLbyte *);
+GLAPI void APIENTRY glVertexAttrib4d (GLuint, GLdouble, GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glVertexAttrib4dv (GLuint, const GLdouble *);
+GLAPI void APIENTRY glVertexAttrib4f (GLuint, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glVertexAttrib4fv (GLuint, const GLfloat *);
+GLAPI void APIENTRY glVertexAttrib4iv (GLuint, const GLint *);
+GLAPI void APIENTRY glVertexAttrib4s (GLuint, GLshort, GLshort, GLshort, GLshort);
+GLAPI void APIENTRY glVertexAttrib4sv (GLuint, const GLshort *);
+GLAPI void APIENTRY glVertexAttrib4ubv (GLuint, const GLubyte *);
+GLAPI void APIENTRY glVertexAttrib4uiv (GLuint, const GLuint *);
+GLAPI void APIENTRY glVertexAttrib4usv (GLuint, const GLushort *);
+GLAPI void APIENTRY glVertexAttribPointer (GLuint, GLint, GLenum, GLboolean, GLsizei, const GLvoid *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha);
+typedef void (APIENTRYP PFNGLDRAWBUFFERSPROC) (GLsizei n, const GLenum *bufs);
+typedef void (APIENTRYP PFNGLSTENCILOPSEPARATEPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+typedef void (APIENTRYP PFNGLSTENCILFUNCSEPARATEPROC) (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask);
+typedef void (APIENTRYP PFNGLSTENCILMASKSEPARATEPROC) (GLenum face, GLuint mask);
+typedef void (APIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
+typedef void (APIENTRYP PFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar *name);
+typedef void (APIENTRYP PFNGLCOMPILESHADERPROC) (GLuint shader);
+typedef GLuint (APIENTRYP PFNGLCREATEPROGRAMPROC) (void);
+typedef GLuint (APIENTRYP PFNGLCREATESHADERPROC) (GLenum type);
+typedef void (APIENTRYP PFNGLDELETEPROGRAMPROC) (GLuint program);
+typedef void (APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader);
+typedef void (APIENTRYP PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader);
+typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index);
+typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index);
+typedef void (APIENTRYP PFNGLGETACTIVEATTRIBPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+typedef void (APIENTRYP PFNGLGETATTACHEDSHADERSPROC) (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *obj);
+typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (APIENTRYP PFNGLGETSHADERSOURCEPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source);
+typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (APIENTRYP PFNGLGETUNIFORMFVPROC) (GLuint program, GLint location, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETUNIFORMIVPROC) (GLuint program, GLint location, GLint *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBDVPROC) (GLuint index, GLenum pname, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBFVPROC) (GLuint index, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint index, GLenum pname, GLvoid* *pointer);
+typedef GLboolean (APIENTRYP PFNGLISPROGRAMPROC) (GLuint program);
+typedef GLboolean (APIENTRYP PFNGLISSHADERPROC) (GLuint shader);
+typedef void (APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program);
+typedef void (APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar* *string, const GLint *length);
+typedef void (APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program);
+typedef void (APIENTRYP PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0);
+typedef void (APIENTRYP PFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1);
+typedef void (APIENTRYP PFNGLUNIFORM3FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (APIENTRYP PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (APIENTRYP PFNGLUNIFORM1IPROC) (GLint location, GLint v0);
+typedef void (APIENTRYP PFNGLUNIFORM2IPROC) (GLint location, GLint v0, GLint v1);
+typedef void (APIENTRYP PFNGLUNIFORM3IPROC) (GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (APIENTRYP PFNGLUNIFORM4IPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (APIENTRYP PFNGLUNIFORM1FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM2FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM3FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM4FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM1IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORM2IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORM3IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORM4IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLVALIDATEPROGRAMPROC) (GLuint program);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1DPROC) (GLuint index, GLdouble x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1DVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1FPROC) (GLuint index, GLfloat x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1FVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1SPROC) (GLuint index, GLshort x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1SVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2DPROC) (GLuint index, GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2DVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2FPROC) (GLuint index, GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2FVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2SPROC) (GLuint index, GLshort x, GLshort y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2SVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3DVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3FVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3SPROC) (GLuint index, GLshort x, GLshort y, GLshort z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3SVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NBVPROC) (GLuint index, const GLbyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NIVPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NSVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBVPROC) (GLuint index, const GLubyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUIVPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUSVPROC) (GLuint index, const GLushort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4BVPROC) (GLuint index, const GLbyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4DVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4IVPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4SPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4SVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4UBVPROC) (GLuint index, const GLubyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4UIVPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4USVPROC) (GLuint index, const GLushort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer);
+#endif
+
+#ifndef GL_ARB_multitexture
+#define GL_ARB_multitexture 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glActiveTextureARB (GLenum);
+GLAPI void APIENTRY glClientActiveTextureARB (GLenum);
+GLAPI void APIENTRY glMultiTexCoord1dARB (GLenum, GLdouble);
+GLAPI void APIENTRY glMultiTexCoord1dvARB (GLenum, const GLdouble *);
+GLAPI void APIENTRY glMultiTexCoord1fARB (GLenum, GLfloat);
+GLAPI void APIENTRY glMultiTexCoord1fvARB (GLenum, const GLfloat *);
+GLAPI void APIENTRY glMultiTexCoord1iARB (GLenum, GLint);
+GLAPI void APIENTRY glMultiTexCoord1ivARB (GLenum, const GLint *);
+GLAPI void APIENTRY glMultiTexCoord1sARB (GLenum, GLshort);
+GLAPI void APIENTRY glMultiTexCoord1svARB (GLenum, const GLshort *);
+GLAPI void APIENTRY glMultiTexCoord2dARB (GLenum, GLdouble, GLdouble);
+GLAPI void APIENTRY glMultiTexCoord2dvARB (GLenum, const GLdouble *);
+GLAPI void APIENTRY glMultiTexCoord2fARB (GLenum, GLfloat, GLfloat);
+GLAPI void APIENTRY glMultiTexCoord2fvARB (GLenum, const GLfloat *);
+GLAPI void APIENTRY glMultiTexCoord2iARB (GLenum, GLint, GLint);
+GLAPI void APIENTRY glMultiTexCoord2ivARB (GLenum, const GLint *);
+GLAPI void APIENTRY glMultiTexCoord2sARB (GLenum, GLshort, GLshort);
+GLAPI void APIENTRY glMultiTexCoord2svARB (GLenum, const GLshort *);
+GLAPI void APIENTRY glMultiTexCoord3dARB (GLenum, GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glMultiTexCoord3dvARB (GLenum, const GLdouble *);
+GLAPI void APIENTRY glMultiTexCoord3fARB (GLenum, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glMultiTexCoord3fvARB (GLenum, const GLfloat *);
+GLAPI void APIENTRY glMultiTexCoord3iARB (GLenum, GLint, GLint, GLint);
+GLAPI void APIENTRY glMultiTexCoord3ivARB (GLenum, const GLint *);
+GLAPI void APIENTRY glMultiTexCoord3sARB (GLenum, GLshort, GLshort, GLshort);
+GLAPI void APIENTRY glMultiTexCoord3svARB (GLenum, const GLshort *);
+GLAPI void APIENTRY glMultiTexCoord4dARB (GLenum, GLdouble, GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glMultiTexCoord4dvARB (GLenum, const GLdouble *);
+GLAPI void APIENTRY glMultiTexCoord4fARB (GLenum, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glMultiTexCoord4fvARB (GLenum, const GLfloat *);
+GLAPI void APIENTRY glMultiTexCoord4iARB (GLenum, GLint, GLint, GLint, GLint);
+GLAPI void APIENTRY glMultiTexCoord4ivARB (GLenum, const GLint *);
+GLAPI void APIENTRY glMultiTexCoord4sARB (GLenum, GLshort, GLshort, GLshort, GLshort);
+GLAPI void APIENTRY glMultiTexCoord4svARB (GLenum, const GLshort *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLACTIVETEXTUREARBPROC) (GLenum texture);
+typedef void (APIENTRYP PFNGLCLIENTACTIVETEXTUREARBPROC) (GLenum texture);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1DARBPROC) (GLenum target, GLdouble s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1FARBPROC) (GLenum target, GLfloat s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1IARBPROC) (GLenum target, GLint s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1IVARBPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1SARBPROC) (GLenum target, GLshort s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1SVARBPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2DARBPROC) (GLenum target, GLdouble s, GLdouble t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2FARBPROC) (GLenum target, GLfloat s, GLfloat t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2IARBPROC) (GLenum target, GLint s, GLint t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2IVARBPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2SARBPROC) (GLenum target, GLshort s, GLshort t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2SVARBPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3IARBPROC) (GLenum target, GLint s, GLint t, GLint r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3IVARBPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3SVARBPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4IARBPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4IVARBPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4SVARBPROC) (GLenum target, const GLshort *v);
+#endif
+
+#ifndef GL_ARB_transpose_matrix
+#define GL_ARB_transpose_matrix 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glLoadTransposeMatrixfARB (const GLfloat *);
+GLAPI void APIENTRY glLoadTransposeMatrixdARB (const GLdouble *);
+GLAPI void APIENTRY glMultTransposeMatrixfARB (const GLfloat *);
+GLAPI void APIENTRY glMultTransposeMatrixdARB (const GLdouble *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXFARBPROC) (const GLfloat *m);
+typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXDARBPROC) (const GLdouble *m);
+typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXFARBPROC) (const GLfloat *m);
+typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXDARBPROC) (const GLdouble *m);
+#endif
+
+#ifndef GL_ARB_multisample
+#define GL_ARB_multisample 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glSampleCoverageARB (GLclampf, GLboolean);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLSAMPLECOVERAGEARBPROC) (GLclampf value, GLboolean invert);
+#endif
+
+#ifndef GL_ARB_texture_env_add
+#define GL_ARB_texture_env_add 1
+#endif
+
+#ifndef GL_ARB_texture_cube_map
+#define GL_ARB_texture_cube_map 1
+#endif
+
+#ifndef GL_ARB_texture_compression
+#define GL_ARB_texture_compression 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glCompressedTexImage3DARB (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *);
+GLAPI void APIENTRY glCompressedTexImage2DARB (GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *);
+GLAPI void APIENTRY glCompressedTexImage1DARB (GLenum, GLint, GLenum, GLsizei, GLint, GLsizei, const GLvoid *);
+GLAPI void APIENTRY glCompressedTexSubImage3DARB (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *);
+GLAPI void APIENTRY glCompressedTexSubImage2DARB (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *);
+GLAPI void APIENTRY glCompressedTexSubImage1DARB (GLenum, GLint, GLint, GLsizei, GLenum, GLsizei, const GLvoid *);
+GLAPI void APIENTRY glGetCompressedTexImageARB (GLenum, GLint, GLvoid *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE1DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint level, GLvoid *img);
+#endif
+
+#ifndef GL_ARB_texture_border_clamp
+#define GL_ARB_texture_border_clamp 1
+#endif
+
+#ifndef GL_ARB_point_parameters
+#define GL_ARB_point_parameters 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPointParameterfARB (GLenum, GLfloat);
+GLAPI void APIENTRY glPointParameterfvARB (GLenum, const GLfloat *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFARBPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFVARBPROC) (GLenum pname, const GLfloat *params);
+#endif
+
+#ifndef GL_ARB_vertex_blend
+#define GL_ARB_vertex_blend 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glWeightbvARB (GLint, const GLbyte *);
+GLAPI void APIENTRY glWeightsvARB (GLint, const GLshort *);
+GLAPI void APIENTRY glWeightivARB (GLint, const GLint *);
+GLAPI void APIENTRY glWeightfvARB (GLint, const GLfloat *);
+GLAPI void APIENTRY glWeightdvARB (GLint, const GLdouble *);
+GLAPI void APIENTRY glWeightubvARB (GLint, const GLubyte *);
+GLAPI void APIENTRY glWeightusvARB (GLint, const GLushort *);
+GLAPI void APIENTRY glWeightuivARB (GLint, const GLuint *);
+GLAPI void APIENTRY glWeightPointerARB (GLint, GLenum, GLsizei, const GLvoid *);
+GLAPI void APIENTRY glVertexBlendARB (GLint);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLWEIGHTBVARBPROC) (GLint size, const GLbyte *weights);
+typedef void (APIENTRYP PFNGLWEIGHTSVARBPROC) (GLint size, const GLshort *weights);
+typedef void (APIENTRYP PFNGLWEIGHTIVARBPROC) (GLint size, const GLint *weights);
+typedef void (APIENTRYP PFNGLWEIGHTFVARBPROC) (GLint size, const GLfloat *weights);
+typedef void (APIENTRYP PFNGLWEIGHTDVARBPROC) (GLint size, const GLdouble *weights);
+typedef void (APIENTRYP PFNGLWEIGHTUBVARBPROC) (GLint size, const GLubyte *weights);
+typedef void (APIENTRYP PFNGLWEIGHTUSVARBPROC) (GLint size, const GLushort *weights);
+typedef void (APIENTRYP PFNGLWEIGHTUIVARBPROC) (GLint size, const GLuint *weights);
+typedef void (APIENTRYP PFNGLWEIGHTPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+typedef void (APIENTRYP PFNGLVERTEXBLENDARBPROC) (GLint count);
+#endif
+
+#ifndef GL_ARB_matrix_palette
+#define GL_ARB_matrix_palette 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glCurrentPaletteMatrixARB (GLint);
+GLAPI void APIENTRY glMatrixIndexubvARB (GLint, const GLubyte *);
+GLAPI void APIENTRY glMatrixIndexusvARB (GLint, const GLushort *);
+GLAPI void APIENTRY glMatrixIndexuivARB (GLint, const GLuint *);
+GLAPI void APIENTRY glMatrixIndexPointerARB (GLint, GLenum, GLsizei, const GLvoid *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLCURRENTPALETTEMATRIXARBPROC) (GLint index);
+typedef void (APIENTRYP PFNGLMATRIXINDEXUBVARBPROC) (GLint size, const GLubyte *indices);
+typedef void (APIENTRYP PFNGLMATRIXINDEXUSVARBPROC) (GLint size, const GLushort *indices);
+typedef void (APIENTRYP PFNGLMATRIXINDEXUIVARBPROC) (GLint size, const GLuint *indices);
+typedef void (APIENTRYP PFNGLMATRIXINDEXPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+#endif
+
+#ifndef GL_ARB_texture_env_combine
+#define GL_ARB_texture_env_combine 1
+#endif
+
+#ifndef GL_ARB_texture_env_crossbar
+#define GL_ARB_texture_env_crossbar 1
+#endif
+
+#ifndef GL_ARB_texture_env_dot3
+#define GL_ARB_texture_env_dot3 1
+#endif
+
+#ifndef GL_ARB_texture_mirrored_repeat
+#define GL_ARB_texture_mirrored_repeat 1
+#endif
+
+#ifndef GL_ARB_depth_texture
+#define GL_ARB_depth_texture 1
+#endif
+
+#ifndef GL_ARB_shadow
+#define GL_ARB_shadow 1
+#endif
+
+#ifndef GL_ARB_shadow_ambient
+#define GL_ARB_shadow_ambient 1
+#endif
+
+#ifndef GL_ARB_window_pos
+#define GL_ARB_window_pos 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glWindowPos2dARB (GLdouble, GLdouble);
+GLAPI void APIENTRY glWindowPos2dvARB (const GLdouble *);
+GLAPI void APIENTRY glWindowPos2fARB (GLfloat, GLfloat);
+GLAPI void APIENTRY glWindowPos2fvARB (const GLfloat *);
+GLAPI void APIENTRY glWindowPos2iARB (GLint, GLint);
+GLAPI void APIENTRY glWindowPos2ivARB (const GLint *);
+GLAPI void APIENTRY glWindowPos2sARB (GLshort, GLshort);
+GLAPI void APIENTRY glWindowPos2svARB (const GLshort *);
+GLAPI void APIENTRY glWindowPos3dARB (GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glWindowPos3dvARB (const GLdouble *);
+GLAPI void APIENTRY glWindowPos3fARB (GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glWindowPos3fvARB (const GLfloat *);
+GLAPI void APIENTRY glWindowPos3iARB (GLint, GLint, GLint);
+GLAPI void APIENTRY glWindowPos3ivARB (const GLint *);
+GLAPI void APIENTRY glWindowPos3sARB (GLshort, GLshort, GLshort);
+GLAPI void APIENTRY glWindowPos3svARB (const GLshort *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLWINDOWPOS2DARBPROC) (GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2DVARBPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2FARBPROC) (GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2FVARBPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2IARBPROC) (GLint x, GLint y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2IVARBPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2SARBPROC) (GLshort x, GLshort y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2SVARBPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3DARBPROC) (GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3DVARBPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3FARBPROC) (GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3FVARBPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3IARBPROC) (GLint x, GLint y, GLint z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3IVARBPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3SARBPROC) (GLshort x, GLshort y, GLshort z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3SVARBPROC) (const GLshort *v);
+#endif
+
+#ifndef GL_ARB_vertex_program
+#define GL_ARB_vertex_program 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexAttrib1dARB (GLuint, GLdouble);
+GLAPI void APIENTRY glVertexAttrib1dvARB (GLuint, const GLdouble *);
+GLAPI void APIENTRY glVertexAttrib1fARB (GLuint, GLfloat);
+GLAPI void APIENTRY glVertexAttrib1fvARB (GLuint, const GLfloat *);
+GLAPI void APIENTRY glVertexAttrib1sARB (GLuint, GLshort);
+GLAPI void APIENTRY glVertexAttrib1svARB (GLuint, const GLshort *);
+GLAPI void APIENTRY glVertexAttrib2dARB (GLuint, GLdouble, GLdouble);
+GLAPI void APIENTRY glVertexAttrib2dvARB (GLuint, const GLdouble *);
+GLAPI void APIENTRY glVertexAttrib2fARB (GLuint, GLfloat, GLfloat);
+GLAPI void APIENTRY glVertexAttrib2fvARB (GLuint, const GLfloat *);
+GLAPI void APIENTRY glVertexAttrib2sARB (GLuint, GLshort, GLshort);
+GLAPI void APIENTRY glVertexAttrib2svARB (GLuint, const GLshort *);
+GLAPI void APIENTRY glVertexAttrib3dARB (GLuint, GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glVertexAttrib3dvARB (GLuint, const GLdouble *);
+GLAPI void APIENTRY glVertexAttrib3fARB (GLuint, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glVertexAttrib3fvARB (GLuint, const GLfloat *);
+GLAPI void APIENTRY glVertexAttrib3sARB (GLuint, GLshort, GLshort, GLshort);
+GLAPI void APIENTRY glVertexAttrib3svARB (GLuint, const GLshort *);
+GLAPI void APIENTRY glVertexAttrib4NbvARB (GLuint, const GLbyte *);
+GLAPI void APIENTRY glVertexAttrib4NivARB (GLuint, const GLint *);
+GLAPI void APIENTRY glVertexAttrib4NsvARB (GLuint, const GLshort *);
+GLAPI void APIENTRY glVertexAttrib4NubARB (GLuint, GLubyte, GLubyte, GLubyte, GLubyte);
+GLAPI void APIENTRY glVertexAttrib4NubvARB (GLuint, const GLubyte *);
+GLAPI void APIENTRY glVertexAttrib4NuivARB (GLuint, const GLuint *);
+GLAPI void APIENTRY glVertexAttrib4NusvARB (GLuint, const GLushort *);
+GLAPI void APIENTRY glVertexAttrib4bvARB (GLuint, const GLbyte *);
+GLAPI void APIENTRY glVertexAttrib4dARB (GLuint, GLdouble, GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glVertexAttrib4dvARB (GLuint, const GLdouble *);
+GLAPI void APIENTRY glVertexAttrib4fARB (GLuint, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glVertexAttrib4fvARB (GLuint, const GLfloat *);
+GLAPI void APIENTRY glVertexAttrib4ivARB (GLuint, const GLint *);
+GLAPI void APIENTRY glVertexAttrib4sARB (GLuint, GLshort, GLshort, GLshort, GLshort);
+GLAPI void APIENTRY glVertexAttrib4svARB (GLuint, const GLshort *);
+GLAPI void APIENTRY glVertexAttrib4ubvARB (GLuint, const GLubyte *);
+GLAPI void APIENTRY glVertexAttrib4uivARB (GLuint, const GLuint *);
+GLAPI void APIENTRY glVertexAttrib4usvARB (GLuint, const GLushort *);
+GLAPI void APIENTRY glVertexAttribPointerARB (GLuint, GLint, GLenum, GLboolean, GLsizei, const GLvoid *);
+GLAPI void APIENTRY glEnableVertexAttribArrayARB (GLuint);
+GLAPI void APIENTRY glDisableVertexAttribArrayARB (GLuint);
+GLAPI void APIENTRY glProgramStringARB (GLenum, GLenum, GLsizei, const GLvoid *);
+GLAPI void APIENTRY glBindProgramARB (GLenum, GLuint);
+GLAPI void APIENTRY glDeleteProgramsARB (GLsizei, const GLuint *);
+GLAPI void APIENTRY glGenProgramsARB (GLsizei, GLuint *);
+GLAPI void APIENTRY glProgramEnvParameter4dARB (GLenum, GLuint, GLdouble, GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glProgramEnvParameter4dvARB (GLenum, GLuint, const GLdouble *);
+GLAPI void APIENTRY glProgramEnvParameter4fARB (GLenum, GLuint, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glProgramEnvParameter4fvARB (GLenum, GLuint, const GLfloat *);
+GLAPI void APIENTRY glProgramLocalParameter4dARB (GLenum, GLuint, GLdouble, GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glProgramLocalParameter4dvARB (GLenum, GLuint, const GLdouble *);
+GLAPI void APIENTRY glProgramLocalParameter4fARB (GLenum, GLuint, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glProgramLocalParameter4fvARB (GLenum, GLuint, const GLfloat *);
+GLAPI void APIENTRY glGetProgramEnvParameterdvARB (GLenum, GLuint, GLdouble *);
+GLAPI void APIENTRY glGetProgramEnvParameterfvARB (GLenum, GLuint, GLfloat *);
+GLAPI void APIENTRY glGetProgramLocalParameterdvARB (GLenum, GLuint, GLdouble *);
+GLAPI void APIENTRY glGetProgramLocalParameterfvARB (GLenum, GLuint, GLfloat *);
+GLAPI void APIENTRY glGetProgramivARB (GLenum, GLenum, GLint *);
+GLAPI void APIENTRY glGetProgramStringARB (GLenum, GLenum, GLvoid *);
+GLAPI void APIENTRY glGetVertexAttribdvARB (GLuint, GLenum, GLdouble *);
+GLAPI void APIENTRY glGetVertexAttribfvARB (GLuint, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetVertexAttribivARB (GLuint, GLenum, GLint *);
+GLAPI void APIENTRY glGetVertexAttribPointervARB (GLuint, GLenum, GLvoid* *);
+GLAPI GLboolean APIENTRY glIsProgramARB (GLuint);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1DARBPROC) (GLuint index, GLdouble x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1DVARBPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1FARBPROC) (GLuint index, GLfloat x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1FVARBPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1SARBPROC) (GLuint index, GLshort x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1SVARBPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2DARBPROC) (GLuint index, GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2DVARBPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2FARBPROC) (GLuint index, GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2FVARBPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2SARBPROC) (GLuint index, GLshort x, GLshort y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2SVARBPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3DVARBPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3FVARBPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3SVARBPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NBVARBPROC) (GLuint index, const GLbyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NIVARBPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NSVARBPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBARBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBVARBPROC) (GLuint index, const GLubyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUIVARBPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUSVARBPROC) (GLuint index, const GLushort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4BVARBPROC) (GLuint index, const GLbyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4DVARBPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4FVARBPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4IVARBPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4SVARBPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4UBVARBPROC) (GLuint index, const GLubyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4UIVARBPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4USVARBPROC) (GLuint index, const GLushort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERARBPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer);
+typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYARBPROC) (GLuint index);
+typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) (GLuint index);
+typedef void (APIENTRYP PFNGLPROGRAMSTRINGARBPROC) (GLenum target, GLenum format, GLsizei len, const GLvoid *string);
+typedef void (APIENTRYP PFNGLBINDPROGRAMARBPROC) (GLenum target, GLuint program);
+typedef void (APIENTRYP PFNGLDELETEPROGRAMSARBPROC) (GLsizei n, const GLuint *programs);
+typedef void (APIENTRYP PFNGLGENPROGRAMSARBPROC) (GLsizei n, GLuint *programs);
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble *params);
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat *params);
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble *params);
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMENVPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMENVPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMIVARBPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMSTRINGARBPROC) (GLenum target, GLenum pname, GLvoid *string);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBDVARBPROC) (GLuint index, GLenum pname, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBFVARBPROC) (GLuint index, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVARBPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVARBPROC) (GLuint index, GLenum pname, GLvoid* *pointer);
+typedef GLboolean (APIENTRYP PFNGLISPROGRAMARBPROC) (GLuint program);
+#endif
+
+#ifndef GL_ARB_fragment_program
+#define GL_ARB_fragment_program 1
+/* All ARB_fragment_program entry points are shared with ARB_vertex_program. */
+#endif
+
+#ifndef GL_ARB_vertex_buffer_object
+#define GL_ARB_vertex_buffer_object 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBindBufferARB (GLenum, GLuint);
+GLAPI void APIENTRY glDeleteBuffersARB (GLsizei, const GLuint *);
+GLAPI void APIENTRY glGenBuffersARB (GLsizei, GLuint *);
+GLAPI GLboolean APIENTRY glIsBufferARB (GLuint);
+GLAPI void APIENTRY glBufferDataARB (GLenum, GLsizeiptrARB, const GLvoid *, GLenum);
+GLAPI void APIENTRY glBufferSubDataARB (GLenum, GLintptrARB, GLsizeiptrARB, const GLvoid *);
+GLAPI void APIENTRY glGetBufferSubDataARB (GLenum, GLintptrARB, GLsizeiptrARB, GLvoid *);
+GLAPI GLvoid* APIENTRY glMapBufferARB (GLenum, GLenum);
+GLAPI GLboolean APIENTRY glUnmapBufferARB (GLenum);
+GLAPI void APIENTRY glGetBufferParameterivARB (GLenum, GLenum, GLint *);
+GLAPI void APIENTRY glGetBufferPointervARB (GLenum, GLenum, GLvoid* *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLBINDBUFFERARBPROC) (GLenum target, GLuint buffer);
+typedef void (APIENTRYP PFNGLDELETEBUFFERSARBPROC) (GLsizei n, const GLuint *buffers);
+typedef void (APIENTRYP PFNGLGENBUFFERSARBPROC) (GLsizei n, GLuint *buffers);
+typedef GLboolean (APIENTRYP PFNGLISBUFFERARBPROC) (GLuint buffer);
+typedef void (APIENTRYP PFNGLBUFFERDATAARBPROC) (GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage);
+typedef void (APIENTRYP PFNGLBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid *data);
+typedef void (APIENTRYP PFNGLGETBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid *data);
+typedef GLvoid* (APIENTRYP PFNGLMAPBUFFERARBPROC) (GLenum target, GLenum access);
+typedef GLboolean (APIENTRYP PFNGLUNMAPBUFFERARBPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERIVARBPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETBUFFERPOINTERVARBPROC) (GLenum target, GLenum pname, GLvoid* *params);
+#endif
+
+#ifndef GL_ARB_occlusion_query
+#define GL_ARB_occlusion_query 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGenQueriesARB (GLsizei, GLuint *);
+GLAPI void APIENTRY glDeleteQueriesARB (GLsizei, const GLuint *);
+GLAPI GLboolean APIENTRY glIsQueryARB (GLuint);
+GLAPI void APIENTRY glBeginQueryARB (GLenum, GLuint);
+GLAPI void APIENTRY glEndQueryARB (GLenum);
+GLAPI void APIENTRY glGetQueryivARB (GLenum, GLenum, GLint *);
+GLAPI void APIENTRY glGetQueryObjectivARB (GLuint, GLenum, GLint *);
+GLAPI void APIENTRY glGetQueryObjectuivARB (GLuint, GLenum, GLuint *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLGENQUERIESARBPROC) (GLsizei n, GLuint *ids);
+typedef void (APIENTRYP PFNGLDELETEQUERIESARBPROC) (GLsizei n, const GLuint *ids);
+typedef GLboolean (APIENTRYP PFNGLISQUERYARBPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLBEGINQUERYARBPROC) (GLenum target, GLuint id);
+typedef void (APIENTRYP PFNGLENDQUERYARBPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLGETQUERYIVARBPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTIVARBPROC) (GLuint id, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTUIVARBPROC) (GLuint id, GLenum pname, GLuint *params);
+#endif
+
+#ifndef GL_ARB_shader_objects
+#define GL_ARB_shader_objects 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDeleteObjectARB (GLhandleARB);
+GLAPI GLhandleARB APIENTRY glGetHandleARB (GLenum);
+GLAPI void APIENTRY glDetachObjectARB (GLhandleARB, GLhandleARB);
+GLAPI GLhandleARB APIENTRY glCreateShaderObjectARB (GLenum);
+GLAPI void APIENTRY glShaderSourceARB (GLhandleARB, GLsizei, const GLcharARB* *, const GLint *);
+GLAPI void APIENTRY glCompileShaderARB (GLhandleARB);
+GLAPI GLhandleARB APIENTRY glCreateProgramObjectARB (void);
+GLAPI void APIENTRY glAttachObjectARB (GLhandleARB, GLhandleARB);
+GLAPI void APIENTRY glLinkProgramARB (GLhandleARB);
+GLAPI void APIENTRY glUseProgramObjectARB (GLhandleARB);
+GLAPI void APIENTRY glValidateProgramARB (GLhandleARB);
+GLAPI void APIENTRY glUniform1fARB (GLint, GLfloat);
+GLAPI void APIENTRY glUniform2fARB (GLint, GLfloat, GLfloat);
+GLAPI void APIENTRY glUniform3fARB (GLint, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glUniform4fARB (GLint, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glUniform1iARB (GLint, GLint);
+GLAPI void APIENTRY glUniform2iARB (GLint, GLint, GLint);
+GLAPI void APIENTRY glUniform3iARB (GLint, GLint, GLint, GLint);
+GLAPI void APIENTRY glUniform4iARB (GLint, GLint, GLint, GLint, GLint);
+GLAPI void APIENTRY glUniform1fvARB (GLint, GLsizei, const GLfloat *);
+GLAPI void APIENTRY glUniform2fvARB (GLint, GLsizei, const GLfloat *);
+GLAPI void APIENTRY glUniform3fvARB (GLint, GLsizei, const GLfloat *);
+GLAPI void APIENTRY glUniform4fvARB (GLint, GLsizei, const GLfloat *);
+GLAPI void APIENTRY glUniform1ivARB (GLint, GLsizei, const GLint *);
+GLAPI void APIENTRY glUniform2ivARB (GLint, GLsizei, const GLint *);
+GLAPI void APIENTRY glUniform3ivARB (GLint, GLsizei, const GLint *);
+GLAPI void APIENTRY glUniform4ivARB (GLint, GLsizei, const GLint *);
+GLAPI void APIENTRY glUniformMatrix2fvARB (GLint, GLsizei, GLboolean, const GLfloat *);
+GLAPI void APIENTRY glUniformMatrix3fvARB (GLint, GLsizei, GLboolean, const GLfloat *);
+GLAPI void APIENTRY glUniformMatrix4fvARB (GLint, GLsizei, GLboolean, const GLfloat *);
+GLAPI void APIENTRY glGetObjectParameterfvARB (GLhandleARB, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetObjectParameterivARB (GLhandleARB, GLenum, GLint *);
+GLAPI void APIENTRY glGetInfoLogARB (GLhandleARB, GLsizei, GLsizei *, GLcharARB *);
+GLAPI void APIENTRY glGetAttachedObjectsARB (GLhandleARB, GLsizei, GLsizei *, GLhandleARB *);
+GLAPI GLint APIENTRY glGetUniformLocationARB (GLhandleARB, const GLcharARB *);
+GLAPI void APIENTRY glGetActiveUniformARB (GLhandleARB, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLcharARB *);
+GLAPI void APIENTRY glGetUniformfvARB (GLhandleARB, GLint, GLfloat *);
+GLAPI void APIENTRY glGetUniformivARB (GLhandleARB, GLint, GLint *);
+GLAPI void APIENTRY glGetShaderSourceARB (GLhandleARB, GLsizei, GLsizei *, GLcharARB *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLDELETEOBJECTARBPROC) (GLhandleARB obj);
+typedef GLhandleARB (APIENTRYP PFNGLGETHANDLEARBPROC) (GLenum pname);
+typedef void (APIENTRYP PFNGLDETACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB attachedObj);
+typedef GLhandleARB (APIENTRYP PFNGLCREATESHADEROBJECTARBPROC) (GLenum shaderType);
+typedef void (APIENTRYP PFNGLSHADERSOURCEARBPROC) (GLhandleARB shaderObj, GLsizei count, const GLcharARB* *string, const GLint *length);
+typedef void (APIENTRYP PFNGLCOMPILESHADERARBPROC) (GLhandleARB shaderObj);
+typedef GLhandleARB (APIENTRYP PFNGLCREATEPROGRAMOBJECTARBPROC) (void);
+typedef void (APIENTRYP PFNGLATTACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB obj);
+typedef void (APIENTRYP PFNGLLINKPROGRAMARBPROC) (GLhandleARB programObj);
+typedef void (APIENTRYP PFNGLUSEPROGRAMOBJECTARBPROC) (GLhandleARB programObj);
+typedef void (APIENTRYP PFNGLVALIDATEPROGRAMARBPROC) (GLhandleARB programObj);
+typedef void (APIENTRYP PFNGLUNIFORM1FARBPROC) (GLint location, GLfloat v0);
+typedef void (APIENTRYP PFNGLUNIFORM2FARBPROC) (GLint location, GLfloat v0, GLfloat v1);
+typedef void (APIENTRYP PFNGLUNIFORM3FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (APIENTRYP PFNGLUNIFORM4FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (APIENTRYP PFNGLUNIFORM1IARBPROC) (GLint location, GLint v0);
+typedef void (APIENTRYP PFNGLUNIFORM2IARBPROC) (GLint location, GLint v0, GLint v1);
+typedef void (APIENTRYP PFNGLUNIFORM3IARBPROC) (GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (APIENTRYP PFNGLUNIFORM4IARBPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (APIENTRYP PFNGLUNIFORM1FVARBPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM2FVARBPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM3FVARBPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM4FVARBPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM1IVARBPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORM2IVARBPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORM3IVARBPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORM4IVARBPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX2FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX3FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLGETOBJECTPARAMETERFVARBPROC) (GLhandleARB obj, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETOBJECTPARAMETERIVARBPROC) (GLhandleARB obj, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETINFOLOGARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *infoLog);
+typedef void (APIENTRYP PFNGLGETATTACHEDOBJECTSARBPROC) (GLhandleARB containerObj, GLsizei maxCount, GLsizei *count, GLhandleARB *obj);
+typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB *name);
+typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name);
+typedef void (APIENTRYP PFNGLGETUNIFORMFVARBPROC) (GLhandleARB programObj, GLint location, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETUNIFORMIVARBPROC) (GLhandleARB programObj, GLint location, GLint *params);
+typedef void (APIENTRYP PFNGLGETSHADERSOURCEARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *source);
+#endif
+
+#ifndef GL_ARB_vertex_shader
+#define GL_ARB_vertex_shader 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBindAttribLocationARB (GLhandleARB, GLuint, const GLcharARB *);
+GLAPI void APIENTRY glGetActiveAttribARB (GLhandleARB, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLcharARB *);
+GLAPI GLint APIENTRY glGetAttribLocationARB (GLhandleARB, const GLcharARB *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLBINDATTRIBLOCATIONARBPROC) (GLhandleARB programObj, GLuint index, const GLcharARB *name);
+typedef void (APIENTRYP PFNGLGETACTIVEATTRIBARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name);
+typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB *name);
+#endif
+
+#ifndef GL_ARB_fragment_shader
+#define GL_ARB_fragment_shader 1
+#endif
+
+#ifndef GL_ARB_shading_language_100
+#define GL_ARB_shading_language_100 1
+#endif
+
+#ifndef GL_ARB_texture_non_power_of_two
+#define GL_ARB_texture_non_power_of_two 1
+#endif
+
+#ifndef GL_ARB_point_sprite
+#define GL_ARB_point_sprite 1
+#endif
+
+#ifndef GL_ARB_fragment_program_shadow
+#define GL_ARB_fragment_program_shadow 1
+#endif
+
+#ifndef GL_ARB_draw_buffers
+#define GL_ARB_draw_buffers 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawBuffersARB (GLsizei, const GLenum *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLDRAWBUFFERSARBPROC) (GLsizei n, const GLenum *bufs);
+#endif
+
+#ifndef GL_ARB_texture_rectangle
+#define GL_ARB_texture_rectangle 1
+#endif
+
+#ifndef GL_ARB_color_buffer_float
+#define GL_ARB_color_buffer_float 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glClampColorARB (GLenum, GLenum);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLCLAMPCOLORARBPROC) (GLenum target, GLenum clamp);
+#endif
+
+#ifndef GL_ARB_half_float_pixel
+#define GL_ARB_half_float_pixel 1
+#endif
+
+#ifndef GL_ARB_texture_float
+#define GL_ARB_texture_float 1
+#endif
+
+#ifndef GL_ARB_pixel_buffer_object
+#define GL_ARB_pixel_buffer_object 1
+#endif
+
+#ifndef GL_EXT_abgr
+#define GL_EXT_abgr 1
+#endif
+
+#ifndef GL_EXT_blend_color
+#define GL_EXT_blend_color 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendColorEXT (GLclampf, GLclampf, GLclampf, GLclampf);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLBLENDCOLOREXTPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+#endif
+
+#ifndef GL_EXT_polygon_offset
+#define GL_EXT_polygon_offset 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPolygonOffsetEXT (GLfloat, GLfloat);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLPOLYGONOFFSETEXTPROC) (GLfloat factor, GLfloat bias);
+#endif
+
+#ifndef GL_EXT_texture
+#define GL_EXT_texture 1
+#endif
+
+#ifndef GL_EXT_texture3D
+#define GL_EXT_texture3D 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTexImage3DEXT (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *);
+GLAPI void APIENTRY glTexSubImage3DEXT (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLTEXIMAGE3DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (APIENTRYP PFNGLTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels);
+#endif
+
+#ifndef GL_SGIS_texture_filter4
+#define GL_SGIS_texture_filter4 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGetTexFilterFuncSGIS (GLenum, GLenum, GLfloat *);
+GLAPI void APIENTRY glTexFilterFuncSGIS (GLenum, GLenum, GLsizei, const GLfloat *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLGETTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLfloat *weights);
+typedef void (APIENTRYP PFNGLTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLsizei n, const GLfloat *weights);
+#endif
+
+#ifndef GL_EXT_subtexture
+#define GL_EXT_subtexture 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTexSubImage1DEXT (GLenum, GLint, GLint, GLsizei, GLenum, GLenum, const GLvoid *);
+GLAPI void APIENTRY glTexSubImage2DEXT (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (APIENTRYP PFNGLTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
+#endif
+
+#ifndef GL_EXT_copy_texture
+#define GL_EXT_copy_texture 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glCopyTexImage1DEXT (GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLint);
+GLAPI void APIENTRY glCopyTexImage2DEXT (GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLsizei, GLint);
+GLAPI void APIENTRY glCopyTexSubImage1DEXT (GLenum, GLint, GLint, GLint, GLint, GLsizei);
+GLAPI void APIENTRY glCopyTexSubImage2DEXT (GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei);
+GLAPI void APIENTRY glCopyTexSubImage3DEXT (GLenum, GLint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLCOPYTEXIMAGE1DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);
+typedef void (APIENTRYP PFNGLCOPYTEXIMAGE2DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+#endif
+
+#ifndef GL_EXT_histogram
+#define GL_EXT_histogram 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGetHistogramEXT (GLenum, GLboolean, GLenum, GLenum, GLvoid *);
+GLAPI void APIENTRY glGetHistogramParameterfvEXT (GLenum, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetHistogramParameterivEXT (GLenum, GLenum, GLint *);
+GLAPI void APIENTRY glGetMinmaxEXT (GLenum, GLboolean, GLenum, GLenum, GLvoid *);
+GLAPI void APIENTRY glGetMinmaxParameterfvEXT (GLenum, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetMinmaxParameterivEXT (GLenum, GLenum, GLint *);
+GLAPI void APIENTRY glHistogramEXT (GLenum, GLsizei, GLenum, GLboolean);
+GLAPI void APIENTRY glMinmaxEXT (GLenum, GLenum, GLboolean);
+GLAPI void APIENTRY glResetHistogramEXT (GLenum);
+GLAPI void APIENTRY glResetMinmaxEXT (GLenum);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLGETHISTOGRAMEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values);
+typedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETMINMAXEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values);
+typedef void (APIENTRYP PFNGLGETMINMAXPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETMINMAXPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLHISTOGRAMEXTPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink);
+typedef void (APIENTRYP PFNGLMINMAXEXTPROC) (GLenum target, GLenum internalformat, GLboolean sink);
+typedef void (APIENTRYP PFNGLRESETHISTOGRAMEXTPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLRESETMINMAXEXTPROC) (GLenum target);
+#endif
+
+#ifndef GL_EXT_convolution
+#define GL_EXT_convolution 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glConvolutionFilter1DEXT (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *);
+GLAPI void APIENTRY glConvolutionFilter2DEXT (GLenum, GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *);
+GLAPI void APIENTRY glConvolutionParameterfEXT (GLenum, GLenum, GLfloat);
+GLAPI void APIENTRY glConvolutionParameterfvEXT (GLenum, GLenum, const GLfloat *);
+GLAPI void APIENTRY glConvolutionParameteriEXT (GLenum, GLenum, GLint);
+GLAPI void APIENTRY glConvolutionParameterivEXT (GLenum, GLenum, const GLint *);
+GLAPI void APIENTRY glCopyConvolutionFilter1DEXT (GLenum, GLenum, GLint, GLint, GLsizei);
+GLAPI void APIENTRY glCopyConvolutionFilter2DEXT (GLenum, GLenum, GLint, GLint, GLsizei, GLsizei);
+GLAPI void APIENTRY glGetConvolutionFilterEXT (GLenum, GLenum, GLenum, GLvoid *);
+GLAPI void APIENTRY glGetConvolutionParameterfvEXT (GLenum, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetConvolutionParameterivEXT (GLenum, GLenum, GLint *);
+GLAPI void APIENTRY glGetSeparableFilterEXT (GLenum, GLenum, GLenum, GLvoid *, GLvoid *, GLvoid *);
+GLAPI void APIENTRY glSeparableFilter2DEXT (GLenum, GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *, const GLvoid *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image);
+typedef void (APIENTRYP PFNGLCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERFEXTPROC) (GLenum target, GLenum pname, GLfloat params);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERIEXTPROC) (GLenum target, GLenum pname, GLint params);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLCOPYCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+typedef void (APIENTRYP PFNGLCOPYCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLGETCONVOLUTIONFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid *image);
+typedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETSEPARABLEFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span);
+typedef void (APIENTRYP PFNGLSEPARABLEFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column);
+#endif
+
+#ifndef GL_EXT_color_matrix
+#define GL_EXT_color_matrix 1
+#endif
+
+#ifndef GL_SGI_color_table
+#define GL_SGI_color_table 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glColorTableSGI (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *);
+GLAPI void APIENTRY glColorTableParameterfvSGI (GLenum, GLenum, const GLfloat *);
+GLAPI void APIENTRY glColorTableParameterivSGI (GLenum, GLenum, const GLint *);
+GLAPI void APIENTRY glCopyColorTableSGI (GLenum, GLenum, GLint, GLint, GLsizei);
+GLAPI void APIENTRY glGetColorTableSGI (GLenum, GLenum, GLenum, GLvoid *);
+GLAPI void APIENTRY glGetColorTableParameterfvSGI (GLenum, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetColorTableParameterivSGI (GLenum, GLenum, GLint *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table);
+typedef void (APIENTRYP PFNGLCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLCOPYCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+typedef void (APIENTRYP PFNGLGETCOLORTABLESGIPROC) (GLenum target, GLenum format, GLenum type, GLvoid *table);
+typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, GLint *params);
+#endif
+
+#ifndef GL_SGIX_pixel_texture
+#define GL_SGIX_pixel_texture 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPixelTexGenSGIX (GLenum);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLPIXELTEXGENSGIXPROC) (GLenum mode);
+#endif
+
+#ifndef GL_SGIS_pixel_texture
+#define GL_SGIS_pixel_texture 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPixelTexGenParameteriSGIS (GLenum, GLint);
+GLAPI void APIENTRY glPixelTexGenParameterivSGIS (GLenum, const GLint *);
+GLAPI void APIENTRY glPixelTexGenParameterfSGIS (GLenum, GLfloat);
+GLAPI void APIENTRY glPixelTexGenParameterfvSGIS (GLenum, const GLfloat *);
+GLAPI void APIENTRY glGetPixelTexGenParameterivSGIS (GLenum, GLint *);
+GLAPI void APIENTRY glGetPixelTexGenParameterfvSGIS (GLenum, GLfloat *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLPIXELTEXGENPARAMETERISGISPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLPIXELTEXGENPARAMETERIVSGISPROC) (GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLPIXELTEXGENPARAMETERFSGISPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLPIXELTEXGENPARAMETERFVSGISPROC) (GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLGETPIXELTEXGENPARAMETERIVSGISPROC) (GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETPIXELTEXGENPARAMETERFVSGISPROC) (GLenum pname, GLfloat *params);
+#endif
+
+#ifndef GL_SGIS_texture4D
+#define GL_SGIS_texture4D 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTexImage4DSGIS (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *);
+GLAPI void APIENTRY glTexSubImage4DSGIS (GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLTEXIMAGE4DSGISPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (APIENTRYP PFNGLTEXSUBIMAGE4DSGISPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint woffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLenum format, GLenum type, const GLvoid *pixels);
+#endif
+
+#ifndef GL_SGI_texture_color_table
+#define GL_SGI_texture_color_table 1
+#endif
+
+#ifndef GL_EXT_cmyka
+#define GL_EXT_cmyka 1
+#endif
+
+#ifndef GL_EXT_texture_object
+#define GL_EXT_texture_object 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLboolean APIENTRY glAreTexturesResidentEXT (GLsizei, const GLuint *, GLboolean *);
+GLAPI void APIENTRY glBindTextureEXT (GLenum, GLuint);
+GLAPI void APIENTRY glDeleteTexturesEXT (GLsizei, const GLuint *);
+GLAPI void APIENTRY glGenTexturesEXT (GLsizei, GLuint *);
+GLAPI GLboolean APIENTRY glIsTextureEXT (GLuint);
+GLAPI void APIENTRY glPrioritizeTexturesEXT (GLsizei, const GLuint *, const GLclampf *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef GLboolean (APIENTRYP PFNGLARETEXTURESRESIDENTEXTPROC) (GLsizei n, const GLuint *textures, GLboolean *residences);
+typedef void (APIENTRYP PFNGLBINDTEXTUREEXTPROC) (GLenum target, GLuint texture);
+typedef void (APIENTRYP PFNGLDELETETEXTURESEXTPROC) (GLsizei n, const GLuint *textures);
+typedef void (APIENTRYP PFNGLGENTEXTURESEXTPROC) (GLsizei n, GLuint *textures);
+typedef GLboolean (APIENTRYP PFNGLISTEXTUREEXTPROC) (GLuint texture);
+typedef void (APIENTRYP PFNGLPRIORITIZETEXTURESEXTPROC) (GLsizei n, const GLuint *textures, const GLclampf *priorities);
+#endif
+
+#ifndef GL_SGIS_detail_texture
+#define GL_SGIS_detail_texture 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDetailTexFuncSGIS (GLenum, GLsizei, const GLfloat *);
+GLAPI void APIENTRY glGetDetailTexFuncSGIS (GLenum, GLfloat *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLDETAILTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat *points);
+typedef void (APIENTRYP PFNGLGETDETAILTEXFUNCSGISPROC) (GLenum target, GLfloat *points);
+#endif
+
+#ifndef GL_SGIS_sharpen_texture
+#define GL_SGIS_sharpen_texture 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glSharpenTexFuncSGIS (GLenum, GLsizei, const GLfloat *);
+GLAPI void APIENTRY glGetSharpenTexFuncSGIS (GLenum, GLfloat *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLSHARPENTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat *points);
+typedef void (APIENTRYP PFNGLGETSHARPENTEXFUNCSGISPROC) (GLenum target, GLfloat *points);
+#endif
+
+#ifndef GL_EXT_packed_pixels
+#define GL_EXT_packed_pixels 1
+#endif
+
+#ifndef GL_SGIS_texture_lod
+#define GL_SGIS_texture_lod 1
+#endif
+
+#ifndef GL_SGIS_multisample
+#define GL_SGIS_multisample 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glSampleMaskSGIS (GLclampf, GLboolean);
+GLAPI void APIENTRY glSamplePatternSGIS (GLenum);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLSAMPLEMASKSGISPROC) (GLclampf value, GLboolean invert);
+typedef void (APIENTRYP PFNGLSAMPLEPATTERNSGISPROC) (GLenum pattern);
+#endif
+
+#ifndef GL_EXT_rescale_normal
+#define GL_EXT_rescale_normal 1
+#endif
+
+#ifndef GL_EXT_vertex_array
+#define GL_EXT_vertex_array 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glArrayElementEXT (GLint);
+GLAPI void APIENTRY glColorPointerEXT (GLint, GLenum, GLsizei, GLsizei, const GLvoid *);
+GLAPI void APIENTRY glDrawArraysEXT (GLenum, GLint, GLsizei);
+GLAPI void APIENTRY glEdgeFlagPointerEXT (GLsizei, GLsizei, const GLboolean *);
+GLAPI void APIENTRY glGetPointervEXT (GLenum, GLvoid* *);
+GLAPI void APIENTRY glIndexPointerEXT (GLenum, GLsizei, GLsizei, const GLvoid *);
+GLAPI void APIENTRY glNormalPointerEXT (GLenum, GLsizei, GLsizei, const GLvoid *);
+GLAPI void APIENTRY glTexCoordPointerEXT (GLint, GLenum, GLsizei, GLsizei, const GLvoid *);
+GLAPI void APIENTRY glVertexPointerEXT (GLint, GLenum, GLsizei, GLsizei, const GLvoid *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLARRAYELEMENTEXTPROC) (GLint i);
+typedef void (APIENTRYP PFNGLCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);
+typedef void (APIENTRYP PFNGLDRAWARRAYSEXTPROC) (GLenum mode, GLint first, GLsizei count);
+typedef void (APIENTRYP PFNGLEDGEFLAGPOINTEREXTPROC) (GLsizei stride, GLsizei count, const GLboolean *pointer);
+typedef void (APIENTRYP PFNGLGETPOINTERVEXTPROC) (GLenum pname, GLvoid* *params);
+typedef void (APIENTRYP PFNGLINDEXPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);
+typedef void (APIENTRYP PFNGLNORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);
+typedef void (APIENTRYP PFNGLTEXCOORDPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);
+typedef void (APIENTRYP PFNGLVERTEXPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);
+#endif
+
+#ifndef GL_EXT_misc_attribute
+#define GL_EXT_misc_attribute 1
+#endif
+
+#ifndef GL_SGIS_generate_mipmap
+#define GL_SGIS_generate_mipmap 1
+#endif
+
+#ifndef GL_SGIX_clipmap
+#define GL_SGIX_clipmap 1
+#endif
+
+#ifndef GL_SGIX_shadow
+#define GL_SGIX_shadow 1
+#endif
+
+#ifndef GL_SGIS_texture_edge_clamp
+#define GL_SGIS_texture_edge_clamp 1
+#endif
+
+#ifndef GL_SGIS_texture_border_clamp
+#define GL_SGIS_texture_border_clamp 1
+#endif
+
+#ifndef GL_EXT_blend_minmax
+#define GL_EXT_blend_minmax 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendEquationEXT (GLenum);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLBLENDEQUATIONEXTPROC) (GLenum mode);
+#endif
+
+#ifndef GL_EXT_blend_subtract
+#define GL_EXT_blend_subtract 1
+#endif
+
+#ifndef GL_EXT_blend_logic_op
+#define GL_EXT_blend_logic_op 1
+#endif
+
+#ifndef GL_SGIX_interlace
+#define GL_SGIX_interlace 1
+#endif
+
+#ifndef GL_SGIX_pixel_tiles
+#define GL_SGIX_pixel_tiles 1
+#endif
+
+#ifndef GL_SGIX_texture_select
+#define GL_SGIX_texture_select 1
+#endif
+
+#ifndef GL_SGIX_sprite
+#define GL_SGIX_sprite 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glSpriteParameterfSGIX (GLenum, GLfloat);
+GLAPI void APIENTRY glSpriteParameterfvSGIX (GLenum, const GLfloat *);
+GLAPI void APIENTRY glSpriteParameteriSGIX (GLenum, GLint);
+GLAPI void APIENTRY glSpriteParameterivSGIX (GLenum, const GLint *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLSPRITEPARAMETERFSGIXPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLSPRITEPARAMETERFVSGIXPROC) (GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLSPRITEPARAMETERISGIXPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLSPRITEPARAMETERIVSGIXPROC) (GLenum pname, const GLint *params);
+#endif
+
+#ifndef GL_SGIX_texture_multi_buffer
+#define GL_SGIX_texture_multi_buffer 1
+#endif
+
+#ifndef GL_EXT_point_parameters
+#define GL_EXT_point_parameters 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPointParameterfEXT (GLenum, GLfloat);
+GLAPI void APIENTRY glPointParameterfvEXT (GLenum, const GLfloat *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFEXTPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFVEXTPROC) (GLenum pname, const GLfloat *params);
+#endif
+
+#ifndef GL_SGIS_point_parameters
+#define GL_SGIS_point_parameters 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPointParameterfSGIS (GLenum, GLfloat);
+GLAPI void APIENTRY glPointParameterfvSGIS (GLenum, const GLfloat *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFSGISPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFVSGISPROC) (GLenum pname, const GLfloat *params);
+#endif
+
+#ifndef GL_SGIX_instruments
+#define GL_SGIX_instruments 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLint APIENTRY glGetInstrumentsSGIX (void);
+GLAPI void APIENTRY glInstrumentsBufferSGIX (GLsizei, GLint *);
+GLAPI GLint APIENTRY glPollInstrumentsSGIX (GLint *);
+GLAPI void APIENTRY glReadInstrumentsSGIX (GLint);
+GLAPI void APIENTRY glStartInstrumentsSGIX (void);
+GLAPI void APIENTRY glStopInstrumentsSGIX (GLint);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef GLint (APIENTRYP PFNGLGETINSTRUMENTSSGIXPROC) (void);
+typedef void (APIENTRYP PFNGLINSTRUMENTSBUFFERSGIXPROC) (GLsizei size, GLint *buffer);
+typedef GLint (APIENTRYP PFNGLPOLLINSTRUMENTSSGIXPROC) (GLint *marker_p);
+typedef void (APIENTRYP PFNGLREADINSTRUMENTSSGIXPROC) (GLint marker);
+typedef void (APIENTRYP PFNGLSTARTINSTRUMENTSSGIXPROC) (void);
+typedef void (APIENTRYP PFNGLSTOPINSTRUMENTSSGIXPROC) (GLint marker);
+#endif
+
+#ifndef GL_SGIX_texture_scale_bias
+#define GL_SGIX_texture_scale_bias 1
+#endif
+
+#ifndef GL_SGIX_framezoom
+#define GL_SGIX_framezoom 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFrameZoomSGIX (GLint);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLFRAMEZOOMSGIXPROC) (GLint factor);
+#endif
+
+#ifndef GL_SGIX_tag_sample_buffer
+#define GL_SGIX_tag_sample_buffer 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTagSampleBufferSGIX (void);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLTAGSAMPLEBUFFERSGIXPROC) (void);
+#endif
+
+#ifndef GL_SGIX_polynomial_ffd
+#define GL_SGIX_polynomial_ffd 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDeformationMap3dSGIX (GLenum, GLdouble, GLdouble, GLint, GLint, GLdouble, GLdouble, GLint, GLint, GLdouble, GLdouble, GLint, GLint, const GLdouble *);
+GLAPI void APIENTRY glDeformationMap3fSGIX (GLenum, GLfloat, GLfloat, GLint, GLint, GLfloat, GLfloat, GLint, GLint, GLfloat, GLfloat, GLint, GLint, const GLfloat *);
+GLAPI void APIENTRY glDeformSGIX (GLbitfield);
+GLAPI void APIENTRY glLoadIdentityDeformationMapSGIX (GLbitfield);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLDEFORMATIONMAP3DSGIXPROC) (GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, GLdouble w1, GLdouble w2, GLint wstride, GLint worder, const GLdouble *points);
+typedef void (APIENTRYP PFNGLDEFORMATIONMAP3FSGIXPROC) (GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, GLfloat w1, GLfloat w2, GLint wstride, GLint worder, const GLfloat *points);
+typedef void (APIENTRYP PFNGLDEFORMSGIXPROC) (GLbitfield mask);
+typedef void (APIENTRYP PFNGLLOADIDENTITYDEFORMATIONMAPSGIXPROC) (GLbitfield mask);
+#endif
+
+#ifndef GL_SGIX_reference_plane
+#define GL_SGIX_reference_plane 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glReferencePlaneSGIX (const GLdouble *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLREFERENCEPLANESGIXPROC) (const GLdouble *equation);
+#endif
+
+#ifndef GL_SGIX_flush_raster
+#define GL_SGIX_flush_raster 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFlushRasterSGIX (void);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLFLUSHRASTERSGIXPROC) (void);
+#endif
+
+#ifndef GL_SGIX_depth_texture
+#define GL_SGIX_depth_texture 1
+#endif
+
+#ifndef GL_SGIS_fog_function
+#define GL_SGIS_fog_function 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFogFuncSGIS (GLsizei, const GLfloat *);
+GLAPI void APIENTRY glGetFogFuncSGIS (GLfloat *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLFOGFUNCSGISPROC) (GLsizei n, const GLfloat *points);
+typedef void (APIENTRYP PFNGLGETFOGFUNCSGISPROC) (GLfloat *points);
+#endif
+
+#ifndef GL_SGIX_fog_offset
+#define GL_SGIX_fog_offset 1
+#endif
+
+#ifndef GL_HP_image_transform
+#define GL_HP_image_transform 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glImageTransformParameteriHP (GLenum, GLenum, GLint);
+GLAPI void APIENTRY glImageTransformParameterfHP (GLenum, GLenum, GLfloat);
+GLAPI void APIENTRY glImageTransformParameterivHP (GLenum, GLenum, const GLint *);
+GLAPI void APIENTRY glImageTransformParameterfvHP (GLenum, GLenum, const GLfloat *);
+GLAPI void APIENTRY glGetImageTransformParameterivHP (GLenum, GLenum, GLint *);
+GLAPI void APIENTRY glGetImageTransformParameterfvHP (GLenum, GLenum, GLfloat *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLIMAGETRANSFORMPARAMETERIHPPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLIMAGETRANSFORMPARAMETERFHPPROC) (GLenum target, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLGETIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, GLfloat *params);
+#endif
+
+#ifndef GL_HP_convolution_border_modes
+#define GL_HP_convolution_border_modes 1
+#endif
+
+#ifndef GL_SGIX_texture_add_env
+#define GL_SGIX_texture_add_env 1
+#endif
+
+#ifndef GL_EXT_color_subtable
+#define GL_EXT_color_subtable 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glColorSubTableEXT (GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *);
+GLAPI void APIENTRY glCopyColorSubTableEXT (GLenum, GLsizei, GLint, GLint, GLsizei);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOPYCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width);
+#endif
+
+#ifndef GL_PGI_vertex_hints
+#define GL_PGI_vertex_hints 1
+#endif
+
+#ifndef GL_PGI_misc_hints
+#define GL_PGI_misc_hints 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glHintPGI (GLenum, GLint);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLHINTPGIPROC) (GLenum target, GLint mode);
+#endif
+
+#ifndef GL_EXT_paletted_texture
+#define GL_EXT_paletted_texture 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glColorTableEXT (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *);
+GLAPI void APIENTRY glGetColorTableEXT (GLenum, GLenum, GLenum, GLvoid *);
+GLAPI void APIENTRY glGetColorTableParameterivEXT (GLenum, GLenum, GLint *);
+GLAPI void APIENTRY glGetColorTableParameterfvEXT (GLenum, GLenum, GLfloat *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const GLvoid *table);
+typedef void (APIENTRYP PFNGLGETCOLORTABLEEXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid *data);
+typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params);
+#endif
+
+#ifndef GL_EXT_clip_volume_hint
+#define GL_EXT_clip_volume_hint 1
+#endif
+
+#ifndef GL_SGIX_list_priority
+#define GL_SGIX_list_priority 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGetListParameterfvSGIX (GLuint, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetListParameterivSGIX (GLuint, GLenum, GLint *);
+GLAPI void APIENTRY glListParameterfSGIX (GLuint, GLenum, GLfloat);
+GLAPI void APIENTRY glListParameterfvSGIX (GLuint, GLenum, const GLfloat *);
+GLAPI void APIENTRY glListParameteriSGIX (GLuint, GLenum, GLint);
+GLAPI void APIENTRY glListParameterivSGIX (GLuint, GLenum, const GLint *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLGETLISTPARAMETERFVSGIXPROC) (GLuint list, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETLISTPARAMETERIVSGIXPROC) (GLuint list, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLLISTPARAMETERFSGIXPROC) (GLuint list, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLLISTPARAMETERFVSGIXPROC) (GLuint list, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLLISTPARAMETERISGIXPROC) (GLuint list, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLLISTPARAMETERIVSGIXPROC) (GLuint list, GLenum pname, const GLint *params);
+#endif
+
+#ifndef GL_SGIX_ir_instrument1
+#define GL_SGIX_ir_instrument1 1
+#endif
+
+#ifndef GL_SGIX_calligraphic_fragment
+#define GL_SGIX_calligraphic_fragment 1
+#endif
+
+#ifndef GL_SGIX_texture_lod_bias
+#define GL_SGIX_texture_lod_bias 1
+#endif
+
+#ifndef GL_SGIX_shadow_ambient
+#define GL_SGIX_shadow_ambient 1
+#endif
+
+#ifndef GL_EXT_index_texture
+#define GL_EXT_index_texture 1
+#endif
+
+#ifndef GL_EXT_index_material
+#define GL_EXT_index_material 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glIndexMaterialEXT (GLenum, GLenum);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLINDEXMATERIALEXTPROC) (GLenum face, GLenum mode);
+#endif
+
+#ifndef GL_EXT_index_func
+#define GL_EXT_index_func 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glIndexFuncEXT (GLenum, GLclampf);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLINDEXFUNCEXTPROC) (GLenum func, GLclampf ref);
+#endif
+
+#ifndef GL_EXT_index_array_formats
+#define GL_EXT_index_array_formats 1
+#endif
+
+#ifndef GL_EXT_compiled_vertex_array
+#define GL_EXT_compiled_vertex_array 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glLockArraysEXT (GLint, GLsizei);
+GLAPI void APIENTRY glUnlockArraysEXT (void);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLLOCKARRAYSEXTPROC) (GLint first, GLsizei count);
+typedef void (APIENTRYP PFNGLUNLOCKARRAYSEXTPROC) (void);
+#endif
+
+#ifndef GL_EXT_cull_vertex
+#define GL_EXT_cull_vertex 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glCullParameterdvEXT (GLenum, GLdouble *);
+GLAPI void APIENTRY glCullParameterfvEXT (GLenum, GLfloat *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLCULLPARAMETERDVEXTPROC) (GLenum pname, GLdouble *params);
+typedef void (APIENTRYP PFNGLCULLPARAMETERFVEXTPROC) (GLenum pname, GLfloat *params);
+#endif
+
+#ifndef GL_SGIX_ycrcb
+#define GL_SGIX_ycrcb 1
+#endif
+
+#ifndef GL_SGIX_fragment_lighting
+#define GL_SGIX_fragment_lighting 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFragmentColorMaterialSGIX (GLenum, GLenum);
+GLAPI void APIENTRY glFragmentLightfSGIX (GLenum, GLenum, GLfloat);
+GLAPI void APIENTRY glFragmentLightfvSGIX (GLenum, GLenum, const GLfloat *);
+GLAPI void APIENTRY glFragmentLightiSGIX (GLenum, GLenum, GLint);
+GLAPI void APIENTRY glFragmentLightivSGIX (GLenum, GLenum, const GLint *);
+GLAPI void APIENTRY glFragmentLightModelfSGIX (GLenum, GLfloat);
+GLAPI void APIENTRY glFragmentLightModelfvSGIX (GLenum, const GLfloat *);
+GLAPI void APIENTRY glFragmentLightModeliSGIX (GLenum, GLint);
+GLAPI void APIENTRY glFragmentLightModelivSGIX (GLenum, const GLint *);
+GLAPI void APIENTRY glFragmentMaterialfSGIX (GLenum, GLenum, GLfloat);
+GLAPI void APIENTRY glFragmentMaterialfvSGIX (GLenum, GLenum, const GLfloat *);
+GLAPI void APIENTRY glFragmentMaterialiSGIX (GLenum, GLenum, GLint);
+GLAPI void APIENTRY glFragmentMaterialivSGIX (GLenum, GLenum, const GLint *);
+GLAPI void APIENTRY glGetFragmentLightfvSGIX (GLenum, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetFragmentLightivSGIX (GLenum, GLenum, GLint *);
+GLAPI void APIENTRY glGetFragmentMaterialfvSGIX (GLenum, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetFragmentMaterialivSGIX (GLenum, GLenum, GLint *);
+GLAPI void APIENTRY glLightEnviSGIX (GLenum, GLint);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLFRAGMENTCOLORMATERIALSGIXPROC) (GLenum face, GLenum mode);
+typedef void (APIENTRYP PFNGLFRAGMENTLIGHTFSGIXPROC) (GLenum light, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLFRAGMENTLIGHTISGIXPROC) (GLenum light, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLFRAGMENTLIGHTMODELFSGIXPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLFRAGMENTLIGHTMODELFVSGIXPROC) (GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLFRAGMENTLIGHTMODELISGIXPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLFRAGMENTLIGHTMODELIVSGIXPROC) (GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLFRAGMENTMATERIALFSGIXPROC) (GLenum face, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLFRAGMENTMATERIALISGIXPROC) (GLenum face, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLGETFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLLIGHTENVISGIXPROC) (GLenum pname, GLint param);
+#endif
+
+#ifndef GL_IBM_rasterpos_clip
+#define GL_IBM_rasterpos_clip 1
+#endif
+
+#ifndef GL_HP_texture_lighting
+#define GL_HP_texture_lighting 1
+#endif
+
+#ifndef GL_EXT_draw_range_elements
+#define GL_EXT_draw_range_elements 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawRangeElementsEXT (GLenum, GLuint, GLuint, GLsizei, GLenum, const GLvoid *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSEXTPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices);
+#endif
+
+#ifndef GL_WIN_phong_shading
+#define GL_WIN_phong_shading 1
+#endif
+
+#ifndef GL_WIN_specular_fog
+#define GL_WIN_specular_fog 1
+#endif
+
+#ifndef GL_EXT_light_texture
+#define GL_EXT_light_texture 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glApplyTextureEXT (GLenum);
+GLAPI void APIENTRY glTextureLightEXT (GLenum);
+GLAPI void APIENTRY glTextureMaterialEXT (GLenum, GLenum);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLAPPLYTEXTUREEXTPROC) (GLenum mode);
+typedef void (APIENTRYP PFNGLTEXTURELIGHTEXTPROC) (GLenum pname);
+typedef void (APIENTRYP PFNGLTEXTUREMATERIALEXTPROC) (GLenum face, GLenum mode);
+#endif
+
+#ifndef GL_SGIX_blend_alpha_minmax
+#define GL_SGIX_blend_alpha_minmax 1
+#endif
+
+#ifndef GL_EXT_bgra
+#define GL_EXT_bgra 1
+#endif
+
+#ifndef GL_SGIX_async
+#define GL_SGIX_async 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glAsyncMarkerSGIX (GLuint);
+GLAPI GLint APIENTRY glFinishAsyncSGIX (GLuint *);
+GLAPI GLint APIENTRY glPollAsyncSGIX (GLuint *);
+GLAPI GLuint APIENTRY glGenAsyncMarkersSGIX (GLsizei);
+GLAPI void APIENTRY glDeleteAsyncMarkersSGIX (GLuint, GLsizei);
+GLAPI GLboolean APIENTRY glIsAsyncMarkerSGIX (GLuint);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLASYNCMARKERSGIXPROC) (GLuint marker);
+typedef GLint (APIENTRYP PFNGLFINISHASYNCSGIXPROC) (GLuint *markerp);
+typedef GLint (APIENTRYP PFNGLPOLLASYNCSGIXPROC) (GLuint *markerp);
+typedef GLuint (APIENTRYP PFNGLGENASYNCMARKERSSGIXPROC) (GLsizei range);
+typedef void (APIENTRYP PFNGLDELETEASYNCMARKERSSGIXPROC) (GLuint marker, GLsizei range);
+typedef GLboolean (APIENTRYP PFNGLISASYNCMARKERSGIXPROC) (GLuint marker);
+#endif
+
+#ifndef GL_SGIX_async_pixel
+#define GL_SGIX_async_pixel 1
+#endif
+
+#ifndef GL_SGIX_async_histogram
+#define GL_SGIX_async_histogram 1
+#endif
+
+#ifndef GL_INTEL_parallel_arrays
+#define GL_INTEL_parallel_arrays 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexPointervINTEL (GLint, GLenum, const GLvoid* *);
+GLAPI void APIENTRY glNormalPointervINTEL (GLenum, const GLvoid* *);
+GLAPI void APIENTRY glColorPointervINTEL (GLint, GLenum, const GLvoid* *);
+GLAPI void APIENTRY glTexCoordPointervINTEL (GLint, GLenum, const GLvoid* *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLVERTEXPOINTERVINTELPROC) (GLint size, GLenum type, const GLvoid* *pointer);
+typedef void (APIENTRYP PFNGLNORMALPOINTERVINTELPROC) (GLenum type, const GLvoid* *pointer);
+typedef void (APIENTRYP PFNGLCOLORPOINTERVINTELPROC) (GLint size, GLenum type, const GLvoid* *pointer);
+typedef void (APIENTRYP PFNGLTEXCOORDPOINTERVINTELPROC) (GLint size, GLenum type, const GLvoid* *pointer);
+#endif
+
+#ifndef GL_HP_occlusion_test
+#define GL_HP_occlusion_test 1
+#endif
+
+#ifndef GL_EXT_pixel_transform
+#define GL_EXT_pixel_transform 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPixelTransformParameteriEXT (GLenum, GLenum, GLint);
+GLAPI void APIENTRY glPixelTransformParameterfEXT (GLenum, GLenum, GLfloat);
+GLAPI void APIENTRY glPixelTransformParameterivEXT (GLenum, GLenum, const GLint *);
+GLAPI void APIENTRY glPixelTransformParameterfvEXT (GLenum, GLenum, const GLfloat *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLPIXELTRANSFORMPARAMETERIEXTPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLPIXELTRANSFORMPARAMETERFEXTPROC) (GLenum target, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLPIXELTRANSFORMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLPIXELTRANSFORMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat *params);
+#endif
+
+#ifndef GL_EXT_pixel_transform_color_table
+#define GL_EXT_pixel_transform_color_table 1
+#endif
+
+#ifndef GL_EXT_shared_texture_palette
+#define GL_EXT_shared_texture_palette 1
+#endif
+
+#ifndef GL_EXT_separate_specular_color
+#define GL_EXT_separate_specular_color 1
+#endif
+
+#ifndef GL_EXT_secondary_color
+#define GL_EXT_secondary_color 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glSecondaryColor3bEXT (GLbyte, GLbyte, GLbyte);
+GLAPI void APIENTRY glSecondaryColor3bvEXT (const GLbyte *);
+GLAPI void APIENTRY glSecondaryColor3dEXT (GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glSecondaryColor3dvEXT (const GLdouble *);
+GLAPI void APIENTRY glSecondaryColor3fEXT (GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glSecondaryColor3fvEXT (const GLfloat *);
+GLAPI void APIENTRY glSecondaryColor3iEXT (GLint, GLint, GLint);
+GLAPI void APIENTRY glSecondaryColor3ivEXT (const GLint *);
+GLAPI void APIENTRY glSecondaryColor3sEXT (GLshort, GLshort, GLshort);
+GLAPI void APIENTRY glSecondaryColor3svEXT (const GLshort *);
+GLAPI void APIENTRY glSecondaryColor3ubEXT (GLubyte, GLubyte, GLubyte);
+GLAPI void APIENTRY glSecondaryColor3ubvEXT (const GLubyte *);
+GLAPI void APIENTRY glSecondaryColor3uiEXT (GLuint, GLuint, GLuint);
+GLAPI void APIENTRY glSecondaryColor3uivEXT (const GLuint *);
+GLAPI void APIENTRY glSecondaryColor3usEXT (GLushort, GLushort, GLushort);
+GLAPI void APIENTRY glSecondaryColor3usvEXT (const GLushort *);
+GLAPI void APIENTRY glSecondaryColorPointerEXT (GLint, GLenum, GLsizei, const GLvoid *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3BEXTPROC) (GLbyte red, GLbyte green, GLbyte blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3BVEXTPROC) (const GLbyte *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3DEXTPROC) (GLdouble red, GLdouble green, GLdouble blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3DVEXTPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3FEXTPROC) (GLfloat red, GLfloat green, GLfloat blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3FVEXTPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3IEXTPROC) (GLint red, GLint green, GLint blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3IVEXTPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3SEXTPROC) (GLshort red, GLshort green, GLshort blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3SVEXTPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBEXTPROC) (GLubyte red, GLubyte green, GLubyte blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBVEXTPROC) (const GLubyte *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIEXTPROC) (GLuint red, GLuint green, GLuint blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIVEXTPROC) (const GLuint *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3USEXTPROC) (GLushort red, GLushort green, GLushort blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3USVEXTPROC) (const GLushort *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+#endif
+
+#ifndef GL_EXT_texture_perturb_normal
+#define GL_EXT_texture_perturb_normal 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTextureNormalEXT (GLenum);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLTEXTURENORMALEXTPROC) (GLenum mode);
+#endif
+
+#ifndef GL_EXT_multi_draw_arrays
+#define GL_EXT_multi_draw_arrays 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMultiDrawArraysEXT (GLenum, GLint *, GLsizei *, GLsizei);
+GLAPI void APIENTRY glMultiDrawElementsEXT (GLenum, const GLsizei *, GLenum, const GLvoid* *, GLsizei);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount);
+typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount);
+#endif
+
+#ifndef GL_EXT_fog_coord
+#define GL_EXT_fog_coord 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFogCoordfEXT (GLfloat);
+GLAPI void APIENTRY glFogCoordfvEXT (const GLfloat *);
+GLAPI void APIENTRY glFogCoorddEXT (GLdouble);
+GLAPI void APIENTRY glFogCoorddvEXT (const GLdouble *);
+GLAPI void APIENTRY glFogCoordPointerEXT (GLenum, GLsizei, const GLvoid *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLFOGCOORDFEXTPROC) (GLfloat coord);
+typedef void (APIENTRYP PFNGLFOGCOORDFVEXTPROC) (const GLfloat *coord);
+typedef void (APIENTRYP PFNGLFOGCOORDDEXTPROC) (GLdouble coord);
+typedef void (APIENTRYP PFNGLFOGCOORDDVEXTPROC) (const GLdouble *coord);
+typedef void (APIENTRYP PFNGLFOGCOORDPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid *pointer);
+#endif
+
+#ifndef GL_REND_screen_coordinates
+#define GL_REND_screen_coordinates 1
+#endif
+
+#ifndef GL_EXT_coordinate_frame
+#define GL_EXT_coordinate_frame 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTangent3bEXT (GLbyte, GLbyte, GLbyte);
+GLAPI void APIENTRY glTangent3bvEXT (const GLbyte *);
+GLAPI void APIENTRY glTangent3dEXT (GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glTangent3dvEXT (const GLdouble *);
+GLAPI void APIENTRY glTangent3fEXT (GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glTangent3fvEXT (const GLfloat *);
+GLAPI void APIENTRY glTangent3iEXT (GLint, GLint, GLint);
+GLAPI void APIENTRY glTangent3ivEXT (const GLint *);
+GLAPI void APIENTRY glTangent3sEXT (GLshort, GLshort, GLshort);
+GLAPI void APIENTRY glTangent3svEXT (const GLshort *);
+GLAPI void APIENTRY glBinormal3bEXT (GLbyte, GLbyte, GLbyte);
+GLAPI void APIENTRY glBinormal3bvEXT (const GLbyte *);
+GLAPI void APIENTRY glBinormal3dEXT (GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glBinormal3dvEXT (const GLdouble *);
+GLAPI void APIENTRY glBinormal3fEXT (GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glBinormal3fvEXT (const GLfloat *);
+GLAPI void APIENTRY glBinormal3iEXT (GLint, GLint, GLint);
+GLAPI void APIENTRY glBinormal3ivEXT (const GLint *);
+GLAPI void APIENTRY glBinormal3sEXT (GLshort, GLshort, GLshort);
+GLAPI void APIENTRY glBinormal3svEXT (const GLshort *);
+GLAPI void APIENTRY glTangentPointerEXT (GLenum, GLsizei, const GLvoid *);
+GLAPI void APIENTRY glBinormalPointerEXT (GLenum, GLsizei, const GLvoid *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLTANGENT3BEXTPROC) (GLbyte tx, GLbyte ty, GLbyte tz);
+typedef void (APIENTRYP PFNGLTANGENT3BVEXTPROC) (const GLbyte *v);
+typedef void (APIENTRYP PFNGLTANGENT3DEXTPROC) (GLdouble tx, GLdouble ty, GLdouble tz);
+typedef void (APIENTRYP PFNGLTANGENT3DVEXTPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLTANGENT3FEXTPROC) (GLfloat tx, GLfloat ty, GLfloat tz);
+typedef void (APIENTRYP PFNGLTANGENT3FVEXTPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLTANGENT3IEXTPROC) (GLint tx, GLint ty, GLint tz);
+typedef void (APIENTRYP PFNGLTANGENT3IVEXTPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLTANGENT3SEXTPROC) (GLshort tx, GLshort ty, GLshort tz);
+typedef void (APIENTRYP PFNGLTANGENT3SVEXTPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLBINORMAL3BEXTPROC) (GLbyte bx, GLbyte by, GLbyte bz);
+typedef void (APIENTRYP PFNGLBINORMAL3BVEXTPROC) (const GLbyte *v);
+typedef void (APIENTRYP PFNGLBINORMAL3DEXTPROC) (GLdouble bx, GLdouble by, GLdouble bz);
+typedef void (APIENTRYP PFNGLBINORMAL3DVEXTPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLBINORMAL3FEXTPROC) (GLfloat bx, GLfloat by, GLfloat bz);
+typedef void (APIENTRYP PFNGLBINORMAL3FVEXTPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLBINORMAL3IEXTPROC) (GLint bx, GLint by, GLint bz);
+typedef void (APIENTRYP PFNGLBINORMAL3IVEXTPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLBINORMAL3SEXTPROC) (GLshort bx, GLshort by, GLshort bz);
+typedef void (APIENTRYP PFNGLBINORMAL3SVEXTPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLTANGENTPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid *pointer);
+typedef void (APIENTRYP PFNGLBINORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid *pointer);
+#endif
+
+#ifndef GL_EXT_texture_env_combine
+#define GL_EXT_texture_env_combine 1
+#endif
+
+#ifndef GL_APPLE_specular_vector
+#define GL_APPLE_specular_vector 1
+#endif
+
+#ifndef GL_APPLE_transform_hint
+#define GL_APPLE_transform_hint 1
+#endif
+
+#ifndef GL_SGIX_fog_scale
+#define GL_SGIX_fog_scale 1
+#endif
+
+#ifndef GL_SUNX_constant_data
+#define GL_SUNX_constant_data 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFinishTextureSUNX (void);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLFINISHTEXTURESUNXPROC) (void);
+#endif
+
+#ifndef GL_SUN_global_alpha
+#define GL_SUN_global_alpha 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGlobalAlphaFactorbSUN (GLbyte);
+GLAPI void APIENTRY glGlobalAlphaFactorsSUN (GLshort);
+GLAPI void APIENTRY glGlobalAlphaFactoriSUN (GLint);
+GLAPI void APIENTRY glGlobalAlphaFactorfSUN (GLfloat);
+GLAPI void APIENTRY glGlobalAlphaFactordSUN (GLdouble);
+GLAPI void APIENTRY glGlobalAlphaFactorubSUN (GLubyte);
+GLAPI void APIENTRY glGlobalAlphaFactorusSUN (GLushort);
+GLAPI void APIENTRY glGlobalAlphaFactoruiSUN (GLuint);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORBSUNPROC) (GLbyte factor);
+typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORSSUNPROC) (GLshort factor);
+typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORISUNPROC) (GLint factor);
+typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORFSUNPROC) (GLfloat factor);
+typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORDSUNPROC) (GLdouble factor);
+typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORUBSUNPROC) (GLubyte factor);
+typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORUSSUNPROC) (GLushort factor);
+typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORUISUNPROC) (GLuint factor);
+#endif
+
+#ifndef GL_SUN_triangle_list
+#define GL_SUN_triangle_list 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glReplacementCodeuiSUN (GLuint);
+GLAPI void APIENTRY glReplacementCodeusSUN (GLushort);
+GLAPI void APIENTRY glReplacementCodeubSUN (GLubyte);
+GLAPI void APIENTRY glReplacementCodeuivSUN (const GLuint *);
+GLAPI void APIENTRY glReplacementCodeusvSUN (const GLushort *);
+GLAPI void APIENTRY glReplacementCodeubvSUN (const GLubyte *);
+GLAPI void APIENTRY glReplacementCodePointerSUN (GLenum, GLsizei, const GLvoid* *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUISUNPROC) (GLuint code);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUSSUNPROC) (GLushort code);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUBSUNPROC) (GLubyte code);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUIVSUNPROC) (const GLuint *code);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUSVSUNPROC) (const GLushort *code);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUBVSUNPROC) (const GLubyte *code);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEPOINTERSUNPROC) (GLenum type, GLsizei stride, const GLvoid* *pointer);
+#endif
+
+#ifndef GL_SUN_vertex
+#define GL_SUN_vertex 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glColor4ubVertex2fSUN (GLubyte, GLubyte, GLubyte, GLubyte, GLfloat, GLfloat);
+GLAPI void APIENTRY glColor4ubVertex2fvSUN (const GLubyte *, const GLfloat *);
+GLAPI void APIENTRY glColor4ubVertex3fSUN (GLubyte, GLubyte, GLubyte, GLubyte, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glColor4ubVertex3fvSUN (const GLubyte *, const GLfloat *);
+GLAPI void APIENTRY glColor3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glColor3fVertex3fvSUN (const GLfloat *, const GLfloat *);
+GLAPI void APIENTRY glNormal3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glNormal3fVertex3fvSUN (const GLfloat *, const GLfloat *);
+GLAPI void APIENTRY glColor4fNormal3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glColor4fNormal3fVertex3fvSUN (const GLfloat *, const GLfloat *, const GLfloat *);
+GLAPI void APIENTRY glTexCoord2fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glTexCoord2fVertex3fvSUN (const GLfloat *, const GLfloat *);
+GLAPI void APIENTRY glTexCoord4fVertex4fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glTexCoord4fVertex4fvSUN (const GLfloat *, const GLfloat *);
+GLAPI void APIENTRY glTexCoord2fColor4ubVertex3fSUN (GLfloat, GLfloat, GLubyte, GLubyte, GLubyte, GLubyte, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glTexCoord2fColor4ubVertex3fvSUN (const GLfloat *, const GLubyte *, const GLfloat *);
+GLAPI void APIENTRY glTexCoord2fColor3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glTexCoord2fColor3fVertex3fvSUN (const GLfloat *, const GLfloat *, const GLfloat *);
+GLAPI void APIENTRY glTexCoord2fNormal3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glTexCoord2fNormal3fVertex3fvSUN (const GLfloat *, const GLfloat *, const GLfloat *);
+GLAPI void APIENTRY glTexCoord2fColor4fNormal3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glTexCoord2fColor4fNormal3fVertex3fvSUN (const GLfloat *, const GLfloat *, const GLfloat *, const GLfloat *);
+GLAPI void APIENTRY glTexCoord4fColor4fNormal3fVertex4fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glTexCoord4fColor4fNormal3fVertex4fvSUN (const GLfloat *, const GLfloat *, const GLfloat *, const GLfloat *);
+GLAPI void APIENTRY glReplacementCodeuiVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glReplacementCodeuiVertex3fvSUN (const GLuint *, const GLfloat *);
+GLAPI void APIENTRY glReplacementCodeuiColor4ubVertex3fSUN (GLuint, GLubyte, GLubyte, GLubyte, GLubyte, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glReplacementCodeuiColor4ubVertex3fvSUN (const GLuint *, const GLubyte *, const GLfloat *);
+GLAPI void APIENTRY glReplacementCodeuiColor3fVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glReplacementCodeuiColor3fVertex3fvSUN (const GLuint *, const GLfloat *, const GLfloat *);
+GLAPI void APIENTRY glReplacementCodeuiNormal3fVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glReplacementCodeuiNormal3fVertex3fvSUN (const GLuint *, const GLfloat *, const GLfloat *);
+GLAPI void APIENTRY glReplacementCodeuiColor4fNormal3fVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glReplacementCodeuiColor4fNormal3fVertex3fvSUN (const GLuint *, const GLfloat *, const GLfloat *, const GLfloat *);
+GLAPI void APIENTRY glReplacementCodeuiTexCoord2fVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glReplacementCodeuiTexCoord2fVertex3fvSUN (const GLuint *, const GLfloat *, const GLfloat *);
+GLAPI void APIENTRY glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN (const GLuint *, const GLfloat *, const GLfloat *, const GLfloat *);
+GLAPI void APIENTRY glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN (const GLuint *, const GLfloat *, const GLfloat *, const GLfloat *, const GLfloat *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLCOLOR4UBVERTEX2FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLCOLOR4UBVERTEX2FVSUNPROC) (const GLubyte *c, const GLfloat *v);
+typedef void (APIENTRYP PFNGLCOLOR4UBVERTEX3FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLCOLOR4UBVERTEX3FVSUNPROC) (const GLubyte *c, const GLfloat *v);
+typedef void (APIENTRYP PFNGLCOLOR3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLCOLOR3FVERTEX3FVSUNPROC) (const GLfloat *c, const GLfloat *v);
+typedef void (APIENTRYP PFNGLNORMAL3FVERTEX3FSUNPROC) (GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *c, const GLfloat *n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLTEXCOORD2FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLTEXCOORD2FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *v);
+typedef void (APIENTRYP PFNGLTEXCOORD4FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLTEXCOORD4FVERTEX4FVSUNPROC) (const GLfloat *tc, const GLfloat *v);
+typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR4UBVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR4UBVERTEX3FVSUNPROC) (const GLfloat *tc, const GLubyte *c, const GLfloat *v);
+typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR3FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *c, const GLfloat *v);
+typedef void (APIENTRYP PFNGLTEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLTEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FVSUNPROC) (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUIVERTEX3FSUNPROC) (GLuint rc, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUIVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FSUNPROC) (GLuint rc, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FVSUNPROC) (const GLuint *rc, const GLubyte *c, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FSUNPROC) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *c, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *tc, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *tc, const GLfloat *n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+#endif
+
+#ifndef GL_EXT_blend_func_separate
+#define GL_EXT_blend_func_separate 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendFuncSeparateEXT (GLenum, GLenum, GLenum, GLenum);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEEXTPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+#endif
+
+#ifndef GL_INGR_blend_func_separate
+#define GL_INGR_blend_func_separate 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendFuncSeparateINGR (GLenum, GLenum, GLenum, GLenum);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEINGRPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+#endif
+
+#ifndef GL_INGR_color_clamp
+#define GL_INGR_color_clamp 1
+#endif
+
+#ifndef GL_INGR_interlace_read
+#define GL_INGR_interlace_read 1
+#endif
+
+#ifndef GL_EXT_stencil_wrap
+#define GL_EXT_stencil_wrap 1
+#endif
+
+#ifndef GL_EXT_422_pixels
+#define GL_EXT_422_pixels 1
+#endif
+
+#ifndef GL_NV_texgen_reflection
+#define GL_NV_texgen_reflection 1
+#endif
+
+#ifndef GL_SUN_convolution_border_modes
+#define GL_SUN_convolution_border_modes 1
+#endif
+
+#ifndef GL_EXT_texture_env_add
+#define GL_EXT_texture_env_add 1
+#endif
+
+#ifndef GL_EXT_texture_lod_bias
+#define GL_EXT_texture_lod_bias 1
+#endif
+
+#ifndef GL_EXT_texture_filter_anisotropic
+#define GL_EXT_texture_filter_anisotropic 1
+#endif
+
+#ifndef GL_EXT_vertex_weighting
+#define GL_EXT_vertex_weighting 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexWeightfEXT (GLfloat);
+GLAPI void APIENTRY glVertexWeightfvEXT (const GLfloat *);
+GLAPI void APIENTRY glVertexWeightPointerEXT (GLsizei, GLenum, GLsizei, const GLvoid *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLVERTEXWEIGHTFEXTPROC) (GLfloat weight);
+typedef void (APIENTRYP PFNGLVERTEXWEIGHTFVEXTPROC) (const GLfloat *weight);
+typedef void (APIENTRYP PFNGLVERTEXWEIGHTPOINTEREXTPROC) (GLsizei size, GLenum type, GLsizei stride, const GLvoid *pointer);
+#endif
+
+#ifndef GL_NV_light_max_exponent
+#define GL_NV_light_max_exponent 1
+#endif
+
+#ifndef GL_NV_vertex_array_range
+#define GL_NV_vertex_array_range 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFlushVertexArrayRangeNV (void);
+GLAPI void APIENTRY glVertexArrayRangeNV (GLsizei, const GLvoid *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLFLUSHVERTEXARRAYRANGENVPROC) (void);
+typedef void (APIENTRYP PFNGLVERTEXARRAYRANGENVPROC) (GLsizei length, const GLvoid *pointer);
+#endif
+
+#ifndef GL_NV_register_combiners
+#define GL_NV_register_combiners 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glCombinerParameterfvNV (GLenum, const GLfloat *);
+GLAPI void APIENTRY glCombinerParameterfNV (GLenum, GLfloat);
+GLAPI void APIENTRY glCombinerParameterivNV (GLenum, const GLint *);
+GLAPI void APIENTRY glCombinerParameteriNV (GLenum, GLint);
+GLAPI void APIENTRY glCombinerInputNV (GLenum, GLenum, GLenum, GLenum, GLenum, GLenum);
+GLAPI void APIENTRY glCombinerOutputNV (GLenum, GLenum, GLenum, GLenum, GLenum, GLenum, GLenum, GLboolean, GLboolean, GLboolean);
+GLAPI void APIENTRY glFinalCombinerInputNV (GLenum, GLenum, GLenum, GLenum);
+GLAPI void APIENTRY glGetCombinerInputParameterfvNV (GLenum, GLenum, GLenum, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetCombinerInputParameterivNV (GLenum, GLenum, GLenum, GLenum, GLint *);
+GLAPI void APIENTRY glGetCombinerOutputParameterfvNV (GLenum, GLenum, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetCombinerOutputParameterivNV (GLenum, GLenum, GLenum, GLint *);
+GLAPI void APIENTRY glGetFinalCombinerInputParameterfvNV (GLenum, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetFinalCombinerInputParameterivNV (GLenum, GLenum, GLint *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLCOMBINERPARAMETERFVNVPROC) (GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLCOMBINERPARAMETERFNVPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLCOMBINERPARAMETERIVNVPROC) (GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLCOMBINERPARAMETERINVPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLCOMBINERINPUTNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage);
+typedef void (APIENTRYP PFNGLCOMBINEROUTPUTNVPROC) (GLenum stage, GLenum portion, GLenum abOutput, GLenum cdOutput, GLenum sumOutput, GLenum scale, GLenum bias, GLboolean abDotProduct, GLboolean cdDotProduct, GLboolean muxSum);
+typedef void (APIENTRYP PFNGLFINALCOMBINERINPUTNVPROC) (GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage);
+typedef void (APIENTRYP PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC) (GLenum variable, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC) (GLenum variable, GLenum pname, GLint *params);
+#endif
+
+#ifndef GL_NV_fog_distance
+#define GL_NV_fog_distance 1
+#endif
+
+#ifndef GL_NV_texgen_emboss
+#define GL_NV_texgen_emboss 1
+#endif
+
+#ifndef GL_NV_blend_square
+#define GL_NV_blend_square 1
+#endif
+
+#ifndef GL_NV_texture_env_combine4
+#define GL_NV_texture_env_combine4 1
+#endif
+
+#ifndef GL_MESA_resize_buffers
+#define GL_MESA_resize_buffers 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glResizeBuffersMESA (void);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLRESIZEBUFFERSMESAPROC) (void);
+#endif
+
+#ifndef GL_MESA_window_pos
+#define GL_MESA_window_pos 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glWindowPos2dMESA (GLdouble, GLdouble);
+GLAPI void APIENTRY glWindowPos2dvMESA (const GLdouble *);
+GLAPI void APIENTRY glWindowPos2fMESA (GLfloat, GLfloat);
+GLAPI void APIENTRY glWindowPos2fvMESA (const GLfloat *);
+GLAPI void APIENTRY glWindowPos2iMESA (GLint, GLint);
+GLAPI void APIENTRY glWindowPos2ivMESA (const GLint *);
+GLAPI void APIENTRY glWindowPos2sMESA (GLshort, GLshort);
+GLAPI void APIENTRY glWindowPos2svMESA (const GLshort *);
+GLAPI void APIENTRY glWindowPos3dMESA (GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glWindowPos3dvMESA (const GLdouble *);
+GLAPI void APIENTRY glWindowPos3fMESA (GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glWindowPos3fvMESA (const GLfloat *);
+GLAPI void APIENTRY glWindowPos3iMESA (GLint, GLint, GLint);
+GLAPI void APIENTRY glWindowPos3ivMESA (const GLint *);
+GLAPI void APIENTRY glWindowPos3sMESA (GLshort, GLshort, GLshort);
+GLAPI void APIENTRY glWindowPos3svMESA (const GLshort *);
+GLAPI void APIENTRY glWindowPos4dMESA (GLdouble, GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glWindowPos4dvMESA (const GLdouble *);
+GLAPI void APIENTRY glWindowPos4fMESA (GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glWindowPos4fvMESA (const GLfloat *);
+GLAPI void APIENTRY glWindowPos4iMESA (GLint, GLint, GLint, GLint);
+GLAPI void APIENTRY glWindowPos4ivMESA (const GLint *);
+GLAPI void APIENTRY glWindowPos4sMESA (GLshort, GLshort, GLshort, GLshort);
+GLAPI void APIENTRY glWindowPos4svMESA (const GLshort *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLWINDOWPOS2DMESAPROC) (GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2DVMESAPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2FMESAPROC) (GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2FVMESAPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2IMESAPROC) (GLint x, GLint y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2IVMESAPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2SMESAPROC) (GLshort x, GLshort y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2SVMESAPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3DMESAPROC) (GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3DVMESAPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3FMESAPROC) (GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3FVMESAPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3IMESAPROC) (GLint x, GLint y, GLint z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3IVMESAPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3SMESAPROC) (GLshort x, GLshort y, GLshort z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3SVMESAPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS4DMESAPROC) (GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLWINDOWPOS4DVMESAPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS4FMESAPROC) (GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLWINDOWPOS4FVMESAPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS4IMESAPROC) (GLint x, GLint y, GLint z, GLint w);
+typedef void (APIENTRYP PFNGLWINDOWPOS4IVMESAPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS4SMESAPROC) (GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (APIENTRYP PFNGLWINDOWPOS4SVMESAPROC) (const GLshort *v);
+#endif
+
+#ifndef GL_IBM_cull_vertex
+#define GL_IBM_cull_vertex 1
+#endif
+
+#ifndef GL_IBM_multimode_draw_arrays
+#define GL_IBM_multimode_draw_arrays 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMultiModeDrawArraysIBM (const GLenum *, const GLint *, const GLsizei *, GLsizei, GLint);
+GLAPI void APIENTRY glMultiModeDrawElementsIBM (const GLenum *, const GLsizei *, GLenum, const GLvoid* const *, GLsizei, GLint);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLMULTIMODEDRAWARRAYSIBMPROC) (const GLenum *mode, const GLint *first, const GLsizei *count, GLsizei primcount, GLint modestride);
+typedef void (APIENTRYP PFNGLMULTIMODEDRAWELEMENTSIBMPROC) (const GLenum *mode, const GLsizei *count, GLenum type, const GLvoid* const *indices, GLsizei primcount, GLint modestride);
+#endif
+
+#ifndef GL_IBM_vertex_array_lists
+#define GL_IBM_vertex_array_lists 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glColorPointerListIBM (GLint, GLenum, GLint, const GLvoid* *, GLint);
+GLAPI void APIENTRY glSecondaryColorPointerListIBM (GLint, GLenum, GLint, const GLvoid* *, GLint);
+GLAPI void APIENTRY glEdgeFlagPointerListIBM (GLint, const GLboolean* *, GLint);
+GLAPI void APIENTRY glFogCoordPointerListIBM (GLenum, GLint, const GLvoid* *, GLint);
+GLAPI void APIENTRY glIndexPointerListIBM (GLenum, GLint, const GLvoid* *, GLint);
+GLAPI void APIENTRY glNormalPointerListIBM (GLenum, GLint, const GLvoid* *, GLint);
+GLAPI void APIENTRY glTexCoordPointerListIBM (GLint, GLenum, GLint, const GLvoid* *, GLint);
+GLAPI void APIENTRY glVertexPointerListIBM (GLint, GLenum, GLint, const GLvoid* *, GLint);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride);
+typedef void (APIENTRYP PFNGLSECONDARYCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride);
+typedef void (APIENTRYP PFNGLEDGEFLAGPOINTERLISTIBMPROC) (GLint stride, const GLboolean* *pointer, GLint ptrstride);
+typedef void (APIENTRYP PFNGLFOGCOORDPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride);
+typedef void (APIENTRYP PFNGLINDEXPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride);
+typedef void (APIENTRYP PFNGLNORMALPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride);
+typedef void (APIENTRYP PFNGLTEXCOORDPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride);
+typedef void (APIENTRYP PFNGLVERTEXPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride);
+#endif
+
+#ifndef GL_SGIX_subsample
+#define GL_SGIX_subsample 1
+#endif
+
+#ifndef GL_SGIX_ycrcba
+#define GL_SGIX_ycrcba 1
+#endif
+
+#ifndef GL_SGIX_ycrcb_subsample
+#define GL_SGIX_ycrcb_subsample 1
+#endif
+
+#ifndef GL_SGIX_depth_pass_instrument
+#define GL_SGIX_depth_pass_instrument 1
+#endif
+
+#ifndef GL_3DFX_texture_compression_FXT1
+#define GL_3DFX_texture_compression_FXT1 1
+#endif
+
+#ifndef GL_3DFX_multisample
+#define GL_3DFX_multisample 1
+#endif
+
+#ifndef GL_3DFX_tbuffer
+#define GL_3DFX_tbuffer 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTbufferMask3DFX (GLuint);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLTBUFFERMASK3DFXPROC) (GLuint mask);
+#endif
+
+#ifndef GL_EXT_multisample
+#define GL_EXT_multisample 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glSampleMaskEXT (GLclampf, GLboolean);
+GLAPI void APIENTRY glSamplePatternEXT (GLenum);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLSAMPLEMASKEXTPROC) (GLclampf value, GLboolean invert);
+typedef void (APIENTRYP PFNGLSAMPLEPATTERNEXTPROC) (GLenum pattern);
+#endif
+
+#ifndef GL_SGIX_vertex_preclip
+#define GL_SGIX_vertex_preclip 1
+#endif
+
+#ifndef GL_SGIX_convolution_accuracy
+#define GL_SGIX_convolution_accuracy 1
+#endif
+
+#ifndef GL_SGIX_resample
+#define GL_SGIX_resample 1
+#endif
+
+#ifndef GL_SGIS_point_line_texgen
+#define GL_SGIS_point_line_texgen 1
+#endif
+
+#ifndef GL_SGIS_texture_color_mask
+#define GL_SGIS_texture_color_mask 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTextureColorMaskSGIS (GLboolean, GLboolean, GLboolean, GLboolean);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLTEXTURECOLORMASKSGISPROC) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+#endif
+
+#ifndef GL_SGIX_igloo_interface
+#define GL_SGIX_igloo_interface 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glIglooInterfaceSGIX (GLenum, const GLvoid *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLIGLOOINTERFACESGIXPROC) (GLenum pname, const GLvoid *params);
+#endif
+
+#ifndef GL_EXT_texture_env_dot3
+#define GL_EXT_texture_env_dot3 1
+#endif
+
+#ifndef GL_ATI_texture_mirror_once
+#define GL_ATI_texture_mirror_once 1
+#endif
+
+#ifndef GL_NV_fence
+#define GL_NV_fence 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDeleteFencesNV (GLsizei, const GLuint *);
+GLAPI void APIENTRY glGenFencesNV (GLsizei, GLuint *);
+GLAPI GLboolean APIENTRY glIsFenceNV (GLuint);
+GLAPI GLboolean APIENTRY glTestFenceNV (GLuint);
+GLAPI void APIENTRY glGetFenceivNV (GLuint, GLenum, GLint *);
+GLAPI void APIENTRY glFinishFenceNV (GLuint);
+GLAPI void APIENTRY glSetFenceNV (GLuint, GLenum);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLDELETEFENCESNVPROC) (GLsizei n, const GLuint *fences);
+typedef void (APIENTRYP PFNGLGENFENCESNVPROC) (GLsizei n, GLuint *fences);
+typedef GLboolean (APIENTRYP PFNGLISFENCENVPROC) (GLuint fence);
+typedef GLboolean (APIENTRYP PFNGLTESTFENCENVPROC) (GLuint fence);
+typedef void (APIENTRYP PFNGLGETFENCEIVNVPROC) (GLuint fence, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLFINISHFENCENVPROC) (GLuint fence);
+typedef void (APIENTRYP PFNGLSETFENCENVPROC) (GLuint fence, GLenum condition);
+#endif
+
+#ifndef GL_NV_evaluators
+#define GL_NV_evaluators 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMapControlPointsNV (GLenum, GLuint, GLenum, GLsizei, GLsizei, GLint, GLint, GLboolean, const GLvoid *);
+GLAPI void APIENTRY glMapParameterivNV (GLenum, GLenum, const GLint *);
+GLAPI void APIENTRY glMapParameterfvNV (GLenum, GLenum, const GLfloat *);
+GLAPI void APIENTRY glGetMapControlPointsNV (GLenum, GLuint, GLenum, GLsizei, GLsizei, GLboolean, GLvoid *);
+GLAPI void APIENTRY glGetMapParameterivNV (GLenum, GLenum, GLint *);
+GLAPI void APIENTRY glGetMapParameterfvNV (GLenum, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetMapAttribParameterivNV (GLenum, GLuint, GLenum, GLint *);
+GLAPI void APIENTRY glGetMapAttribParameterfvNV (GLenum, GLuint, GLenum, GLfloat *);
+GLAPI void APIENTRY glEvalMapsNV (GLenum, GLenum);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLint uorder, GLint vorder, GLboolean packed, const GLvoid *points);
+typedef void (APIENTRYP PFNGLMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLGETMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLboolean packed, GLvoid *points);
+typedef void (APIENTRYP PFNGLGETMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETMAPATTRIBPARAMETERIVNVPROC) (GLenum target, GLuint index, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETMAPATTRIBPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLEVALMAPSNVPROC) (GLenum target, GLenum mode);
+#endif
+
+#ifndef GL_NV_packed_depth_stencil
+#define GL_NV_packed_depth_stencil 1
+#endif
+
+#ifndef GL_NV_register_combiners2
+#define GL_NV_register_combiners2 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glCombinerStageParameterfvNV (GLenum, GLenum, const GLfloat *);
+GLAPI void APIENTRY glGetCombinerStageParameterfvNV (GLenum, GLenum, GLfloat *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, GLfloat *params);
+#endif
+
+#ifndef GL_NV_texture_compression_vtc
+#define GL_NV_texture_compression_vtc 1
+#endif
+
+#ifndef GL_NV_texture_rectangle
+#define GL_NV_texture_rectangle 1
+#endif
+
+#ifndef GL_NV_texture_shader
+#define GL_NV_texture_shader 1
+#endif
+
+#ifndef GL_NV_texture_shader2
+#define GL_NV_texture_shader2 1
+#endif
+
+#ifndef GL_NV_vertex_array_range2
+#define GL_NV_vertex_array_range2 1
+#endif
+
+#ifndef GL_NV_vertex_program
+#define GL_NV_vertex_program 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLboolean APIENTRY glAreProgramsResidentNV (GLsizei, const GLuint *, GLboolean *);
+GLAPI void APIENTRY glBindProgramNV (GLenum, GLuint);
+GLAPI void APIENTRY glDeleteProgramsNV (GLsizei, const GLuint *);
+GLAPI void APIENTRY glExecuteProgramNV (GLenum, GLuint, const GLfloat *);
+GLAPI void APIENTRY glGenProgramsNV (GLsizei, GLuint *);
+GLAPI void APIENTRY glGetProgramParameterdvNV (GLenum, GLuint, GLenum, GLdouble *);
+GLAPI void APIENTRY glGetProgramParameterfvNV (GLenum, GLuint, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetProgramivNV (GLuint, GLenum, GLint *);
+GLAPI void APIENTRY glGetProgramStringNV (GLuint, GLenum, GLubyte *);
+GLAPI void APIENTRY glGetTrackMatrixivNV (GLenum, GLuint, GLenum, GLint *);
+GLAPI void APIENTRY glGetVertexAttribdvNV (GLuint, GLenum, GLdouble *);
+GLAPI void APIENTRY glGetVertexAttribfvNV (GLuint, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetVertexAttribivNV (GLuint, GLenum, GLint *);
+GLAPI void APIENTRY glGetVertexAttribPointervNV (GLuint, GLenum, GLvoid* *);
+GLAPI GLboolean APIENTRY glIsProgramNV (GLuint);
+GLAPI void APIENTRY glLoadProgramNV (GLenum, GLuint, GLsizei, const GLubyte *);
+GLAPI void APIENTRY glProgramParameter4dNV (GLenum, GLuint, GLdouble, GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glProgramParameter4dvNV (GLenum, GLuint, const GLdouble *);
+GLAPI void APIENTRY glProgramParameter4fNV (GLenum, GLuint, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glProgramParameter4fvNV (GLenum, GLuint, const GLfloat *);
+GLAPI void APIENTRY glProgramParameters4dvNV (GLenum, GLuint, GLuint, const GLdouble *);
+GLAPI void APIENTRY glProgramParameters4fvNV (GLenum, GLuint, GLuint, const GLfloat *);
+GLAPI void APIENTRY glRequestResidentProgramsNV (GLsizei, const GLuint *);
+GLAPI void APIENTRY glTrackMatrixNV (GLenum, GLuint, GLenum, GLenum);
+GLAPI void APIENTRY glVertexAttribPointerNV (GLuint, GLint, GLenum, GLsizei, const GLvoid *);
+GLAPI void APIENTRY glVertexAttrib1dNV (GLuint, GLdouble);
+GLAPI void APIENTRY glVertexAttrib1dvNV (GLuint, const GLdouble *);
+GLAPI void APIENTRY glVertexAttrib1fNV (GLuint, GLfloat);
+GLAPI void APIENTRY glVertexAttrib1fvNV (GLuint, const GLfloat *);
+GLAPI void APIENTRY glVertexAttrib1sNV (GLuint, GLshort);
+GLAPI void APIENTRY glVertexAttrib1svNV (GLuint, const GLshort *);
+GLAPI void APIENTRY glVertexAttrib2dNV (GLuint, GLdouble, GLdouble);
+GLAPI void APIENTRY glVertexAttrib2dvNV (GLuint, const GLdouble *);
+GLAPI void APIENTRY glVertexAttrib2fNV (GLuint, GLfloat, GLfloat);
+GLAPI void APIENTRY glVertexAttrib2fvNV (GLuint, const GLfloat *);
+GLAPI void APIENTRY glVertexAttrib2sNV (GLuint, GLshort, GLshort);
+GLAPI void APIENTRY glVertexAttrib2svNV (GLuint, const GLshort *);
+GLAPI void APIENTRY glVertexAttrib3dNV (GLuint, GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glVertexAttrib3dvNV (GLuint, const GLdouble *);
+GLAPI void APIENTRY glVertexAttrib3fNV (GLuint, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glVertexAttrib3fvNV (GLuint, const GLfloat *);
+GLAPI void APIENTRY glVertexAttrib3sNV (GLuint, GLshort, GLshort, GLshort);
+GLAPI void APIENTRY glVertexAttrib3svNV (GLuint, const GLshort *);
+GLAPI void APIENTRY glVertexAttrib4dNV (GLuint, GLdouble, GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glVertexAttrib4dvNV (GLuint, const GLdouble *);
+GLAPI void APIENTRY glVertexAttrib4fNV (GLuint, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glVertexAttrib4fvNV (GLuint, const GLfloat *);
+GLAPI void APIENTRY glVertexAttrib4sNV (GLuint, GLshort, GLshort, GLshort, GLshort);
+GLAPI void APIENTRY glVertexAttrib4svNV (GLuint, const GLshort *);
+GLAPI void APIENTRY glVertexAttrib4ubNV (GLuint, GLubyte, GLubyte, GLubyte, GLubyte);
+GLAPI void APIENTRY glVertexAttrib4ubvNV (GLuint, const GLubyte *);
+GLAPI void APIENTRY glVertexAttribs1dvNV (GLuint, GLsizei, const GLdouble *);
+GLAPI void APIENTRY glVertexAttribs1fvNV (GLuint, GLsizei, const GLfloat *);
+GLAPI void APIENTRY glVertexAttribs1svNV (GLuint, GLsizei, const GLshort *);
+GLAPI void APIENTRY glVertexAttribs2dvNV (GLuint, GLsizei, const GLdouble *);
+GLAPI void APIENTRY glVertexAttribs2fvNV (GLuint, GLsizei, const GLfloat *);
+GLAPI void APIENTRY glVertexAttribs2svNV (GLuint, GLsizei, const GLshort *);
+GLAPI void APIENTRY glVertexAttribs3dvNV (GLuint, GLsizei, const GLdouble *);
+GLAPI void APIENTRY glVertexAttribs3fvNV (GLuint, GLsizei, const GLfloat *);
+GLAPI void APIENTRY glVertexAttribs3svNV (GLuint, GLsizei, const GLshort *);
+GLAPI void APIENTRY glVertexAttribs4dvNV (GLuint, GLsizei, const GLdouble *);
+GLAPI void APIENTRY glVertexAttribs4fvNV (GLuint, GLsizei, const GLfloat *);
+GLAPI void APIENTRY glVertexAttribs4svNV (GLuint, GLsizei, const GLshort *);
+GLAPI void APIENTRY glVertexAttribs4ubvNV (GLuint, GLsizei, const GLubyte *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef GLboolean (APIENTRYP PFNGLAREPROGRAMSRESIDENTNVPROC) (GLsizei n, const GLuint *programs, GLboolean *residences);
+typedef void (APIENTRYP PFNGLBINDPROGRAMNVPROC) (GLenum target, GLuint id);
+typedef void (APIENTRYP PFNGLDELETEPROGRAMSNVPROC) (GLsizei n, const GLuint *programs);
+typedef void (APIENTRYP PFNGLEXECUTEPROGRAMNVPROC) (GLenum target, GLuint id, const GLfloat *params);
+typedef void (APIENTRYP PFNGLGENPROGRAMSNVPROC) (GLsizei n, GLuint *programs);
+typedef void (APIENTRYP PFNGLGETPROGRAMPARAMETERDVNVPROC) (GLenum target, GLuint index, GLenum pname, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMIVNVPROC) (GLuint id, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMSTRINGNVPROC) (GLuint id, GLenum pname, GLubyte *program);
+typedef void (APIENTRYP PFNGLGETTRACKMATRIXIVNVPROC) (GLenum target, GLuint address, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBDVNVPROC) (GLuint index, GLenum pname, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBFVNVPROC) (GLuint index, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVNVPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVNVPROC) (GLuint index, GLenum pname, GLvoid* *pointer);
+typedef GLboolean (APIENTRYP PFNGLISPROGRAMNVPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLLOADPROGRAMNVPROC) (GLenum target, GLuint id, GLsizei len, const GLubyte *program);
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETER4DNVPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETER4DVNVPROC) (GLenum target, GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETER4FNVPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETER4FVNVPROC) (GLenum target, GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETERS4DVNVPROC) (GLenum target, GLuint index, GLuint count, const GLdouble *v);
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETERS4FVNVPROC) (GLenum target, GLuint index, GLuint count, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREQUESTRESIDENTPROGRAMSNVPROC) (GLsizei n, const GLuint *programs);
+typedef void (APIENTRYP PFNGLTRACKMATRIXNVPROC) (GLenum target, GLuint address, GLenum matrix, GLenum transform);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERNVPROC) (GLuint index, GLint fsize, GLenum type, GLsizei stride, const GLvoid *pointer);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1DNVPROC) (GLuint index, GLdouble x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1DVNVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1FNVPROC) (GLuint index, GLfloat x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1FVNVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1SNVPROC) (GLuint index, GLshort x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1SVNVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2DNVPROC) (GLuint index, GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2DVNVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2FNVPROC) (GLuint index, GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2FVNVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2SNVPROC) (GLuint index, GLshort x, GLshort y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2SVNVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3DVNVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3FVNVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3SVNVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4DVNVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4FVNVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4SVNVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4UBNVPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4UBVNVPROC) (GLuint index, const GLubyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS1DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS1FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS1SVNVPROC) (GLuint index, GLsizei count, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS2DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS2FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS2SVNVPROC) (GLuint index, GLsizei count, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS3DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS3FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS3SVNVPROC) (GLuint index, GLsizei count, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS4DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS4FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS4SVNVPROC) (GLuint index, GLsizei count, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS4UBVNVPROC) (GLuint index, GLsizei count, const GLubyte *v);
+#endif
+
+#ifndef GL_SGIX_texture_coordinate_clamp
+#define GL_SGIX_texture_coordinate_clamp 1
+#endif
+
+#ifndef GL_SGIX_scalebias_hint
+#define GL_SGIX_scalebias_hint 1
+#endif
+
+#ifndef GL_OML_interlace
+#define GL_OML_interlace 1
+#endif
+
+#ifndef GL_OML_subsample
+#define GL_OML_subsample 1
+#endif
+
+#ifndef GL_OML_resample
+#define GL_OML_resample 1
+#endif
+
+#ifndef GL_NV_copy_depth_to_color
+#define GL_NV_copy_depth_to_color 1
+#endif
+
+#ifndef GL_ATI_envmap_bumpmap
+#define GL_ATI_envmap_bumpmap 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTexBumpParameterivATI (GLenum, const GLint *);
+GLAPI void APIENTRY glTexBumpParameterfvATI (GLenum, const GLfloat *);
+GLAPI void APIENTRY glGetTexBumpParameterivATI (GLenum, GLint *);
+GLAPI void APIENTRY glGetTexBumpParameterfvATI (GLenum, GLfloat *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLTEXBUMPPARAMETERIVATIPROC) (GLenum pname, const GLint *param);
+typedef void (APIENTRYP PFNGLTEXBUMPPARAMETERFVATIPROC) (GLenum pname, const GLfloat *param);
+typedef void (APIENTRYP PFNGLGETTEXBUMPPARAMETERIVATIPROC) (GLenum pname, GLint *param);
+typedef void (APIENTRYP PFNGLGETTEXBUMPPARAMETERFVATIPROC) (GLenum pname, GLfloat *param);
+#endif
+
+#ifndef GL_ATI_fragment_shader
+#define GL_ATI_fragment_shader 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLuint APIENTRY glGenFragmentShadersATI (GLuint);
+GLAPI void APIENTRY glBindFragmentShaderATI (GLuint);
+GLAPI void APIENTRY glDeleteFragmentShaderATI (GLuint);
+GLAPI void APIENTRY glBeginFragmentShaderATI (void);
+GLAPI void APIENTRY glEndFragmentShaderATI (void);
+GLAPI void APIENTRY glPassTexCoordATI (GLuint, GLuint, GLenum);
+GLAPI void APIENTRY glSampleMapATI (GLuint, GLuint, GLenum);
+GLAPI void APIENTRY glColorFragmentOp1ATI (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint);
+GLAPI void APIENTRY glColorFragmentOp2ATI (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint);
+GLAPI void APIENTRY glColorFragmentOp3ATI (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint);
+GLAPI void APIENTRY glAlphaFragmentOp1ATI (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint);
+GLAPI void APIENTRY glAlphaFragmentOp2ATI (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint);
+GLAPI void APIENTRY glAlphaFragmentOp3ATI (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint);
+GLAPI void APIENTRY glSetFragmentShaderConstantATI (GLuint, const GLfloat *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef GLuint (APIENTRYP PFNGLGENFRAGMENTSHADERSATIPROC) (GLuint range);
+typedef void (APIENTRYP PFNGLBINDFRAGMENTSHADERATIPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLDELETEFRAGMENTSHADERATIPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLBEGINFRAGMENTSHADERATIPROC) (void);
+typedef void (APIENTRYP PFNGLENDFRAGMENTSHADERATIPROC) (void);
+typedef void (APIENTRYP PFNGLPASSTEXCOORDATIPROC) (GLuint dst, GLuint coord, GLenum swizzle);
+typedef void (APIENTRYP PFNGLSAMPLEMAPATIPROC) (GLuint dst, GLuint interp, GLenum swizzle);
+typedef void (APIENTRYP PFNGLCOLORFRAGMENTOP1ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod);
+typedef void (APIENTRYP PFNGLCOLORFRAGMENTOP2ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod);
+typedef void (APIENTRYP PFNGLCOLORFRAGMENTOP3ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod);
+typedef void (APIENTRYP PFNGLALPHAFRAGMENTOP1ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod);
+typedef void (APIENTRYP PFNGLALPHAFRAGMENTOP2ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod);
+typedef void (APIENTRYP PFNGLALPHAFRAGMENTOP3ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod);
+typedef void (APIENTRYP PFNGLSETFRAGMENTSHADERCONSTANTATIPROC) (GLuint dst, const GLfloat *value);
+#endif
+
+#ifndef GL_ATI_pn_triangles
+#define GL_ATI_pn_triangles 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPNTrianglesiATI (GLenum, GLint);
+GLAPI void APIENTRY glPNTrianglesfATI (GLenum, GLfloat);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLPNTRIANGLESIATIPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLPNTRIANGLESFATIPROC) (GLenum pname, GLfloat param);
+#endif
+
+#ifndef GL_ATI_vertex_array_object
+#define GL_ATI_vertex_array_object 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLuint APIENTRY glNewObjectBufferATI (GLsizei, const GLvoid *, GLenum);
+GLAPI GLboolean APIENTRY glIsObjectBufferATI (GLuint);
+GLAPI void APIENTRY glUpdateObjectBufferATI (GLuint, GLuint, GLsizei, const GLvoid *, GLenum);
+GLAPI void APIENTRY glGetObjectBufferfvATI (GLuint, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetObjectBufferivATI (GLuint, GLenum, GLint *);
+GLAPI void APIENTRY glFreeObjectBufferATI (GLuint);
+GLAPI void APIENTRY glArrayObjectATI (GLenum, GLint, GLenum, GLsizei, GLuint, GLuint);
+GLAPI void APIENTRY glGetArrayObjectfvATI (GLenum, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetArrayObjectivATI (GLenum, GLenum, GLint *);
+GLAPI void APIENTRY glVariantArrayObjectATI (GLuint, GLenum, GLsizei, GLuint, GLuint);
+GLAPI void APIENTRY glGetVariantArrayObjectfvATI (GLuint, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetVariantArrayObjectivATI (GLuint, GLenum, GLint *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef GLuint (APIENTRYP PFNGLNEWOBJECTBUFFERATIPROC) (GLsizei size, const GLvoid *pointer, GLenum usage);
+typedef GLboolean (APIENTRYP PFNGLISOBJECTBUFFERATIPROC) (GLuint buffer);
+typedef void (APIENTRYP PFNGLUPDATEOBJECTBUFFERATIPROC) (GLuint buffer, GLuint offset, GLsizei size, const GLvoid *pointer, GLenum preserve);
+typedef void (APIENTRYP PFNGLGETOBJECTBUFFERFVATIPROC) (GLuint buffer, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETOBJECTBUFFERIVATIPROC) (GLuint buffer, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLFREEOBJECTBUFFERATIPROC) (GLuint buffer);
+typedef void (APIENTRYP PFNGLARRAYOBJECTATIPROC) (GLenum array, GLint size, GLenum type, GLsizei stride, GLuint buffer, GLuint offset);
+typedef void (APIENTRYP PFNGLGETARRAYOBJECTFVATIPROC) (GLenum array, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETARRAYOBJECTIVATIPROC) (GLenum array, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLVARIANTARRAYOBJECTATIPROC) (GLuint id, GLenum type, GLsizei stride, GLuint buffer, GLuint offset);
+typedef void (APIENTRYP PFNGLGETVARIANTARRAYOBJECTFVATIPROC) (GLuint id, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETVARIANTARRAYOBJECTIVATIPROC) (GLuint id, GLenum pname, GLint *params);
+#endif
+
+#ifndef GL_EXT_vertex_shader
+#define GL_EXT_vertex_shader 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBeginVertexShaderEXT (void);
+GLAPI void APIENTRY glEndVertexShaderEXT (void);
+GLAPI void APIENTRY glBindVertexShaderEXT (GLuint);
+GLAPI GLuint APIENTRY glGenVertexShadersEXT (GLuint);
+GLAPI void APIENTRY glDeleteVertexShaderEXT (GLuint);
+GLAPI void APIENTRY glShaderOp1EXT (GLenum, GLuint, GLuint);
+GLAPI void APIENTRY glShaderOp2EXT (GLenum, GLuint, GLuint, GLuint);
+GLAPI void APIENTRY glShaderOp3EXT (GLenum, GLuint, GLuint, GLuint, GLuint);
+GLAPI void APIENTRY glSwizzleEXT (GLuint, GLuint, GLenum, GLenum, GLenum, GLenum);
+GLAPI void APIENTRY glWriteMaskEXT (GLuint, GLuint, GLenum, GLenum, GLenum, GLenum);
+GLAPI void APIENTRY glInsertComponentEXT (GLuint, GLuint, GLuint);
+GLAPI void APIENTRY glExtractComponentEXT (GLuint, GLuint, GLuint);
+GLAPI GLuint APIENTRY glGenSymbolsEXT (GLenum, GLenum, GLenum, GLuint);
+GLAPI void APIENTRY glSetInvariantEXT (GLuint, GLenum, const GLvoid *);
+GLAPI void APIENTRY glSetLocalConstantEXT (GLuint, GLenum, const GLvoid *);
+GLAPI void APIENTRY glVariantbvEXT (GLuint, const GLbyte *);
+GLAPI void APIENTRY glVariantsvEXT (GLuint, const GLshort *);
+GLAPI void APIENTRY glVariantivEXT (GLuint, const GLint *);
+GLAPI void APIENTRY glVariantfvEXT (GLuint, const GLfloat *);
+GLAPI void APIENTRY glVariantdvEXT (GLuint, const GLdouble *);
+GLAPI void APIENTRY glVariantubvEXT (GLuint, const GLubyte *);
+GLAPI void APIENTRY glVariantusvEXT (GLuint, const GLushort *);
+GLAPI void APIENTRY glVariantuivEXT (GLuint, const GLuint *);
+GLAPI void APIENTRY glVariantPointerEXT (GLuint, GLenum, GLuint, const GLvoid *);
+GLAPI void APIENTRY glEnableVariantClientStateEXT (GLuint);
+GLAPI void APIENTRY glDisableVariantClientStateEXT (GLuint);
+GLAPI GLuint APIENTRY glBindLightParameterEXT (GLenum, GLenum);
+GLAPI GLuint APIENTRY glBindMaterialParameterEXT (GLenum, GLenum);
+GLAPI GLuint APIENTRY glBindTexGenParameterEXT (GLenum, GLenum, GLenum);
+GLAPI GLuint APIENTRY glBindTextureUnitParameterEXT (GLenum, GLenum);
+GLAPI GLuint APIENTRY glBindParameterEXT (GLenum);
+GLAPI GLboolean APIENTRY glIsVariantEnabledEXT (GLuint, GLenum);
+GLAPI void APIENTRY glGetVariantBooleanvEXT (GLuint, GLenum, GLboolean *);
+GLAPI void APIENTRY glGetVariantIntegervEXT (GLuint, GLenum, GLint *);
+GLAPI void APIENTRY glGetVariantFloatvEXT (GLuint, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetVariantPointervEXT (GLuint, GLenum, GLvoid* *);
+GLAPI void APIENTRY glGetInvariantBooleanvEXT (GLuint, GLenum, GLboolean *);
+GLAPI void APIENTRY glGetInvariantIntegervEXT (GLuint, GLenum, GLint *);
+GLAPI void APIENTRY glGetInvariantFloatvEXT (GLuint, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetLocalConstantBooleanvEXT (GLuint, GLenum, GLboolean *);
+GLAPI void APIENTRY glGetLocalConstantIntegervEXT (GLuint, GLenum, GLint *);
+GLAPI void APIENTRY glGetLocalConstantFloatvEXT (GLuint, GLenum, GLfloat *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLBEGINVERTEXSHADEREXTPROC) (void);
+typedef void (APIENTRYP PFNGLENDVERTEXSHADEREXTPROC) (void);
+typedef void (APIENTRYP PFNGLBINDVERTEXSHADEREXTPROC) (GLuint id);
+typedef GLuint (APIENTRYP PFNGLGENVERTEXSHADERSEXTPROC) (GLuint range);
+typedef void (APIENTRYP PFNGLDELETEVERTEXSHADEREXTPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLSHADEROP1EXTPROC) (GLenum op, GLuint res, GLuint arg1);
+typedef void (APIENTRYP PFNGLSHADEROP2EXTPROC) (GLenum op, GLuint res, GLuint arg1, GLuint arg2);
+typedef void (APIENTRYP PFNGLSHADEROP3EXTPROC) (GLenum op, GLuint res, GLuint arg1, GLuint arg2, GLuint arg3);
+typedef void (APIENTRYP PFNGLSWIZZLEEXTPROC) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW);
+typedef void (APIENTRYP PFNGLWRITEMASKEXTPROC) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW);
+typedef void (APIENTRYP PFNGLINSERTCOMPONENTEXTPROC) (GLuint res, GLuint src, GLuint num);
+typedef void (APIENTRYP PFNGLEXTRACTCOMPONENTEXTPROC) (GLuint res, GLuint src, GLuint num);
+typedef GLuint (APIENTRYP PFNGLGENSYMBOLSEXTPROC) (GLenum datatype, GLenum storagetype, GLenum range, GLuint components);
+typedef void (APIENTRYP PFNGLSETINVARIANTEXTPROC) (GLuint id, GLenum type, const GLvoid *addr);
+typedef void (APIENTRYP PFNGLSETLOCALCONSTANTEXTPROC) (GLuint id, GLenum type, const GLvoid *addr);
+typedef void (APIENTRYP PFNGLVARIANTBVEXTPROC) (GLuint id, const GLbyte *addr);
+typedef void (APIENTRYP PFNGLVARIANTSVEXTPROC) (GLuint id, const GLshort *addr);
+typedef void (APIENTRYP PFNGLVARIANTIVEXTPROC) (GLuint id, const GLint *addr);
+typedef void (APIENTRYP PFNGLVARIANTFVEXTPROC) (GLuint id, const GLfloat *addr);
+typedef void (APIENTRYP PFNGLVARIANTDVEXTPROC) (GLuint id, const GLdouble *addr);
+typedef void (APIENTRYP PFNGLVARIANTUBVEXTPROC) (GLuint id, const GLubyte *addr);
+typedef void (APIENTRYP PFNGLVARIANTUSVEXTPROC) (GLuint id, const GLushort *addr);
+typedef void (APIENTRYP PFNGLVARIANTUIVEXTPROC) (GLuint id, const GLuint *addr);
+typedef void (APIENTRYP PFNGLVARIANTPOINTEREXTPROC) (GLuint id, GLenum type, GLuint stride, const GLvoid *addr);
+typedef void (APIENTRYP PFNGLENABLEVARIANTCLIENTSTATEEXTPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLDISABLEVARIANTCLIENTSTATEEXTPROC) (GLuint id);
+typedef GLuint (APIENTRYP PFNGLBINDLIGHTPARAMETEREXTPROC) (GLenum light, GLenum value);
+typedef GLuint (APIENTRYP PFNGLBINDMATERIALPARAMETEREXTPROC) (GLenum face, GLenum value);
+typedef GLuint (APIENTRYP PFNGLBINDTEXGENPARAMETEREXTPROC) (GLenum unit, GLenum coord, GLenum value);
+typedef GLuint (APIENTRYP PFNGLBINDTEXTUREUNITPARAMETEREXTPROC) (GLenum unit, GLenum value);
+typedef GLuint (APIENTRYP PFNGLBINDPARAMETEREXTPROC) (GLenum value);
+typedef GLboolean (APIENTRYP PFNGLISVARIANTENABLEDEXTPROC) (GLuint id, GLenum cap);
+typedef void (APIENTRYP PFNGLGETVARIANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data);
+typedef void (APIENTRYP PFNGLGETVARIANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data);
+typedef void (APIENTRYP PFNGLGETVARIANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data);
+typedef void (APIENTRYP PFNGLGETVARIANTPOINTERVEXTPROC) (GLuint id, GLenum value, GLvoid* *data);
+typedef void (APIENTRYP PFNGLGETINVARIANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data);
+typedef void (APIENTRYP PFNGLGETINVARIANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data);
+typedef void (APIENTRYP PFNGLGETINVARIANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data);
+typedef void (APIENTRYP PFNGLGETLOCALCONSTANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data);
+typedef void (APIENTRYP PFNGLGETLOCALCONSTANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data);
+typedef void (APIENTRYP PFNGLGETLOCALCONSTANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data);
+#endif
+
+#ifndef GL_ATI_vertex_streams
+#define GL_ATI_vertex_streams 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexStream1sATI (GLenum, GLshort);
+GLAPI void APIENTRY glVertexStream1svATI (GLenum, const GLshort *);
+GLAPI void APIENTRY glVertexStream1iATI (GLenum, GLint);
+GLAPI void APIENTRY glVertexStream1ivATI (GLenum, const GLint *);
+GLAPI void APIENTRY glVertexStream1fATI (GLenum, GLfloat);
+GLAPI void APIENTRY glVertexStream1fvATI (GLenum, const GLfloat *);
+GLAPI void APIENTRY glVertexStream1dATI (GLenum, GLdouble);
+GLAPI void APIENTRY glVertexStream1dvATI (GLenum, const GLdouble *);
+GLAPI void APIENTRY glVertexStream2sATI (GLenum, GLshort, GLshort);
+GLAPI void APIENTRY glVertexStream2svATI (GLenum, const GLshort *);
+GLAPI void APIENTRY glVertexStream2iATI (GLenum, GLint, GLint);
+GLAPI void APIENTRY glVertexStream2ivATI (GLenum, const GLint *);
+GLAPI void APIENTRY glVertexStream2fATI (GLenum, GLfloat, GLfloat);
+GLAPI void APIENTRY glVertexStream2fvATI (GLenum, const GLfloat *);
+GLAPI void APIENTRY glVertexStream2dATI (GLenum, GLdouble, GLdouble);
+GLAPI void APIENTRY glVertexStream2dvATI (GLenum, const GLdouble *);
+GLAPI void APIENTRY glVertexStream3sATI (GLenum, GLshort, GLshort, GLshort);
+GLAPI void APIENTRY glVertexStream3svATI (GLenum, const GLshort *);
+GLAPI void APIENTRY glVertexStream3iATI (GLenum, GLint, GLint, GLint);
+GLAPI void APIENTRY glVertexStream3ivATI (GLenum, const GLint *);
+GLAPI void APIENTRY glVertexStream3fATI (GLenum, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glVertexStream3fvATI (GLenum, const GLfloat *);
+GLAPI void APIENTRY glVertexStream3dATI (GLenum, GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glVertexStream3dvATI (GLenum, const GLdouble *);
+GLAPI void APIENTRY glVertexStream4sATI (GLenum, GLshort, GLshort, GLshort, GLshort);
+GLAPI void APIENTRY glVertexStream4svATI (GLenum, const GLshort *);
+GLAPI void APIENTRY glVertexStream4iATI (GLenum, GLint, GLint, GLint, GLint);
+GLAPI void APIENTRY glVertexStream4ivATI (GLenum, const GLint *);
+GLAPI void APIENTRY glVertexStream4fATI (GLenum, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glVertexStream4fvATI (GLenum, const GLfloat *);
+GLAPI void APIENTRY glVertexStream4dATI (GLenum, GLdouble, GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glVertexStream4dvATI (GLenum, const GLdouble *);
+GLAPI void APIENTRY glNormalStream3bATI (GLenum, GLbyte, GLbyte, GLbyte);
+GLAPI void APIENTRY glNormalStream3bvATI (GLenum, const GLbyte *);
+GLAPI void APIENTRY glNormalStream3sATI (GLenum, GLshort, GLshort, GLshort);
+GLAPI void APIENTRY glNormalStream3svATI (GLenum, const GLshort *);
+GLAPI void APIENTRY glNormalStream3iATI (GLenum, GLint, GLint, GLint);
+GLAPI void APIENTRY glNormalStream3ivATI (GLenum, const GLint *);
+GLAPI void APIENTRY glNormalStream3fATI (GLenum, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glNormalStream3fvATI (GLenum, const GLfloat *);
+GLAPI void APIENTRY glNormalStream3dATI (GLenum, GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glNormalStream3dvATI (GLenum, const GLdouble *);
+GLAPI void APIENTRY glClientActiveVertexStreamATI (GLenum);
+GLAPI void APIENTRY glVertexBlendEnviATI (GLenum, GLint);
+GLAPI void APIENTRY glVertexBlendEnvfATI (GLenum, GLfloat);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLVERTEXSTREAM1SATIPROC) (GLenum stream, GLshort x);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM1SVATIPROC) (GLenum stream, const GLshort *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM1IATIPROC) (GLenum stream, GLint x);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM1IVATIPROC) (GLenum stream, const GLint *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM1FATIPROC) (GLenum stream, GLfloat x);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM1FVATIPROC) (GLenum stream, const GLfloat *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM1DATIPROC) (GLenum stream, GLdouble x);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM1DVATIPROC) (GLenum stream, const GLdouble *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM2SATIPROC) (GLenum stream, GLshort x, GLshort y);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM2SVATIPROC) (GLenum stream, const GLshort *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM2IATIPROC) (GLenum stream, GLint x, GLint y);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM2IVATIPROC) (GLenum stream, const GLint *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM2FATIPROC) (GLenum stream, GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM2FVATIPROC) (GLenum stream, const GLfloat *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM2DATIPROC) (GLenum stream, GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM2DVATIPROC) (GLenum stream, const GLdouble *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM3SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM3SVATIPROC) (GLenum stream, const GLshort *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM3IATIPROC) (GLenum stream, GLint x, GLint y, GLint z);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM3IVATIPROC) (GLenum stream, const GLint *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM3FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM3FVATIPROC) (GLenum stream, const GLfloat *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM3DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM3DVATIPROC) (GLenum stream, const GLdouble *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM4SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM4SVATIPROC) (GLenum stream, const GLshort *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM4IATIPROC) (GLenum stream, GLint x, GLint y, GLint z, GLint w);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM4IVATIPROC) (GLenum stream, const GLint *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM4FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM4FVATIPROC) (GLenum stream, const GLfloat *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM4DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM4DVATIPROC) (GLenum stream, const GLdouble *coords);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3BATIPROC) (GLenum stream, GLbyte nx, GLbyte ny, GLbyte nz);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3BVATIPROC) (GLenum stream, const GLbyte *coords);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3SATIPROC) (GLenum stream, GLshort nx, GLshort ny, GLshort nz);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3SVATIPROC) (GLenum stream, const GLshort *coords);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3IATIPROC) (GLenum stream, GLint nx, GLint ny, GLint nz);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3IVATIPROC) (GLenum stream, const GLint *coords);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3FATIPROC) (GLenum stream, GLfloat nx, GLfloat ny, GLfloat nz);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3FVATIPROC) (GLenum stream, const GLfloat *coords);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3DATIPROC) (GLenum stream, GLdouble nx, GLdouble ny, GLdouble nz);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3DVATIPROC) (GLenum stream, const GLdouble *coords);
+typedef void (APIENTRYP PFNGLCLIENTACTIVEVERTEXSTREAMATIPROC) (GLenum stream);
+typedef void (APIENTRYP PFNGLVERTEXBLENDENVIATIPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLVERTEXBLENDENVFATIPROC) (GLenum pname, GLfloat param);
+#endif
+
+#ifndef GL_ATI_element_array
+#define GL_ATI_element_array 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glElementPointerATI (GLenum, const GLvoid *);
+GLAPI void APIENTRY glDrawElementArrayATI (GLenum, GLsizei);
+GLAPI void APIENTRY glDrawRangeElementArrayATI (GLenum, GLuint, GLuint, GLsizei);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLELEMENTPOINTERATIPROC) (GLenum type, const GLvoid *pointer);
+typedef void (APIENTRYP PFNGLDRAWELEMENTARRAYATIPROC) (GLenum mode, GLsizei count);
+typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTARRAYATIPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count);
+#endif
+
+#ifndef GL_SUN_mesh_array
+#define GL_SUN_mesh_array 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawMeshArraysSUN (GLenum, GLint, GLsizei, GLsizei);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLDRAWMESHARRAYSSUNPROC) (GLenum mode, GLint first, GLsizei count, GLsizei width);
+#endif
+
+#ifndef GL_SUN_slice_accum
+#define GL_SUN_slice_accum 1
+#endif
+
+#ifndef GL_NV_multisample_filter_hint
+#define GL_NV_multisample_filter_hint 1
+#endif
+
+#ifndef GL_NV_depth_clamp
+#define GL_NV_depth_clamp 1
+#endif
+
+#ifndef GL_NV_occlusion_query
+#define GL_NV_occlusion_query 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGenOcclusionQueriesNV (GLsizei, GLuint *);
+GLAPI void APIENTRY glDeleteOcclusionQueriesNV (GLsizei, const GLuint *);
+GLAPI GLboolean APIENTRY glIsOcclusionQueryNV (GLuint);
+GLAPI void APIENTRY glBeginOcclusionQueryNV (GLuint);
+GLAPI void APIENTRY glEndOcclusionQueryNV (void);
+GLAPI void APIENTRY glGetOcclusionQueryivNV (GLuint, GLenum, GLint *);
+GLAPI void APIENTRY glGetOcclusionQueryuivNV (GLuint, GLenum, GLuint *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLGENOCCLUSIONQUERIESNVPROC) (GLsizei n, GLuint *ids);
+typedef void (APIENTRYP PFNGLDELETEOCCLUSIONQUERIESNVPROC) (GLsizei n, const GLuint *ids);
+typedef GLboolean (APIENTRYP PFNGLISOCCLUSIONQUERYNVPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLBEGINOCCLUSIONQUERYNVPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLENDOCCLUSIONQUERYNVPROC) (void);
+typedef void (APIENTRYP PFNGLGETOCCLUSIONQUERYIVNVPROC) (GLuint id, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETOCCLUSIONQUERYUIVNVPROC) (GLuint id, GLenum pname, GLuint *params);
+#endif
+
+#ifndef GL_NV_point_sprite
+#define GL_NV_point_sprite 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPointParameteriNV (GLenum, GLint);
+GLAPI void APIENTRY glPointParameterivNV (GLenum, const GLint *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLPOINTPARAMETERINVPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERIVNVPROC) (GLenum pname, const GLint *params);
+#endif
+
+#ifndef GL_NV_texture_shader3
+#define GL_NV_texture_shader3 1
+#endif
+
+#ifndef GL_NV_vertex_program1_1
+#define GL_NV_vertex_program1_1 1
+#endif
+
+#ifndef GL_EXT_shadow_funcs
+#define GL_EXT_shadow_funcs 1
+#endif
+
+#ifndef GL_EXT_stencil_two_side
+#define GL_EXT_stencil_two_side 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glActiveStencilFaceEXT (GLenum);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLACTIVESTENCILFACEEXTPROC) (GLenum face);
+#endif
+
+#ifndef GL_ATI_text_fragment_shader
+#define GL_ATI_text_fragment_shader 1
+#endif
+
+#ifndef GL_APPLE_client_storage
+#define GL_APPLE_client_storage 1
+#endif
+
+#ifndef GL_APPLE_element_array
+#define GL_APPLE_element_array 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glElementPointerAPPLE (GLenum, const GLvoid *);
+GLAPI void APIENTRY glDrawElementArrayAPPLE (GLenum, GLint, GLsizei);
+GLAPI void APIENTRY glDrawRangeElementArrayAPPLE (GLenum, GLuint, GLuint, GLint, GLsizei);
+GLAPI void APIENTRY glMultiDrawElementArrayAPPLE (GLenum, const GLint *, const GLsizei *, GLsizei);
+GLAPI void APIENTRY glMultiDrawRangeElementArrayAPPLE (GLenum, GLuint, GLuint, const GLint *, const GLsizei *, GLsizei);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLELEMENTPOINTERAPPLEPROC) (GLenum type, const GLvoid *pointer);
+typedef void (APIENTRYP PFNGLDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, GLint first, GLsizei count);
+typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, GLint first, GLsizei count);
+typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
+typedef void (APIENTRYP PFNGLMULTIDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, const GLint *first, const GLsizei *count, GLsizei primcount);
+#endif
+
+#ifndef GL_APPLE_fence
+#define GL_APPLE_fence 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGenFencesAPPLE (GLsizei, GLuint *);
+GLAPI void APIENTRY glDeleteFencesAPPLE (GLsizei, const GLuint *);
+GLAPI void APIENTRY glSetFenceAPPLE (GLuint);
+GLAPI GLboolean APIENTRY glIsFenceAPPLE (GLuint);
+GLAPI GLboolean APIENTRY glTestFenceAPPLE (GLuint);
+GLAPI void APIENTRY glFinishFenceAPPLE (GLuint);
+GLAPI GLboolean APIENTRY glTestObjectAPPLE (GLenum, GLuint);
+GLAPI void APIENTRY glFinishObjectAPPLE (GLenum, GLint);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLGENFENCESAPPLEPROC) (GLsizei n, GLuint *fences);
+typedef void (APIENTRYP PFNGLDELETEFENCESAPPLEPROC) (GLsizei n, const GLuint *fences);
+typedef void (APIENTRYP PFNGLSETFENCEAPPLEPROC) (GLuint fence);
+typedef GLboolean (APIENTRYP PFNGLISFENCEAPPLEPROC) (GLuint fence);
+typedef GLboolean (APIENTRYP PFNGLTESTFENCEAPPLEPROC) (GLuint fence);
+typedef void (APIENTRYP PFNGLFINISHFENCEAPPLEPROC) (GLuint fence);
+typedef GLboolean (APIENTRYP PFNGLTESTOBJECTAPPLEPROC) (GLenum object, GLuint name);
+typedef void (APIENTRYP PFNGLFINISHOBJECTAPPLEPROC) (GLenum object, GLint name);
+#endif
+
+#ifndef GL_APPLE_vertex_array_object
+#define GL_APPLE_vertex_array_object 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBindVertexArrayAPPLE (GLuint);
+GLAPI void APIENTRY glDeleteVertexArraysAPPLE (GLsizei, const GLuint *);
+GLAPI void APIENTRY glGenVertexArraysAPPLE (GLsizei, const GLuint *);
+GLAPI GLboolean APIENTRY glIsVertexArrayAPPLE (GLuint);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLBINDVERTEXARRAYAPPLEPROC) (GLuint array);
+typedef void (APIENTRYP PFNGLDELETEVERTEXARRAYSAPPLEPROC) (GLsizei n, const GLuint *arrays);
+typedef void (APIENTRYP PFNGLGENVERTEXARRAYSAPPLEPROC) (GLsizei n, const GLuint *arrays);
+typedef GLboolean (APIENTRYP PFNGLISVERTEXARRAYAPPLEPROC) (GLuint array);
+#endif
+
+#ifndef GL_APPLE_vertex_array_range
+#define GL_APPLE_vertex_array_range 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexArrayRangeAPPLE (GLsizei, GLvoid *);
+GLAPI void APIENTRY glFlushVertexArrayRangeAPPLE (GLsizei, GLvoid *);
+GLAPI void APIENTRY glVertexArrayParameteriAPPLE (GLenum, GLint);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, GLvoid *pointer);
+typedef void (APIENTRYP PFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, GLvoid *pointer);
+typedef void (APIENTRYP PFNGLVERTEXARRAYPARAMETERIAPPLEPROC) (GLenum pname, GLint param);
+#endif
+
+#ifndef GL_APPLE_ycbcr_422
+#define GL_APPLE_ycbcr_422 1
+#endif
+
+#ifndef GL_S3_s3tc
+#define GL_S3_s3tc 1
+#endif
+
+#ifndef GL_ATI_draw_buffers
+#define GL_ATI_draw_buffers 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawBuffersATI (GLsizei, const GLenum *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLDRAWBUFFERSATIPROC) (GLsizei n, const GLenum *bufs);
+#endif
+
+#ifndef GL_ATI_pixel_format_float
+#define GL_ATI_pixel_format_float 1
+/* This is really a WGL extension, but defines some associated GL enums.
+ * ATI does not export "GL_ATI_pixel_format_float" in the GL_EXTENSIONS string.
+ */
+#endif
+
+#ifndef GL_ATI_texture_env_combine3
+#define GL_ATI_texture_env_combine3 1
+#endif
+
+#ifndef GL_ATI_texture_float
+#define GL_ATI_texture_float 1
+#endif
+
+#ifndef GL_NV_float_buffer
+#define GL_NV_float_buffer 1
+#endif
+
+#ifndef GL_NV_fragment_program
+#define GL_NV_fragment_program 1
+/* Some NV_fragment_program entry points are shared with ARB_vertex_program. */
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glProgramNamedParameter4fNV (GLuint, GLsizei, const GLubyte *, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glProgramNamedParameter4dNV (GLuint, GLsizei, const GLubyte *, GLdouble, GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glProgramNamedParameter4fvNV (GLuint, GLsizei, const GLubyte *, const GLfloat *);
+GLAPI void APIENTRY glProgramNamedParameter4dvNV (GLuint, GLsizei, const GLubyte *, const GLdouble *);
+GLAPI void APIENTRY glGetProgramNamedParameterfvNV (GLuint, GLsizei, const GLubyte *, GLfloat *);
+GLAPI void APIENTRY glGetProgramNamedParameterdvNV (GLuint, GLsizei, const GLubyte *, GLdouble *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLPROGRAMNAMEDPARAMETER4FNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLPROGRAMNAMEDPARAMETER4DNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLPROGRAMNAMEDPARAMETER4FVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, const GLfloat *v);
+typedef void (APIENTRYP PFNGLPROGRAMNAMEDPARAMETER4DVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, const GLdouble *v);
+typedef void (APIENTRYP PFNGLGETPROGRAMNAMEDPARAMETERFVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMNAMEDPARAMETERDVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLdouble *params);
+#endif
+
+#ifndef GL_NV_half_float
+#define GL_NV_half_float 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertex2hNV (GLhalfNV, GLhalfNV);
+GLAPI void APIENTRY glVertex2hvNV (const GLhalfNV *);
+GLAPI void APIENTRY glVertex3hNV (GLhalfNV, GLhalfNV, GLhalfNV);
+GLAPI void APIENTRY glVertex3hvNV (const GLhalfNV *);
+GLAPI void APIENTRY glVertex4hNV (GLhalfNV, GLhalfNV, GLhalfNV, GLhalfNV);
+GLAPI void APIENTRY glVertex4hvNV (const GLhalfNV *);
+GLAPI void APIENTRY glNormal3hNV (GLhalfNV, GLhalfNV, GLhalfNV);
+GLAPI void APIENTRY glNormal3hvNV (const GLhalfNV *);
+GLAPI void APIENTRY glColor3hNV (GLhalfNV, GLhalfNV, GLhalfNV);
+GLAPI void APIENTRY glColor3hvNV (const GLhalfNV *);
+GLAPI void APIENTRY glColor4hNV (GLhalfNV, GLhalfNV, GLhalfNV, GLhalfNV);
+GLAPI void APIENTRY glColor4hvNV (const GLhalfNV *);
+GLAPI void APIENTRY glTexCoord1hNV (GLhalfNV);
+GLAPI void APIENTRY glTexCoord1hvNV (const GLhalfNV *);
+GLAPI void APIENTRY glTexCoord2hNV (GLhalfNV, GLhalfNV);
+GLAPI void APIENTRY glTexCoord2hvNV (const GLhalfNV *);
+GLAPI void APIENTRY glTexCoord3hNV (GLhalfNV, GLhalfNV, GLhalfNV);
+GLAPI void APIENTRY glTexCoord3hvNV (const GLhalfNV *);
+GLAPI void APIENTRY glTexCoord4hNV (GLhalfNV, GLhalfNV, GLhalfNV, GLhalfNV);
+GLAPI void APIENTRY glTexCoord4hvNV (const GLhalfNV *);
+GLAPI void APIENTRY glMultiTexCoord1hNV (GLenum, GLhalfNV);
+GLAPI void APIENTRY glMultiTexCoord1hvNV (GLenum, const GLhalfNV *);
+GLAPI void APIENTRY glMultiTexCoord2hNV (GLenum, GLhalfNV, GLhalfNV);
+GLAPI void APIENTRY glMultiTexCoord2hvNV (GLenum, const GLhalfNV *);
+GLAPI void APIENTRY glMultiTexCoord3hNV (GLenum, GLhalfNV, GLhalfNV, GLhalfNV);
+GLAPI void APIENTRY glMultiTexCoord3hvNV (GLenum, const GLhalfNV *);
+GLAPI void APIENTRY glMultiTexCoord4hNV (GLenum, GLhalfNV, GLhalfNV, GLhalfNV, GLhalfNV);
+GLAPI void APIENTRY glMultiTexCoord4hvNV (GLenum, const GLhalfNV *);
+GLAPI void APIENTRY glFogCoordhNV (GLhalfNV);
+GLAPI void APIENTRY glFogCoordhvNV (const GLhalfNV *);
+GLAPI void APIENTRY glSecondaryColor3hNV (GLhalfNV, GLhalfNV, GLhalfNV);
+GLAPI void APIENTRY glSecondaryColor3hvNV (const GLhalfNV *);
+GLAPI void APIENTRY glVertexWeighthNV (GLhalfNV);
+GLAPI void APIENTRY glVertexWeighthvNV (const GLhalfNV *);
+GLAPI void APIENTRY glVertexAttrib1hNV (GLuint, GLhalfNV);
+GLAPI void APIENTRY glVertexAttrib1hvNV (GLuint, const GLhalfNV *);
+GLAPI void APIENTRY glVertexAttrib2hNV (GLuint, GLhalfNV, GLhalfNV);
+GLAPI void APIENTRY glVertexAttrib2hvNV (GLuint, const GLhalfNV *);
+GLAPI void APIENTRY glVertexAttrib3hNV (GLuint, GLhalfNV, GLhalfNV, GLhalfNV);
+GLAPI void APIENTRY glVertexAttrib3hvNV (GLuint, const GLhalfNV *);
+GLAPI void APIENTRY glVertexAttrib4hNV (GLuint, GLhalfNV, GLhalfNV, GLhalfNV, GLhalfNV);
+GLAPI void APIENTRY glVertexAttrib4hvNV (GLuint, const GLhalfNV *);
+GLAPI void APIENTRY glVertexAttribs1hvNV (GLuint, GLsizei, const GLhalfNV *);
+GLAPI void APIENTRY glVertexAttribs2hvNV (GLuint, GLsizei, const GLhalfNV *);
+GLAPI void APIENTRY glVertexAttribs3hvNV (GLuint, GLsizei, const GLhalfNV *);
+GLAPI void APIENTRY glVertexAttribs4hvNV (GLuint, GLsizei, const GLhalfNV *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLVERTEX2HNVPROC) (GLhalfNV x, GLhalfNV y);
+typedef void (APIENTRYP PFNGLVERTEX2HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEX3HNVPROC) (GLhalfNV x, GLhalfNV y, GLhalfNV z);
+typedef void (APIENTRYP PFNGLVERTEX3HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEX4HNVPROC) (GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w);
+typedef void (APIENTRYP PFNGLVERTEX4HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLNORMAL3HNVPROC) (GLhalfNV nx, GLhalfNV ny, GLhalfNV nz);
+typedef void (APIENTRYP PFNGLNORMAL3HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLCOLOR3HNVPROC) (GLhalfNV red, GLhalfNV green, GLhalfNV blue);
+typedef void (APIENTRYP PFNGLCOLOR3HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLCOLOR4HNVPROC) (GLhalfNV red, GLhalfNV green, GLhalfNV blue, GLhalfNV alpha);
+typedef void (APIENTRYP PFNGLCOLOR4HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLTEXCOORD1HNVPROC) (GLhalfNV s);
+typedef void (APIENTRYP PFNGLTEXCOORD1HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLTEXCOORD2HNVPROC) (GLhalfNV s, GLhalfNV t);
+typedef void (APIENTRYP PFNGLTEXCOORD2HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLTEXCOORD3HNVPROC) (GLhalfNV s, GLhalfNV t, GLhalfNV r);
+typedef void (APIENTRYP PFNGLTEXCOORD3HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLTEXCOORD4HNVPROC) (GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q);
+typedef void (APIENTRYP PFNGLTEXCOORD4HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1HNVPROC) (GLenum target, GLhalfNV s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1HVNVPROC) (GLenum target, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2HNVPROC) (GLenum target, GLhalfNV s, GLhalfNV t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2HVNVPROC) (GLenum target, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3HNVPROC) (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3HVNVPROC) (GLenum target, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4HNVPROC) (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4HVNVPROC) (GLenum target, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLFOGCOORDHNVPROC) (GLhalfNV fog);
+typedef void (APIENTRYP PFNGLFOGCOORDHVNVPROC) (const GLhalfNV *fog);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3HNVPROC) (GLhalfNV red, GLhalfNV green, GLhalfNV blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEXWEIGHTHNVPROC) (GLhalfNV weight);
+typedef void (APIENTRYP PFNGLVERTEXWEIGHTHVNVPROC) (const GLhalfNV *weight);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1HNVPROC) (GLuint index, GLhalfNV x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1HVNVPROC) (GLuint index, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2HNVPROC) (GLuint index, GLhalfNV x, GLhalfNV y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2HVNVPROC) (GLuint index, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3HNVPROC) (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3HVNVPROC) (GLuint index, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4HNVPROC) (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4HVNVPROC) (GLuint index, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS1HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS2HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS3HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS4HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v);
+#endif
+
+#ifndef GL_NV_pixel_data_range
+#define GL_NV_pixel_data_range 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPixelDataRangeNV (GLenum, GLsizei, GLvoid *);
+GLAPI void APIENTRY glFlushPixelDataRangeNV (GLenum);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLPIXELDATARANGENVPROC) (GLenum target, GLsizei length, GLvoid *pointer);
+typedef void (APIENTRYP PFNGLFLUSHPIXELDATARANGENVPROC) (GLenum target);
+#endif
+
+#ifndef GL_NV_primitive_restart
+#define GL_NV_primitive_restart 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPrimitiveRestartNV (void);
+GLAPI void APIENTRY glPrimitiveRestartIndexNV (GLuint);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLPRIMITIVERESTARTNVPROC) (void);
+typedef void (APIENTRYP PFNGLPRIMITIVERESTARTINDEXNVPROC) (GLuint index);
+#endif
+
+#ifndef GL_NV_texture_expand_normal
+#define GL_NV_texture_expand_normal 1
+#endif
+
+#ifndef GL_NV_vertex_program2
+#define GL_NV_vertex_program2 1
+#endif
+
+#ifndef GL_ATI_map_object_buffer
+#define GL_ATI_map_object_buffer 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLvoid* APIENTRY glMapObjectBufferATI (GLuint);
+GLAPI void APIENTRY glUnmapObjectBufferATI (GLuint);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef GLvoid* (APIENTRYP PFNGLMAPOBJECTBUFFERATIPROC) (GLuint buffer);
+typedef void (APIENTRYP PFNGLUNMAPOBJECTBUFFERATIPROC) (GLuint buffer);
+#endif
+
+#ifndef GL_ATI_separate_stencil
+#define GL_ATI_separate_stencil 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glStencilOpSeparateATI (GLenum, GLenum, GLenum, GLenum);
+GLAPI void APIENTRY glStencilFuncSeparateATI (GLenum, GLenum, GLint, GLuint);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLSTENCILOPSEPARATEATIPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+typedef void (APIENTRYP PFNGLSTENCILFUNCSEPARATEATIPROC) (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask);
+#endif
+
+#ifndef GL_ATI_vertex_attrib_array_object
+#define GL_ATI_vertex_attrib_array_object 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexAttribArrayObjectATI (GLuint, GLint, GLenum, GLboolean, GLsizei, GLuint, GLuint);
+GLAPI void APIENTRY glGetVertexAttribArrayObjectfvATI (GLuint, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetVertexAttribArrayObjectivATI (GLuint, GLenum, GLint *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLVERTEXATTRIBARRAYOBJECTATIPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLuint buffer, GLuint offset);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBARRAYOBJECTFVATIPROC) (GLuint index, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBARRAYOBJECTIVATIPROC) (GLuint index, GLenum pname, GLint *params);
+#endif
+
+#ifndef GL_OES_read_format
+#define GL_OES_read_format 1
+#endif
+
+#ifndef GL_EXT_depth_bounds_test
+#define GL_EXT_depth_bounds_test 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDepthBoundsEXT (GLclampd, GLclampd);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLDEPTHBOUNDSEXTPROC) (GLclampd zmin, GLclampd zmax);
+#endif
+
+#ifndef GL_EXT_texture_mirror_clamp
+#define GL_EXT_texture_mirror_clamp 1
+#endif
+
+#ifndef GL_EXT_blend_equation_separate
+#define GL_EXT_blend_equation_separate 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendEquationSeparateEXT (GLenum, GLenum);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEEXTPROC) (GLenum modeRGB, GLenum modeAlpha);
+#endif
+
+#ifndef GL_MESA_pack_invert
+#define GL_MESA_pack_invert 1
+#endif
+
+#ifndef GL_MESA_ycbcr_texture
+#define GL_MESA_ycbcr_texture 1
+#endif
+
+#ifndef GL_EXT_pixel_buffer_object
+#define GL_EXT_pixel_buffer_object 1
+#endif
+
+#ifndef GL_NV_fragment_program_option
+#define GL_NV_fragment_program_option 1
+#endif
+
+#ifndef GL_NV_fragment_program2
+#define GL_NV_fragment_program2 1
+#endif
+
+#ifndef GL_NV_vertex_program2_option
+#define GL_NV_vertex_program2_option 1
+#endif
+
+#ifndef GL_NV_vertex_program3
+#define GL_NV_vertex_program3 1
+#endif
+
+#ifndef GL_EXT_framebuffer_object
+#define GL_EXT_framebuffer_object 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLboolean APIENTRY glIsRenderbufferEXT (GLuint);
+GLAPI void APIENTRY glBindRenderbufferEXT (GLenum, GLuint);
+GLAPI void APIENTRY glDeleteRenderbuffersEXT (GLsizei, const GLuint *);
+GLAPI void APIENTRY glGenRenderbuffersEXT (GLsizei, GLuint *);
+GLAPI void APIENTRY glRenderbufferStorageEXT (GLenum, GLenum, GLsizei, GLsizei);
+GLAPI void APIENTRY glGetRenderbufferParameterivEXT (GLenum, GLenum, GLint *);
+GLAPI GLboolean APIENTRY glIsFramebufferEXT (GLuint);
+GLAPI void APIENTRY glBindFramebufferEXT (GLenum, GLuint);
+GLAPI void APIENTRY glDeleteFramebuffersEXT (GLsizei, const GLuint *);
+GLAPI void APIENTRY glGenFramebuffersEXT (GLsizei, GLuint *);
+GLAPI GLenum APIENTRY glCheckFramebufferStatusEXT (GLenum);
+GLAPI void APIENTRY glFramebufferTexture1DEXT (GLenum, GLenum, GLenum, GLuint, GLint);
+GLAPI void APIENTRY glFramebufferTexture2DEXT (GLenum, GLenum, GLenum, GLuint, GLint);
+GLAPI void APIENTRY glFramebufferTexture3DEXT (GLenum, GLenum, GLenum, GLuint, GLint, GLint);
+GLAPI void APIENTRY glFramebufferRenderbufferEXT (GLenum, GLenum, GLenum, GLuint);
+GLAPI void APIENTRY glGetFramebufferAttachmentParameterivEXT (GLenum, GLenum, GLenum, GLint *);
+GLAPI void APIENTRY glGenerateMipmapEXT (GLenum);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef GLboolean (APIENTRYP PFNGLISRENDERBUFFEREXTPROC) (GLuint renderbuffer);
+typedef void (APIENTRYP PFNGLBINDRENDERBUFFEREXTPROC) (GLenum target, GLuint renderbuffer);
+typedef void (APIENTRYP PFNGLDELETERENDERBUFFERSEXTPROC) (GLsizei n, const GLuint *renderbuffers);
+typedef void (APIENTRYP PFNGLGENRENDERBUFFERSEXTPROC) (GLsizei n, GLuint *renderbuffers);
+typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef GLboolean (APIENTRYP PFNGLISFRAMEBUFFEREXTPROC) (GLuint framebuffer);
+typedef void (APIENTRYP PFNGLBINDFRAMEBUFFEREXTPROC) (GLenum target, GLuint framebuffer);
+typedef void (APIENTRYP PFNGLDELETEFRAMEBUFFERSEXTPROC) (GLsizei n, const GLuint *framebuffers);
+typedef void (APIENTRYP PFNGLGENFRAMEBUFFERSEXTPROC) (GLsizei n, GLuint *framebuffers);
+typedef GLenum (APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE1DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+typedef void (APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) (GLenum target, GLenum attachment, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGENERATEMIPMAPEXTPROC) (GLenum target);
+#endif
+
+#ifndef GL_GREMEDY_string_marker
+#define GL_GREMEDY_string_marker 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glStringMarkerGREMEDY (GLsizei, const GLvoid *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLSTRINGMARKERGREMEDYPROC) (GLsizei len, const GLvoid *string);
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/3dengfx/src/3dengfx/shadows.cpp b/src/3dengfx/src/3dengfx/shadows.cpp
new file mode 100644 (file)
index 0000000..b2d7bd2
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+This file is part of the 3dengfx, realtime visualization system.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+3dengfx is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+3dengfx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with 3dengfx; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <vector>
+#include "shadows.hpp"
+
+std::vector<Edge> *create_silhouette(const TriMesh *mesh, const Vector3 &pt) {
+       const GeometryArray<Edge> *mesh_edges = mesh->get_edge_array();
+       unsigned long ecount = mesh_edges->get_count();
+       const Edge *eptr = mesh_edges->get_data();
+
+       const Vertex *varray = mesh->get_vertex_array()->get_data();
+       const Triangle *tarray = mesh->get_triangle_array()->get_data();
+
+       std::vector<Edge> *edges = new std::vector<Edge>;
+
+       for(unsigned long i=0; i<ecount; i++) {
+               const Triangle *t1 = tarray + eptr->adjfaces[0];
+               const Triangle *t2 = tarray + eptr->adjfaces[1];
+               // XXX: assumption that the light direction for one of a triangle's vertices
+               // can be used as the light direction for the whole triangle.
+               Vector3 ldir1 = (pt - varray[t1->vertices[0]].pos).normalized();
+               Vector3 ldir2 = (pt - varray[t2->vertices[0]].pos).normalized();
+               scalar_t t1dot = dot_product(t1->normal, ldir1);
+               scalar_t t2dot = dot_product(t2->normal, ldir2);
+               
+               if((t1dot > 0 && t2dot < 0) || (t1dot < 0 && t2dot > 0)) {
+                       edges->push_back(*eptr);
+               }
+               eptr++;
+       }
+
+       return edges;
+}
+
+void destroy_silhouette(std::vector<Edge> *edges) {
+       delete edges;
+}
+/*
+TriMesh *create_shadow_volume(const TriMesh *mesh, const Vector3 &pt) {
+       
+}
+*/
diff --git a/src/3dengfx/src/3dengfx/shadows.hpp b/src/3dengfx/src/3dengfx/shadows.hpp
new file mode 100644 (file)
index 0000000..e129124
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+This file is part of the 3dengfx, realtime visualization system.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+3dengfx is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+3dengfx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with 3dengfx; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef SHADOWS_HPP_
+#define SHADOWS_HPP_
+
+#include <vector>
+#include "gfx/3dgeom.hpp"
+#include "n3dmath2/n3dmath2.hpp"
+
+std::vector<Edge> *create_silhouette(const TriMesh *mesh, const Vector3 &pt);
+void destroy_silhouette(std::vector<Edge> *edges);
+//TriMesh *create_shadow_volume(const TriMesh *mesh, const Vector3 &pt);
+
+#endif // SHADOWS_HPP_
diff --git a/src/3dengfx/src/3dengfx/teapot.h b/src/3dengfx/src/3dengfx/teapot.h
new file mode 100644 (file)
index 0000000..7788377
--- /dev/null
@@ -0,0 +1,358 @@
+/* teapot.h
+ * Original datafile by Newell
+ * converted to .h by Michael Georgoulopoulos 1/1/2005
+ * Happy new year!
+ */
+
+#ifndef GGEN_SOURCE
+#error "Do not include teapot.h anywhere!"
+#endif /* GGEN_SOURCE */
+
+
+static const int teapot_num_patches = 32;
+
+static const unsigned int teapot_patches[] = {
+       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 
+       4, 17, 18, 19, 8, 20, 21, 22, 12, 23, 24, 25, 16, 26, 27, 28, 
+       19, 29, 30, 31, 22, 32, 33, 34, 25, 35, 36, 37, 28, 38, 39, 40, 
+       31, 41, 42, 1, 34, 43, 44, 5, 37, 45, 46, 9, 40, 47, 48, 13, 
+       13, 14, 15, 16, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 
+       16, 26, 27, 28, 52, 61, 62, 63, 56, 64, 65, 66, 60, 67, 68, 69, 
+       28, 38, 39, 40, 63, 70, 71, 72, 66, 73, 74, 75, 69, 76, 77, 78, 
+       40, 47, 48, 13, 72, 79, 80, 49, 75, 81, 82, 53, 78, 83, 84, 57, 
+       57, 58, 59, 60, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 
+       60, 67, 68, 69, 88, 97, 98, 99, 92, 100, 101, 102, 96, 103, 104, 105, 
+       69, 76, 77, 78, 99, 106, 107, 108, 102, 109, 110, 111, 105, 112, 113, 114, 
+       78, 83, 84, 57, 108, 115, 116, 85, 111, 117, 118, 89, 114, 119, 120, 93, 
+       121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 
+       124, 137, 138, 121, 128, 139, 140, 125, 132, 141, 142, 129, 136, 143, 144, 133, 
+       133, 134, 135, 136, 145, 146, 147, 148, 149, 150, 151, 152, 69, 153, 154, 155, 
+       136, 143, 144, 133, 148, 156, 157, 145, 152, 158, 159, 149, 155, 160, 161, 69, 
+       162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 
+       165, 178, 179, 162, 169, 180, 181, 166, 173, 182, 183, 170, 177, 184, 185, 174, 
+       174, 175, 176, 177, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 
+       177, 184, 185, 174, 189, 198, 199, 186, 193, 200, 201, 190, 197, 202, 203, 194, 
+       204, 204, 204, 204, 207, 208, 209, 210, 211, 211, 211, 211, 212, 213, 214, 215, 
+       204, 204, 204, 204, 210, 217, 218, 219, 211, 211, 211, 211, 215, 220, 221, 222, 
+       204, 204, 204, 204, 219, 224, 225, 226, 211, 211, 211, 211, 222, 227, 228, 229, 
+       204, 204, 204, 204, 226, 230, 231, 207, 211, 211, 211, 211, 229, 232, 233, 212, 
+       212, 213, 214, 215, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 
+       215, 220, 221, 222, 237, 246, 247, 248, 241, 249, 250, 251, 245, 252, 253, 254, 
+       222, 227, 228, 229, 248, 255, 256, 257, 251, 258, 259, 260, 254, 261, 262, 263, 
+       229, 232, 233, 212, 257, 264, 265, 234, 260, 266, 267, 238, 263, 268, 269, 242, 
+       270, 270, 270, 270, 279, 280, 281, 282, 275, 276, 277, 278, 271, 272, 273, 274, 
+       270, 270, 270, 270, 282, 289, 290, 291, 278, 286, 287, 288, 274, 283, 284, 285, 
+       270, 270, 270, 270, 291, 298, 299, 300, 288, 295, 296, 297, 285, 292, 293, 294, 
+       270, 270, 270, 270, 300, 305, 306, 279, 297, 303, 304, 275, 294, 301, 302, 271
+};
+
+static const int teapot_num_vertices = 306;
+
+static const float teapot_vertices[] = {
+       1.4, 0.0, 2.4, 
+       1.4, -0.784, 2.4, 
+       0.784, -1.4, 2.4, 
+       0.0, -1.4, 2.4, 
+       1.3375, 0.0, 2.53125, 
+       1.3375, -0.749, 2.53125, 
+       0.749, -1.3375, 2.53125, 
+       0.0, -1.3375, 2.53125, 
+       1.4375, 0.0, 2.53125, 
+       1.4375, -0.805, 2.53125, 
+       0.805, -1.4375, 2.53125, 
+       0.0, -1.4375, 2.53125, 
+       1.5, 0.0, 2.4, 
+       1.5, -0.84, 2.4, 
+       0.84, -1.5, 2.4, 
+       0.0, -1.5, 2.4, 
+       -0.784, -1.4, 2.4, 
+       -1.4, -0.784, 2.4, 
+       -1.4, 0.0, 2.4, 
+       -0.749, -1.3375, 2.53125, 
+       -1.3375, -0.749, 2.53125, 
+       -1.3375, 0.0, 2.53125, 
+       -0.805, -1.4375, 2.53125, 
+       -1.4375, -0.805, 2.53125, 
+       -1.4375, 0.0, 2.53125, 
+       -0.84, -1.5, 2.4, 
+       -1.5, -0.84, 2.4, 
+       -1.5, 0.0, 2.4, 
+       -1.4, 0.784, 2.4, 
+       -0.784, 1.4, 2.4, 
+       0.0, 1.4, 2.4, 
+       -1.3375, 0.749, 2.53125, 
+       -0.749, 1.3375, 2.53125, 
+       0.0, 1.3375, 2.53125, 
+       -1.4375, 0.805, 2.53125, 
+       -0.805, 1.4375, 2.53125, 
+       0.0, 1.4375, 2.53125, 
+       -1.5, 0.84, 2.4, 
+       -0.84, 1.5, 2.4, 
+       0.0, 1.5, 2.4, 
+       0.784, 1.4, 2.4, 
+       1.4, 0.784, 2.4, 
+       0.749, 1.3375, 2.53125, 
+       1.3375, 0.749, 2.53125, 
+       0.805, 1.4375, 2.53125, 
+       1.4375, 0.805, 2.53125, 
+       0.84, 1.5, 2.4, 
+       1.5, 0.84, 2.4, 
+       1.75, 0.0, 1.875, 
+       1.75, -0.98, 1.875, 
+       0.98, -1.75, 1.875, 
+       0.0, -1.75, 1.875, 
+       2.0, 0.0, 1.35, 
+       2.0, -1.12, 1.35, 
+       1.12, -2.0, 1.35, 
+       0.0, -2.0, 1.35, 
+       2.0, 0.0, 0.9, 
+       2.0, -1.12, 0.9, 
+       1.12, -2.0, 0.9, 
+       0.0, -2.0, 0.9, 
+       -0.98, -1.75, 1.875, 
+       -1.75, -0.98, 1.875, 
+       -1.75, 0.0, 1.875, 
+       -1.12, -2.0, 1.35, 
+       -2.0, -1.12, 1.35, 
+       -2.0, 0.0, 1.35, 
+       -1.12, -2.0, 0.9, 
+       -2.0, -1.12, 0.9, 
+       -2.0, 0.0, 0.9, 
+       -1.75, 0.98, 1.875, 
+       -0.98, 1.75, 1.875, 
+       0.0, 1.75, 1.875, 
+       -2.0, 1.12, 1.35, 
+       -1.12, 2.0, 1.35, 
+       0.0, 2.0, 1.35, 
+       -2.0, 1.12, 0.9, 
+       -1.12, 2.0, 0.9, 
+       0.0, 2.0, 0.9, 
+       0.98, 1.75, 1.875, 
+       1.75, 0.98, 1.875, 
+       1.12, 2.0, 1.35, 
+       2.0, 1.12, 1.35, 
+       1.12, 2.0, 0.9, 
+       2.0, 1.12, 0.9, 
+       2.0, 0.0, 0.45, 
+       2.0, -1.12, 0.45, 
+       1.12, -2.0, 0.45, 
+       0.0, -2.0, 0.45, 
+       1.5, 0.0, 0.225, 
+       1.5, -0.84, 0.225, 
+       0.84, -1.5, 0.225, 
+       0.0, -1.5, 0.225, 
+       1.5, 0.0, 0.15, 
+       1.5, -0.84, 0.15, 
+       0.84, -1.5, 0.15, 
+       0.0, -1.5, 0.15, 
+       -1.12, -2.0, 0.45, 
+       -2.0, -1.12, 0.45, 
+       -2.0, 0.0, 0.45, 
+       -0.84, -1.5, 0.225, 
+       -1.5, -0.84, 0.225, 
+       -1.5, 0.0, 0.225, 
+       -0.84, -1.5, 0.15, 
+       -1.5, -0.84, 0.15, 
+       -1.5, 0.0, 0.15, 
+       -2.0, 1.12, 0.45, 
+       -1.12, 2.0, 0.45, 
+       0.0, 2.0, 0.45, 
+       -1.5, 0.84, 0.225, 
+       -0.84, 1.5, 0.225, 
+       0.0, 1.5, 0.225, 
+       -1.5, 0.84, 0.15, 
+       -0.84, 1.5, 0.15, 
+       0.0, 1.5, 0.15, 
+       1.12, 2.0, 0.45, 
+       2.0, 1.12, 0.45, 
+       0.84, 1.5, 0.225, 
+       1.5, 0.84, 0.225, 
+       0.84, 1.5, 0.15, 
+       1.5, 0.84, 0.15, 
+       -1.6, 0.0, 2.025, 
+       -1.6, -0.3, 2.025, 
+       -1.5, -0.3, 2.25, 
+       -1.5, 0.0, 2.25, 
+       -2.3, 0.0, 2.025, 
+       -2.3, -0.3, 2.025, 
+       -2.5, -0.3, 2.25, 
+       -2.5, 0.0, 2.25, 
+       -2.7, 0.0, 2.025, 
+       -2.7, -0.3, 2.025, 
+       -3.0, -0.3, 2.25, 
+       -3.0, 0.0, 2.25, 
+       -2.7, 0.0, 1.8, 
+       -2.7, -0.3, 1.8, 
+       -3.0, -0.3, 1.8, 
+       -3.0, 0.0, 1.8, 
+       -1.5, 0.3, 2.25, 
+       -1.6, 0.3, 2.025, 
+       -2.5, 0.3, 2.25, 
+       -2.3, 0.3, 2.025, 
+       -3.0, 0.3, 2.25, 
+       -2.7, 0.3, 2.025, 
+       -3.0, 0.3, 1.8, 
+       -2.7, 0.3, 1.8, 
+       -2.7, 0.0, 1.575, 
+       -2.7, -0.3, 1.575, 
+       -3.0, -0.3, 1.35, 
+       -3.0, 0.0, 1.35, 
+       -2.5, 0.0, 1.125, 
+       -2.5, -0.3, 1.125, 
+       -2.65, -0.3, 0.9375, 
+       -2.65, 0.0, 0.9375, 
+       -2.0, -0.3, 0.9, 
+       -1.9, -0.3, 0.6, 
+       -1.9, 0.0, 0.6, 
+       -3.0, 0.3, 1.35, 
+       -2.7, 0.3, 1.575, 
+       -2.65, 0.3, 0.9375, 
+       -2.5, 0.3, 1.125, 
+       -1.9, 0.3, 0.6, 
+       -2.0, 0.3, 0.9, 
+       1.7, 0.0, 1.425, 
+       1.7, -0.66, 1.425, 
+       1.7, -0.66, 0.6, 
+       1.7, 0.0, 0.6, 
+       2.6, 0.0, 1.425, 
+       2.6, -0.66, 1.425, 
+       3.1, -0.66, 0.825, 
+       3.1, 0.0, 0.825, 
+       2.3, 0.0, 2.1, 
+       2.3, -0.25, 2.1, 
+       2.4, -0.25, 2.025, 
+       2.4, 0.0, 2.025, 
+       2.7, 0.0, 2.4, 
+       2.7, -0.25, 2.4, 
+       3.3, -0.25, 2.4, 
+       3.3, 0.0, 2.4, 
+       1.7, 0.66, 0.6, 
+       1.7, 0.66, 1.425, 
+       3.1, 0.66, 0.825, 
+       2.6, 0.66, 1.425, 
+       2.4, 0.25, 2.025, 
+       2.3, 0.25, 2.1, 
+       3.3, 0.25, 2.4, 
+       2.7, 0.25, 2.4, 
+       2.8, 0.0, 2.475, 
+       2.8, -0.25, 2.475, 
+       3.525, -0.25, 2.49375, 
+       3.525, 0.0, 2.49375, 
+       2.9, 0.0, 2.475, 
+       2.9, -0.15, 2.475, 
+       3.45, -0.15, 2.5125, 
+       3.45, 0.0, 2.5125, 
+       2.8, 0.0, 2.4, 
+       2.8, -0.15, 2.4, 
+       3.2, -0.15, 2.4, 
+       3.2, 0.0, 2.4, 
+       3.525, 0.25, 2.49375, 
+       2.8, 0.25, 2.475, 
+       3.45, 0.15, 2.5125, 
+       2.9, 0.15, 2.475, 
+       3.2, 0.15, 2.4, 
+       2.8, 0.15, 2.4, 
+       0.0, 0.0, 3.15, 
+       0.0, -0.002, 3.15, 
+       0.002, 0.0, 3.15, 
+       0.8, 0.0, 3.15, 
+       0.8, -0.45, 3.15, 
+       0.45, -0.8, 3.15, 
+       0.0, -0.8, 3.15, 
+       0.0, 0.0, 2.85, 
+       0.2, 0.0, 2.7, 
+       0.2, -0.112, 2.7, 
+       0.112, -0.2, 2.7, 
+       0.0, -0.2, 2.7, 
+       -0.002, 0.0, 3.15, 
+       -0.45, -0.8, 3.15, 
+       -0.8, -0.45, 3.15, 
+       -0.8, 0.0, 3.15, 
+       -0.112, -0.2, 2.7, 
+       -0.2, -0.112, 2.7, 
+       -0.2, 0.0, 2.7, 
+       0.0, 0.002, 3.15, 
+       -0.8, 0.45, 3.15, 
+       -0.45, 0.8, 3.15, 
+       0.0, 0.8, 3.15, 
+       -0.2, 0.112, 2.7, 
+       -0.112, 0.2, 2.7, 
+       0.0, 0.2, 2.7, 
+       0.45, 0.8, 3.15, 
+       0.8, 0.45, 3.15, 
+       0.112, 0.2, 2.7, 
+       0.2, 0.112, 2.7, 
+       0.4, 0.0, 2.55, 
+       0.4, -0.224, 2.55, 
+       0.224, -0.4, 2.55, 
+       0.0, -0.4, 2.55, 
+       1.3, 0.0, 2.55, 
+       1.3, -0.728, 2.55, 
+       0.728, -1.3, 2.55, 
+       0.0, -1.3, 2.55, 
+       1.3, 0.0, 2.4, 
+       1.3, -0.728, 2.4, 
+       0.728, -1.3, 2.4, 
+       0.0, -1.3, 2.4, 
+       -0.224, -0.4, 2.55, 
+       -0.4, -0.224, 2.55, 
+       -0.4, 0.0, 2.55, 
+       -0.728, -1.3, 2.55, 
+       -1.3, -0.728, 2.55, 
+       -1.3, 0.0, 2.55, 
+       -0.728, -1.3, 2.4, 
+       -1.3, -0.728, 2.4, 
+       -1.3, 0.0, 2.4, 
+       -0.4, 0.224, 2.55, 
+       -0.224, 0.4, 2.55, 
+       0.0, 0.4, 2.55, 
+       -1.3, 0.728, 2.55, 
+       -0.728, 1.3, 2.55, 
+       0.0, 1.3, 2.55, 
+       -1.3, 0.728, 2.4, 
+       -0.728, 1.3, 2.4, 
+       0.0, 1.3, 2.4, 
+       0.224, 0.4, 2.55, 
+       0.4, 0.224, 2.55, 
+       0.728, 1.3, 2.55, 
+       1.3, 0.728, 2.55, 
+       0.728, 1.3, 2.4, 
+       1.3, 0.728, 2.4, 
+       0.0, 0.0, 0.0, 
+       1.5, 0.0, 0.15, 
+       1.5, 0.84, 0.15, 
+       0.84, 1.5, 0.15, 
+       0.0, 1.5, 0.15, 
+       1.5, 0.0, 0.075, 
+       1.5, 0.84, 0.075, 
+       0.84, 1.5, 0.075, 
+       0.0, 1.5, 0.075, 
+       1.425, 0.0, 0.0, 
+       1.425, 0.798, 0.0, 
+       0.798, 1.425, 0.0, 
+       0.0, 1.425, 0.0, 
+       -0.84, 1.5, 0.15, 
+       -1.5, 0.84, 0.15, 
+       -1.5, 0.0, 0.15, 
+       -0.84, 1.5, 0.075, 
+       -1.5, 0.84, 0.075, 
+       -1.5, 0.0, 0.075, 
+       -0.798, 1.425, 0.0, 
+       -1.425, 0.798, 0.0, 
+       -1.425, 0.0, 0.0, 
+       -1.5, -0.84, 0.15, 
+       -0.84, -1.5, 0.15, 
+       0.0, -1.5, 0.15, 
+       -1.5, -0.84, 0.075, 
+       -0.84, -1.5, 0.075, 
+       0.0, -1.5, 0.075, 
+       -1.425, -0.798, 0.0, 
+       -0.798, -1.425, 0.0, 
+       0.0, -1.425, 0.0, 
+       0.84, -1.5, 0.15, 
+       1.5, -0.84, 0.15, 
+       0.84, -1.5, 0.075, 
+       1.5, -0.84, 0.075, 
+       0.798, -1.425, 0.0, 
+       1.425, -0.798, 0.0
+};
diff --git a/src/3dengfx/src/3dengfx/texman.cpp b/src/3dengfx/src/3dengfx/texman.cpp
new file mode 100644 (file)
index 0000000..66ef695
--- /dev/null
@@ -0,0 +1,360 @@
+/*
+This file is part of 3dengfx, realtime visualization system.
+Copyright (C) 2004, 2005, 2006 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+/* texture manager
+ *
+ * Author: John Tsiombikas 2004
+ */
+
+#include "3dengfx_config.h"
+
+#include <string>
+#include <cstring>
+#include "texman.hpp"
+#include "common/hashtable.hpp"
+#include "gfx/image.h"
+#include "gfx/color.hpp"
+#include "n3dmath2/n3dmath2.hpp"
+#include "common/string_hash.hpp"
+#include "common/err_msg.h"
+
+using std::string;
+
+static void create_normal_cube_map();
+
+static HashTable<string, Texture*> *textures;
+static Texture *normal_cubemap;
+
+static void delete_texture(Texture *tex) {
+       glDeleteTextures(1, &tex->tex_id);
+       glGetError();
+       //delete tex;
+}
+
+static void init_tex_man() {
+       if(textures) return;
+       textures = new HashTable<string, Texture*>;
+       textures->set_hash_function(string_hash);
+       textures->set_data_destructor(delete_texture);
+}
+
+void add_texture(Texture *texture, const char *fname) {
+       
+       if(!textures) init_tex_man();
+       
+       if(!fname) {    // enter a randomly named texture
+               textures->insert(tmpnam(0), texture);
+       } else {
+               textures->insert(fname, texture);
+       }
+}
+
+// TODO: implement this one, after making HashTable remove by value
+void remove_texture(Texture *texture) {
+}
+
+Texture *find_texture(const char *fname) {
+       
+       if(!textures) init_tex_man();
+       
+       Pair<string, Texture*> *res = textures->find(fname);
+       return res ? res->val : 0;
+}
+
+
+/* ----- get_texture() function -----
+ * first looks in the texture database in constant time (hash table)
+ * if the texture is already there it just returns the pointer. If the
+ * texture is not there it tries to load the image data, create the texture
+ * and return it, and if it fails it returns a NULL pointer
+ */
+Texture *get_texture(const char *fname) {
+       if(!fname) return 0;
+       
+       Texture *tex;
+       if((tex = find_texture(fname))) return tex;
+
+       // first check to see if it's a custom file (cubemap).
+       if(is_cubemap(fname)) {
+               tex = load_cubemap(fname);
+               add_texture(tex, fname);
+               return tex;
+       }
+       
+       PixelBuffer pbuf;
+       
+       void *img_buf = load_image(fname, &pbuf.width, &pbuf.height);
+       if(!img_buf) return 0;
+
+       pbuf.buffer = new Pixel[pbuf.width * pbuf.height];
+       memcpy(pbuf.buffer, img_buf, pbuf.width * pbuf.height * sizeof(Pixel));
+
+       free_image(img_buf);
+       
+       tex = new Texture;
+       tex->set_pixel_data(pbuf);
+       add_texture(tex, fname);
+       return tex;
+}
+
+
+void destroy_textures() {
+       static bool called_again = false;
+
+       if(called_again) {
+               warning("Multiple destroy_textures() calls");
+               return;
+       } else {
+               called_again = true;
+       }
+
+       info("Shutting down texture manager, destroying all textures...");
+       delete textures;
+       textures = 0;
+}
+
+
+Texture *make_cube_map(Texture **tex_array) {
+       int size = tex_array[0]->width;
+
+       Texture *cube = new Texture(size, size, TEX_CUBE);
+
+       cube->lock(CUBE_MAP_PX);
+       tex_array[CUBE_MAP_INDEX_PX]->lock();
+       memcpy(cube->buffer, tex_array[CUBE_MAP_INDEX_PX]->buffer, size * size * sizeof(Pixel));
+       tex_array[CUBE_MAP_INDEX_PX]->unlock();
+       cube->unlock(CUBE_MAP_PX);
+
+       cube->lock(CUBE_MAP_NX);
+       tex_array[CUBE_MAP_INDEX_NX]->lock();
+       memcpy(cube->buffer, tex_array[CUBE_MAP_INDEX_NX]->buffer, size * size * sizeof(Pixel));
+       tex_array[CUBE_MAP_INDEX_NX]->unlock();
+       cube->unlock(CUBE_MAP_NX);
+       
+       cube->lock(CUBE_MAP_PY);
+       tex_array[CUBE_MAP_INDEX_PY]->lock();
+       memcpy(cube->buffer, tex_array[CUBE_MAP_INDEX_PY]->buffer, size * size * sizeof(Pixel));
+       tex_array[CUBE_MAP_INDEX_PY]->unlock();
+       cube->unlock(CUBE_MAP_PY);
+       
+       cube->lock(CUBE_MAP_NY);
+       tex_array[CUBE_MAP_INDEX_NY]->lock();
+       memcpy(cube->buffer, tex_array[CUBE_MAP_INDEX_NY]->buffer, size * size * sizeof(Pixel));
+       tex_array[CUBE_MAP_INDEX_NY]->unlock();
+       cube->unlock(CUBE_MAP_NY);
+
+       cube->lock(CUBE_MAP_PZ);
+       tex_array[CUBE_MAP_INDEX_PZ]->lock();
+       memcpy(cube->buffer, tex_array[CUBE_MAP_INDEX_PZ]->buffer, size * size * sizeof(Pixel));
+       tex_array[CUBE_MAP_INDEX_PZ]->unlock();
+       cube->unlock(CUBE_MAP_PZ);
+
+       cube->lock(CUBE_MAP_NZ);
+       tex_array[CUBE_MAP_INDEX_NZ]->lock();
+       memcpy(cube->buffer, tex_array[CUBE_MAP_INDEX_NZ]->buffer, size * size * sizeof(Pixel));
+       tex_array[CUBE_MAP_INDEX_NZ]->unlock();
+       cube->unlock(CUBE_MAP_NZ);
+
+       return cube;
+}
+
+
+Texture *get_normal_cube() {
+       if(!normal_cubemap) create_normal_cube_map();
+       return normal_cubemap;
+}
+
+static Color vec_to_color(const Vector3 &v) {
+       return Color(v.x * 0.5 + 0.5, v.y * 0.5 + 0.5, v.z * 0.5 + 0.5);
+}
+
+static void create_normal_cube_map() {
+       static const int size = 32;
+       static const scalar_t fsize = (scalar_t)size;
+       static const scalar_t half_size = fsize / 2.0;
+       Pixel *ptr;
+       
+       delete normal_cubemap;
+       normal_cubemap = new Texture(size, size, TEX_CUBE);
+
+       // +X
+       normal_cubemap->lock(CUBE_MAP_PX);
+       ptr = normal_cubemap->buffer;
+       for(int j=0; j<size; j++) {
+               for(int i=0; i<size; i++) {
+                       Vector3 normal(half_size, -((scalar_t)j + 0.5 - half_size), -((scalar_t)i + 0.5 - half_size));
+                       *ptr++ = pack_color32(vec_to_color(normal.normalized()));
+               }
+       }
+       normal_cubemap->unlock(CUBE_MAP_PX);
+       
+       // -X
+       normal_cubemap->lock(CUBE_MAP_NX);
+       ptr = normal_cubemap->buffer;
+       for(int j=0; j<size; j++) {
+               for(int i=0; i<size; i++) {
+                       Vector3 normal(-half_size, -((scalar_t)j + 0.5 - half_size), (scalar_t)i + 0.5 - half_size);
+                       *ptr++ = pack_color32(vec_to_color(normal.normalized()));
+               }
+       }
+       normal_cubemap->unlock(CUBE_MAP_NX);
+       
+       // +Y
+       normal_cubemap->lock(CUBE_MAP_PY);
+       ptr = normal_cubemap->buffer;
+       for(int j=0; j<size; j++) {
+               for(int i=0; i<size; i++) {
+                       Vector3 normal((scalar_t)i + 0.5 - half_size, half_size, (scalar_t)j + 0.5 - half_size); 
+                       *ptr++ = pack_color32(vec_to_color(normal.normalized()));
+               }
+       }
+       normal_cubemap->unlock(CUBE_MAP_PY);
+       
+       // -Y
+       normal_cubemap->lock(CUBE_MAP_NY);
+       ptr = normal_cubemap->buffer;
+       for(int j=0; j<size; j++) {
+               for(int i=0; i<size; i++) {
+                       Vector3 normal((scalar_t)i + 0.5 - half_size, -half_size, -((scalar_t)j + 0.5 - half_size)); 
+                       *ptr++ = pack_color32(vec_to_color(normal.normalized()));
+               }
+       }
+       normal_cubemap->unlock(CUBE_MAP_NY);
+
+       // +Z
+       normal_cubemap->lock(CUBE_MAP_PZ);
+       ptr = normal_cubemap->buffer;
+       for(int j=0; j<size; j++) {
+               for(int i=0; i<size; i++) {
+                       Vector3 normal((scalar_t)i + 0.5 - half_size, -((scalar_t)j + 0.5 - half_size), half_size);
+                       *ptr++ = pack_color32(vec_to_color(normal.normalized()));
+               }
+       }
+       normal_cubemap->unlock(CUBE_MAP_PZ);
+
+       // -Z
+       normal_cubemap->lock(CUBE_MAP_NZ);
+       ptr = normal_cubemap->buffer;
+       for(int j=0; j<size; j++) {
+               for(int i=0; i<size; i++) {
+                       Vector3 normal(-((scalar_t)i + 0.5 - half_size), -((scalar_t)j + 0.5 - half_size), -half_size);
+                       *ptr++ = pack_color32(vec_to_color(normal.normalized()));
+               }
+       }
+       normal_cubemap->unlock(CUBE_MAP_NZ);
+}
+
+
+bool is_cubemap(const char *fname) {
+       FILE *fp = fopen(fname, "r");
+       if(!fp) {
+               return false;
+       }
+
+       char idstr[5];
+       fread(idstr, 1, 4, fp);
+       idstr[4] = 0;
+
+       fclose(fp);
+       return strcmp(idstr, "CUBE") == 0;
+}
+
+Texture *load_cubemap(const char *fname) {
+       FILE *fp = fopen(fname, "r");
+       if(!fp) {
+               error("could not open %s", fname);
+               return 0;
+       }
+
+       if(!is_cubemap(fname)) {
+               error("%s is not a cubemap", fname);
+               fclose(fp);
+               return 0;
+       }
+
+       char line[512];
+       unsigned int cube_size = 0;
+       unsigned long xsz = 0, ysz = 0;
+       void *img[6] = {0};
+
+       fgets(line, 512, fp);   // skip file id & text description
+       
+       if(fgets(line, 512, fp) && isdigit(*line)) {
+               cube_size = atoi(line);
+       }
+       
+       for(int i=0; i<6; i++) {
+               if(!fgets(line, 512, fp)) {
+                       error("%s is not a complete cubemap file, EOF encountered", fname);
+                       break;
+               }
+
+               if(line[strlen(line)-1] == '\n') {
+                       line[strlen(line)-1] = 0;
+               }
+               
+               unsigned long x, y;
+               if(!(img[i] = load_image(line, &x, &y))) {
+                       error("cubemap %s requires %s, which cannot be opened", fname, line);
+                       break;
+               }
+
+               if(i > 0 && (x != xsz || y != ysz)) {
+                       error("inconsistent cubemap %s, image sizes differ", fname);
+                       break;
+               }
+               xsz = x;
+               ysz = y;
+
+               if(xsz != ysz) {
+                       error("cubemap %s contains non-square textures", fname);
+                       break;
+               }
+       }
+
+       fclose(fp);
+       
+       if(!img[5]) {
+               for(int i=0; i<6; i++) {
+                       if(img[i]) free_image(img[i]);
+               }
+               return 0;
+       }
+       
+       if(xsz != cube_size) {
+               warning("cubemap %s loaded correctly, but wrong size in the header", fname);
+       }
+
+       Texture *cube = new Texture(cube_size, cube_size, TEX_CUBE);
+
+       CubeMapFace faces[] = {
+               CUBE_MAP_PX, CUBE_MAP_NX,
+               CUBE_MAP_PY, CUBE_MAP_NY,
+               CUBE_MAP_PZ, CUBE_MAP_NZ
+       };
+
+       for(int i=0; i<6; i++) {
+               cube->lock(faces[i]);
+               memcpy(cube->buffer, img[i], cube_size * cube_size * sizeof(Pixel));
+               cube->unlock(faces[i]);
+
+               free_image(img[i]);
+       }
+
+       return cube;
+}
diff --git a/src/3dengfx/src/3dengfx/texman.hpp b/src/3dengfx/src/3dengfx/texman.hpp
new file mode 100644 (file)
index 0000000..6a41a77
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+This file is part of 3dengfx, realtime visualization system.
+Copyright (C) 2004, 2005, 2006 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+#ifndef _TEXMAN_HPP_
+#define _TEXMAN_HPP_
+
+#include "textures.hpp"
+
+void add_texture(Texture *texture, const char *fname = 0);
+void remove_texture(Texture *texture);
+Texture *find_texture(const char *fname);
+
+Texture *get_texture(const char *fname);
+void destroy_textures();
+
+
+enum CubeMapIndex {
+       CUBE_MAP_INDEX_PX,
+       CUBE_MAP_INDEX_NX,
+       CUBE_MAP_INDEX_PY,
+       CUBE_MAP_INDEX_NY,
+       CUBE_MAP_INDEX_PZ,
+       CUBE_MAP_INDEX_NZ
+};
+
+Texture *make_cube_map(Texture **tex_array);
+Texture *get_normal_cube();
+
+bool is_cubemap(const char *fname);
+Texture *load_cubemap(const char *fname);
+
+#endif // _TEXMAN_HPP_
diff --git a/src/3dengfx/src/3dengfx/textures.cpp b/src/3dengfx/src/3dengfx/textures.cpp
new file mode 100644 (file)
index 0000000..e651375
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+This file is part of the 3dengfx, realtime visualization system.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+3dengfx is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+3dengfx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with 3dengfx; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "3dengfx_config.h"
+
+#include <string.h>
+#include <cassert>
+#include "opengl.h"
+#include "textures.hpp"
+
+static void invert_image(Pixel *img, int x, int y) {
+       Pixel *s2 = img + (y - 1) * x;
+       Pixel *tmp = new Pixel[x];
+       
+       int swaps = y / 2;
+       int sl_bytes = x * sizeof(Pixel);
+       for(int i=0; i<swaps; i++) {
+               memcpy(tmp, img, sl_bytes);
+               memcpy(img, s2, sl_bytes);
+               memcpy(s2, tmp, sl_bytes);
+               img += x;
+               s2 -= x;
+       }
+
+       delete [] tmp;
+}
+
+static PixelBuffer undef_pbuf;
+
+static void gen_undef_image(int x, int y) {
+       if((int)undef_pbuf.width != x || (int)undef_pbuf.height != y) {
+               if(undef_pbuf.buffer) {
+                       delete [] undef_pbuf.buffer;
+               }
+               undef_pbuf.width = x;
+               undef_pbuf.height = y;
+               undef_pbuf.pitch = x * sizeof(Pixel);
+               undef_pbuf.buffer = new Pixel[x * y];
+
+               for(int i=0; i<y; i++) {
+                       memset(&undef_pbuf.buffer[i * x], (i/(y >= 8 ? y/8 : 1))%2 ? 0x00ff0000 : 0, x * sizeof(Pixel));
+               }
+       }
+}
+
+
+Texture::Texture(int x, int y, TextureDim type) {
+       width = x;
+       height = type == TEX_1D ? 1 : y;
+       this->type = type;
+
+       if(x != -1 && y != -1) {
+               gen_undef_image(width, height);
+               add_frame(undef_pbuf);
+       }
+}
+
+Texture::Texture(int x, TextureDim type) {
+       width = x;
+       height = type == TEX_1D ? 1 : x;
+       this->type = type;
+
+       gen_undef_image(width, height);
+       add_frame(undef_pbuf);
+}
+               
+Texture::~Texture() {
+       // TODO: check if it's destroyed between a lock/unlock and free image data
+}
+
+void Texture::add_frame() {
+       glGenTextures(1, &tex_id);
+       glBindTexture(type, tex_id);
+       
+       glTexParameteri(type, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+       glTexParameteri(type, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+       if(type == TEX_CUBE) {
+               glTexParameteri(type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+               glTexParameteri(type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+       } else {
+               glTexParameteri(type, GL_TEXTURE_WRAP_S, GL_REPEAT);
+               glTexParameteri(type, GL_TEXTURE_WRAP_T, GL_REPEAT);
+       }
+       
+       frame_tex_id.push_back(tex_id);
+}
+
+void Texture::add_frame(const PixelBuffer &pbuf) {
+       add_frame();
+
+       if(type == TEX_CUBE) {
+               set_pixel_data(pbuf, CUBE_MAP_PX);
+               set_pixel_data(pbuf, CUBE_MAP_NX);
+               set_pixel_data(pbuf, CUBE_MAP_PY);
+               set_pixel_data(pbuf, CUBE_MAP_NY);
+               set_pixel_data(pbuf, CUBE_MAP_PZ);
+               set_pixel_data(pbuf, CUBE_MAP_NZ);
+       } else {
+               set_pixel_data(pbuf);
+       }
+}
+
+void Texture::set_active_frame(unsigned int frame) {
+       assert(frame < frame_tex_id.size());
+       
+       active_frame = frame;
+       tex_id = frame_tex_id[active_frame];
+}
+
+unsigned int Texture::get_active_frame() const {
+       return active_frame;
+}
+
+void Texture::lock(CubeMapFace cube_map_face) {
+       buffer = new Pixel[width * height];
+       
+       glBindTexture(type, tex_id);
+       
+       if(type == TEX_CUBE) {
+               glGetTexImage(cube_map_face, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
+       } else {
+               glGetTexImage(type, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
+       }
+
+       invert_image(buffer, width, height);
+}
+
+void Texture::unlock(CubeMapFace cube_map_face) {
+       glBindTexture(type, tex_id);
+
+       invert_image(buffer, width, height);
+
+       switch(type) {
+       case TEX_1D:
+               glTexImage1D(type, 0, 4, width, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
+               break;
+
+       case TEX_2D:
+               glTexImage2D(type, 0, 4, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
+               break;
+
+       case TEX_CUBE:
+               glTexImage2D(cube_map_face, 0, 4, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
+               break;
+
+       default:
+               break;
+       }
+       
+       delete [] buffer;
+       buffer = 0;
+}
+
+void Texture::set_pixel_data(const PixelBuffer &pbuf, CubeMapFace cube_map_face) {
+       
+       if(!frame_tex_id.size()) {
+               add_frame();
+       }
+               
+       width = pbuf.width;
+       height = pbuf.height;
+       
+       glBindTexture(type, tex_id);
+
+       buffer = new Pixel[width * height];
+       memcpy(buffer, pbuf.buffer, width * height * sizeof(Pixel));
+       invert_image(buffer, width, height);
+
+       switch(type) {
+       case TEX_1D:
+               glTexImage1D(type, 0, 4, width, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
+               break;
+
+       case TEX_2D:
+               glTexImage2D(type, 0, 4, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, buffer);
+               break;
+
+       case TEX_CUBE:
+               invert_image(buffer, width, height);
+               glTexImage2D(cube_map_face, 0, 4, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
+               break;
+
+       default:
+               break;
+       }
+
+       delete [] buffer;
+       buffer = 0;
+}
+
+TextureDim Texture::get_type() const {
+       return type;
+}
diff --git a/src/3dengfx/src/3dengfx/textures.hpp b/src/3dengfx/src/3dengfx/textures.hpp
new file mode 100644 (file)
index 0000000..3923f86
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+Copyright 2004 John Tsiombikas <nuclear@siggraph.org>
+
+This file is part of the 3dengfx, realtime visualization system.
+
+3dengfx is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+3dengfx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with 3dengfx; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#ifndef _TEXTURES_HPP_
+#define _TEXTURES_HPP_
+
+#include <vector>
+#include "gfx/pbuffer.hpp"
+#include "3denginefx_types.hpp"
+
+/* ---- Texture class ----
+** it does NOT hold the actual pixel data, if we need access to
+** the pixels we have to call lock() then the data are retrieved from
+** OpenGL, and unlock() updates the OpenGL texture from our modified
+** pixel data in pbuf.
+** if we wish to just set some pixel data without first retrieving the
+** actual data from OpenGL, we can use the function set_pixel_data() with a
+** new PixelBuffer as argument (this is copied, not referenced)
+*/
+class Texture : public PixelBuffer {
+private:
+       // for animated textures this will hold all the tex_ids of the frames
+       std::vector<unsigned int> frame_tex_id;
+       unsigned int active_frame;
+
+       TextureDim type;
+
+public:
+       unsigned int tex_id;    /* OpenGL texture id 
+                                                        * (for animated textures this is the active tex_id)
+                                                        */
+
+       Texture(int x = -1, int y = -1, TextureDim type = TEX_2D);
+       Texture(int x, TextureDim type = TEX_1D);
+       ~Texture();
+
+       void add_frame();
+       void add_frame(const PixelBuffer &pbuf);
+       
+       void set_active_frame(unsigned int frame);
+       unsigned int get_active_frame() const;
+       
+       void lock(CubeMapFace cube_map_face = CUBE_MAP_PX);             // get a valid pixel pointer
+       void unlock(CubeMapFace cube_map_face = CUBE_MAP_PX);   // update system data & invalidate pointer
+       
+       void set_pixel_data(const PixelBuffer &pbuf, CubeMapFace cube_map_face = CUBE_MAP_PX);
+
+       TextureDim get_type() const;
+};
+
+#endif // _TEXTURES_HPP_
diff --git a/src/3dengfx/src/3dengfx_config.h b/src/3dengfx/src/3dengfx_config.h
new file mode 100644 (file)
index 0000000..4be19c6
--- /dev/null
@@ -0,0 +1,33 @@
+/* this header is created by the 3dengfx configuration script */
+#ifndef _3DENGFX_CONFIG_H_
+#define _3DENGFX_CONFIG_H_
+
+#define USING_3DENGFX
+#define VER_STR        "0.5"
+#define PREFIX "/usr/local"
+
+#define SDL                                    1
+#define GLUT                           2
+#define GTK                                    3
+#define GTKMM                          4
+#define NATIVE                         5
+#define NATIVE_X11                     10
+#define NATIVE_WIN32           11
+
+#define GFX_LIBRARY SDL
+
+#define SINGLE_PRECISION_MATH
+
+#define COORD_LHS
+
+#define FXWT_NO_FREETYPE
+
+#if GFX_LIBRARY == NATIVE
+#if defined(unix) || defined(__unix__)
+#define NATIVE_LIB             NATIVE_X11
+#elif defined(WIN32) || defined(__WIN32__)
+#define NATIVE_LIB             NATIVE_WIN32
+#endif /* unix/win32 */
+#endif /* GFX_LIBRARY == NATIVE */
+
+#endif /* _3DENGFX_CONFIG_H_ */
diff --git a/src/3dengfx/src/common/byteorder.c b/src/3dengfx/src/common/byteorder.c
new file mode 100644 (file)
index 0000000..4beb68d
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+Copyright (C) 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <stdio.h>
+#include "byteorder.h"
+
+int8_t read_int8(FILE *fp) {
+       int8_t v;
+       fread(&v, 1, 1, fp);
+       return v;
+}
+
+int16_t read_int16(FILE *fp) {
+       int16_t v;
+       fread(&v, 2, 1, fp);
+       return v;
+}
+
+int16_t read_int16_inv(FILE *fp) {
+       int16_t v;
+       fread(&v, 2, 1, fp);
+       return v >> 8 | v << 8;
+}
+
+int32_t read_int32(FILE *fp) {
+       int32_t v;
+       fread(&v, 4, 1, fp);
+       return v;
+}
+
+int32_t read_int32_inv(FILE *fp) {
+       int32_t v;
+       fread(&v, 4, 1, fp);
+       return v >> 24 | (v & 0x00ff0000) >> 8 | (v & 0x0000ff00) << 8 | v << 24;
+}
+
+float read_float(FILE *fp) {
+       int32_t tmp = read_int32(fp);
+       return *((float*)&tmp);
+}
+
+float read_float_inv(FILE *fp) {
+       int32_t tmp = read_int32_inv(fp);
+       return *((float*)&tmp);
+}
+
+void write_int8(FILE *fp, int8_t v) {
+       fwrite(&v, 1, 1, fp);
+}
+
+void write_int16(FILE *fp, int16_t v) {
+       fwrite(&v, 2, 1, fp);
+}
+
+void write_int16_inv(FILE *fp, int16_t v) {
+       int16_t tmp = v >> 8 | v << 8;
+       fwrite(&tmp, 2, 1, fp);
+}
+
+void write_int32(FILE *fp, int32_t v) {
+       fwrite(&v, 4, 1, fp);
+}
+
+void write_int32_inv(FILE *fp, int32_t v) {
+       int32_t tmp = v >> 24 | (v & 0x00ff0000) >> 8 | (v & 0x0000ff00) << 8 | v << 24;
+       fwrite(&tmp, 4, 1, fp);
+}
+
+void write_float(FILE *fp, float v) {
+       write_int32(fp, *((int32_t*)&v));
+}
+void write_float_inv(FILE *fp, float v) {
+       write_int32_inv(fp, *((int32_t*)&v));
+}
diff --git a/src/3dengfx/src/common/byteorder.h b/src/3dengfx/src/common/byteorder.h
new file mode 100644 (file)
index 0000000..f040ffb
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+Copyright (C) 2004 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* byte order macros.
+ * author: John Tsiombikas 2004
+ * modified: John Tsiombikas 2006
+ */
+
+#ifndef _BYTEORDER_H_
+#define _BYTEORDER_H_
+
+#include <stdio.h>
+#include "types.h"
+
+/*The byte order determination procedure is derived from SDL's SDL_byteorder.h
+ * SDL is free software (LGPL), copyright: Sam Lantinga
+ */
+
+#if !defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN)
+
+#if  defined(__i386__) || defined(__ia64__) || defined(WIN32) || \
+    (defined(__alpha__) || defined(__alpha)) || \
+     defined(__arm__) || \
+    (defined(__mips__) && defined(__MIPSEL__)) || \
+     defined(__SYMBIAN32__) || \
+     defined(__x86_64__) || \
+     defined(__LITTLE_ENDIAN__)
+       
+/* little endian */
+#define LITTLE_ENDIAN
+
+#else
+/* big endian */       
+#define BIG_ENDIAN
+
+#endif /* endian check */
+#endif /* !defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN) */
+
+#ifdef LITTLE_ENDIAN
+/* little endian */
+#define read_int8_le(f)                read_int8(f)
+#define read_int8_be(f)                read_int8(f)
+#define read_int16_le(f)       read_int16(f)
+#define read_int16_be(f)       read_int16_inv(f)
+#define read_int32_le(f)       read_int32(f)
+#define read_int32_be(f)       read_int32_inv(f)
+#define read_float_le(f)       read_float(f)
+#define read_float_be(f)       read_float_inv(f)
+       
+#define write_int8_le(f, v)    write_int8(f, v)
+#define write_int8_be(f, v)    write_int8(f, v)
+#define write_int16_le(f, v)   write_int16(f, v)
+#define write_int16_be(f, v)   write_int16_inv(f, v)
+#define write_int32_le(f, v)   write_int32(f, v)
+#define write_int32_be(f, v)   write_int32_inv(f, v)
+#define write_float_le(f, v)   write_float(f, v)
+#define write_float_be(f, v)   write_float_inv(f, v)
+
+#else
+
+/* big endian */
+#define read_int8_be(f)                read_int8(f)
+#define read_int8_le(f)                read_int8(f)
+#define read_int16_be(f)       read_int16(f)
+#define read_int16_le(f)       read_int16_inv(f)
+#define read_int32_be(f)       read_int32(f)
+#define read_int32_le(f)       read_int32_inv(f)
+#define read_float_be(f)       read_float(f)
+#define read_float_le(f)       read_float_inv(f)
+       
+#define write_int8_be(f, v)    write_int8(f, v)
+#define write_int8_le(f, v)    write_int8(f, v)
+#define write_int16_be(f, v)   write_int16(f, v)
+#define write_int16_le(f, v)   write_int16_inv(f, v)
+#define write_int32_be(f, v)   write_int32(f, v)
+#define write_int32_le(f, v)   write_int32_inv(f, v)
+#define write_float_be(f, v)   write_float(f, v)
+#define write_float_le(f, v)   write_float_inv(f, v)
+
+#endif /* LITTLE_ENDIAN */
+
+int8_t read_int8(FILE *fp);
+int16_t read_int16(FILE *fp);
+int16_t read_int16_inv(FILE *fp);
+int32_t read_int32(FILE *fp);
+int32_t read_int32_inv(FILE *fp);
+float read_float(FILE *fp);
+float read_float_inv(FILE *fp);
+
+void write_int8(FILE *fp, int8_t v);
+void write_int16(FILE *fp, int16_t v);
+void write_int16_inv(FILE *fp, int16_t v);
+void write_int32(FILE *fp, int32_t v);
+void write_int32_inv(FILE *fp, int32_t v);
+void write_float(FILE *fp, float v);
+void write_float_inv(FILE *fp, float v);
+
+#endif /* _BYTEORDER_H_ */
diff --git a/src/3dengfx/src/common/config_parser.c b/src/3dengfx/src/common/config_parser.c
new file mode 100644 (file)
index 0000000..fa6ac0b
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+Copyright 2004 John Tsiombikas <nuclear@siggraph.org>
+
+This file is part of the eternal demo.
+
+The eternal library is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+The eternal demo is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with the eternal demo; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include "config_parser.h"
+
+/* state variables */
+static char sym_assign = '=';
+static char sym_comment = ';';
+static char max_line_len = 100;
+static char seperators[257] = " \t";
+static struct ConfigOption cfg_opt;
+
+static char *config_file, *cfgptr;
+
+void set_parser_state(enum ParserState state, long value) {
+       switch(state) {
+       case PS_AssignmentSymbol:
+               sym_assign = (char)value;
+               break;
+               
+       case PS_CommentSymbol:
+               sym_comment = (char)value;
+               break;
+               
+       case PS_MaxLineLen:
+               max_line_len = value;
+               break;
+               
+       case PS_Seperators:
+               strncpy(seperators, (char*)value, 257);
+               break;
+       }
+}
+
+int load_config_file(const char *fname) {
+       FILE *fp;
+       int fsize;
+       char *temp, *line;
+       
+       if(!fname) return -1;   
+       if(!(fp = fopen(fname, "r"))) return -1;
+       
+       fseek(fp, 0, SEEK_END);
+       fsize = ftell(fp);
+       fseek(fp, 0, SEEK_SET);
+       
+       if(!(temp = realloc(config_file, fsize))) return -1;
+       config_file = temp;
+       
+       cfgptr = config_file;
+       if(!(line = malloc(max_line_len + 1))) return -1;
+       while(fgets(line, max_line_len, fp)) {
+               char *ptr = line;
+               
+               if(*ptr == '\n') continue;      /* kill empty lines, they irritate the parser */
+               
+               while(ptr && *ptr && *ptr != sym_comment) {
+                       if(!strchr(seperators, *ptr)) { /* not a seperator */
+                               *cfgptr++ = *ptr;
+                       }
+                       ptr++;
+               }
+               
+               if(*ptr == sym_comment && ptr != line) {
+                       *cfgptr++ = '\n';
+               }
+       }
+       
+       *cfgptr = 0;
+       
+       memset(&cfg_opt, 0, sizeof(struct ConfigOption));
+       cfgptr = config_file;
+       free(line);
+       return 0;
+}
+
+const struct ConfigOption *get_next_option() {
+       char *tmpbuf = malloc(max_line_len + 1);
+       char *ptr = tmpbuf;
+       
+       if(!(*cfgptr)) {
+               free(tmpbuf);
+               return 0;
+       }
+       
+       while(*cfgptr != '\n') {
+               *ptr++ = *cfgptr++;
+       }
+       *ptr = 0;
+       cfgptr++;
+       
+       if(!(ptr = strchr(tmpbuf, sym_assign))) {
+               free(tmpbuf);
+               return 0;
+       }       
+       *ptr++ = 0;
+       
+       cfg_opt.flags = 0;
+       
+       cfg_opt.option = realloc(cfg_opt.option, strlen(tmpbuf) + 1);
+       strcpy(cfg_opt.option, tmpbuf);
+       
+       cfg_opt.str_value = realloc(cfg_opt.str_value, strlen(ptr) + 1);
+       strcpy(cfg_opt.str_value, ptr);
+       
+       if(isdigit(cfg_opt.str_value[0])) {
+               cfg_opt.flags |= CFGOPT_INT;
+               cfg_opt.int_value = atoi(cfg_opt.str_value);
+               cfg_opt.flt_value = atof(cfg_opt.str_value);
+       }
+
+       free(tmpbuf);   
+       return &cfg_opt;
+}
+
+void destroy_config_parser() {
+       if(cfg_opt.str_value) free(cfg_opt.str_value);
+       if(cfg_opt.option) free(cfg_opt.option);
+       if(config_file) free(config_file);
+       config_file = 0;
+}
diff --git a/src/3dengfx/src/common/config_parser.h b/src/3dengfx/src/common/config_parser.h
new file mode 100644 (file)
index 0000000..f2208f0
--- /dev/null
@@ -0,0 +1,37 @@
+#ifndef _CONFIG_PARSER_H_
+#define _CONFIG_PARSER_H_
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* _cplusplus */
+
+
+enum ParserState {
+       PS_AssignmentSymbol,
+       PS_CommentSymbol,
+       PS_Seperators,
+       PS_MaxLineLen
+};
+
+#define CFGOPT_INT     1
+#define CFGOPT_FLT     2
+       
+struct ConfigOption {
+       char *option, *str_value;
+       int int_value;
+       float flt_value;
+       unsigned short flags;
+};
+
+void set_parser_state(enum ParserState state, long value);
+int load_config_file(const char *fname);
+const struct ConfigOption *get_next_option();
+void destroy_config_parser();
+
+
+#ifdef __cplusplus
+}
+#endif /* _cplusplus */
+
+#endif /* _CONFIG_PARSER_H_ */
diff --git a/src/3dengfx/src/common/err_msg.c b/src/3dengfx/src/common/err_msg.c
new file mode 100644 (file)
index 0000000..78ddd63
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* Error messages and logging
+ *
+ * Author: John Tsiombikas 2004
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include "err_msg.h"
+
+#ifdef _MSC_VER
+#define vsnprintf(str, size, format, ap)       vsprintf(str, format, ap)
+#else
+int vsnprintf(char *str, size_t size, const char *format, va_list ap);
+#endif
+
+/* verbosity setting:
+ * 0 = do not output anything
+ * 1 = output only errors
+ * 2 = output errors and warnings
+ * 3 = output errors, warnings and informative messages
+ */
+
+static int verbosity = 3;
+static int log_verbosity = 4;
+
+static FILE *log_file;
+
+#define ERR_BUF_SIZE   4096
+static char err_buf[ERR_BUF_SIZE];
+
+#define MAX_LOG_FNAME  256
+static char log_fname[MAX_LOG_FNAME];
+
+static const char *default_log_fname(void) {
+#if defined(unix) || defined(__unix__)
+       return "/tmp/3dengfx.log";
+#elif defined(WIN32) || defined(__WIN32__)
+       return "3dengfx.log";
+#else
+       return "3dengfx.log";
+#endif
+}
+
+static int open_log_file() {
+       if(log_fname[0] == 0) {
+               set_log_filename(default_log_fname());
+       }
+       
+       if((log_file = fopen(log_fname, "a"))) {
+               setbuf(log_file, 0);
+       } else {
+               int prev_lv = log_verbosity;
+               log_verbosity = 0;
+               warning("could not open %s for writing", log_fname);
+               log_verbosity = prev_lv;
+       }
+
+       return log_file == 0 ? -1 : 0;
+}
+
+static void close_log_file() {
+       fclose(log_file);
+}
+
+void set_log_filename(const char *fname) {
+       strncpy(log_fname, fname, MAX_LOG_FNAME-1);
+}
+
+const char *get_log_filename(void) {
+       if(!*log_fname) {
+               return default_log_fname();
+       }
+       return log_fname;
+}
+
+void set_verbosity(int v) {
+       verbosity = v;
+}
+
+void set_log_verbosity(int v) {
+       log_verbosity = v;
+}
+
+void error(const char *str, ...) {
+       va_list arg_list;
+
+       strcpy(err_buf, "E: ");
+               
+       va_start(arg_list, str);
+       vsnprintf(err_buf+3, ERR_BUF_SIZE, str, arg_list);
+       va_end(arg_list);
+       
+       if(verbosity > 0) {
+               fputs(err_buf, stderr);
+               fputc('\n', stderr);
+       }
+
+       if(log_verbosity > 0 && open_log_file() != -1) {
+               fputs(err_buf, log_file);
+               fputc('\n', log_file);
+               close_log_file();
+       }
+}
+
+void warning(const char *str, ...) {
+       va_list arg_list;
+
+       strcpy(err_buf, "W: ");
+       
+       va_start(arg_list, str);
+       vsnprintf(err_buf+3, ERR_BUF_SIZE, str, arg_list);
+       va_end(arg_list);
+       
+       if(verbosity > 1) {
+               fputs(err_buf, stderr);
+               fputc('\n', stderr);
+       }
+
+       if(log_verbosity > 1 && open_log_file() != -1) {
+               fputs(err_buf, log_file);
+               fputc('\n', log_file);
+               close_log_file();
+       }
+}
+
+void info(const char *str, ...) {
+       va_list arg_list;
+
+       strcpy(err_buf, "I: ");
+       
+       va_start(arg_list, str);
+       vsnprintf(err_buf+3, ERR_BUF_SIZE, str, arg_list);
+       va_end(arg_list);
+       
+       if(verbosity > 2) {
+               fputs(err_buf, stdout);
+               fputc('\n', stdout);
+       }
+
+       if(log_verbosity > 2 && open_log_file() != -1) {
+               fputs(err_buf, log_file);
+               fputc('\n', log_file);
+               close_log_file();
+       }
+}
diff --git a/src/3dengfx/src/common/err_msg.h b/src/3dengfx/src/common/err_msg.h
new file mode 100644 (file)
index 0000000..61588af
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* Error messages and logging
+ *
+ * Author: John Tsiombikas 2004
+ */
+
+#ifndef _ERR_MSG_H_
+#define _ERR_MSG_H_
+
+/* verbosity setting:
+ * 0 = do not output anything
+ * 1 = output only errors
+ * 2 = output errors and warnings
+ * 3 = output errors, warnings and informative messages
+ */
+
+#ifdef _MSC_VER
+#define __func__       __FUNCTION__
+#endif /* MSC_VER */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+void set_verbosity(int value);
+void set_log_verbosity(int value);
+
+void set_log_filename(const char *fname);
+const char *get_log_filename(void);
+
+void error(const char *str, ...);
+void warning(const char *str, ...);
+void info(const char *str, ...);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _ERR_MSG_H_ */
diff --git a/src/3dengfx/src/common/fps_counter.c b/src/3dengfx/src/common/fps_counter.c
new file mode 100644 (file)
index 0000000..48aeef0
--- /dev/null
@@ -0,0 +1,35 @@
+#include <stdio.h>
+#include "fps_counter.h"
+
+void fps_start(fps_counter *fpsc, unsigned long time, unsigned long sample_interval) {
+       fpsc->sample_interval = sample_interval;
+       fpsc->sample_start_time = time;
+       fpsc->frame_count = 0;
+       fpsc->fps = 0.0f;
+}
+
+int fps_frame_proc(fps_counter *fpsc, unsigned long time) {
+       if(time - fpsc->sample_start_time < fpsc->sample_interval) {
+               fpsc->frame_count++;
+               return 0;
+       } else {
+               fpsc->fps = (float)fpsc->frame_count / ((float)fpsc->sample_interval / 1000.0f);
+
+               fpsc->sample_start_time = time;
+               fpsc->frame_count = 0;
+               return 1;
+       }
+}
+
+/* changed it to a macro, see header */
+/*
+float fps_get_frame_rate(fps_counter *fpsc) {
+       return fpsc->fps;
+}
+*/
+
+const char *fps_get_frame_rate_str(fps_counter *fpsc) {
+       static char str[32];
+       sprintf(str, "%.1f", fpsc->fps);
+       return str;
+}
diff --git a/src/3dengfx/src/common/fps_counter.h b/src/3dengfx/src/common/fps_counter.h
new file mode 100644 (file)
index 0000000..f9ef08c
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef _FPS_COUNTER_H_
+#define _FPS_COUNTER_H_
+
+typedef struct fps_counter {
+       unsigned long sample_interval;
+       unsigned long sample_start_time;
+       unsigned long frame_count;
+       float fps;
+} fps_counter;
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+void fps_start(fps_counter *fpsc, unsigned long time, unsigned long sample_interval);
+int fps_frame_proc(fps_counter *fpsc, unsigned long time);
+const char *fps_get_frame_rate_str(fps_counter *fpsc);
+
+#define fps_get_frame_rate(fpsc) (fpsc)->fps
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _FPS_COUNTER_H_ */
diff --git a/src/3dengfx/src/common/hashtable.hpp b/src/3dengfx/src/common/hashtable.hpp
new file mode 100644 (file)
index 0000000..4a28c25
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This is a hash table implementation with chaining collision resolution.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* Hash table with chaining.
+ * 
+ * Author: John Tsiombikas 2004
+ */
+
+// TODO: create a decent hash table and get rid of this mess.
+
+#ifndef _HASHTABLE_HPP_
+#define _HASHTABLE_HPP_
+
+#include <iostream>
+#include <list>
+#include <vector>
+#include <algorithm>
+
+template <class KeyT, class ValT> 
+struct Pair {
+       KeyT key; 
+       ValT val;
+};
+
+template <class KeyType, class ValType>
+class HashTable {
+private:
+       size_t size;
+       std::vector<std::list<Pair<KeyType, ValType> > > table;
+
+       unsigned int (*hash_func)(const KeyType &key, unsigned long size);
+       unsigned int hash(const KeyType &key) {return (unsigned int)hash_func(key, (unsigned long)size);}
+
+       void (*data_destructor)(ValType);
+public:
+
+       HashTable(unsigned long size = 101);
+       ~HashTable();
+
+       void set_hash_function(unsigned int (*hash_func)(const KeyType&, unsigned long));
+
+       void insert(KeyType key, ValType value);
+       void remove(KeyType key);
+
+       Pair<KeyType, ValType> *find(KeyType key);
+
+       void set_data_destructor(void (*destructor)(ValType));
+};
+
+
+// hash table member functions
+template <class KeyType, class ValType>
+HashTable<KeyType, ValType>::HashTable(unsigned long size) {
+       this->size = size;
+       table.resize(size);
+       data_destructor = 0;
+}
+
+template <class KeyType, class ValType>
+HashTable<KeyType, ValType>::~HashTable() {
+       for(unsigned long i=0; i<size; i++) {
+               if(data_destructor) {
+                       std::list<ValType> hacklist;
+
+                       typename std::list<Pair<KeyType, ValType> >::iterator iter = table[i].begin();
+                       while(iter != table[i].end()) {
+                               if(std::find(hacklist.begin(), hacklist.end(), iter->val) == hacklist.end()) {
+                                       hacklist.push_back(iter->val);
+                                       data_destructor((iter++)->val);
+                               }
+                       }
+               }
+                       
+               table[i].clear();
+       }
+}
+
+template <class KeyType, class ValType>
+void HashTable<KeyType, ValType>::set_hash_function(unsigned int (*hash_func)(const KeyType&, unsigned long)) {
+       this->hash_func = hash_func;
+}
+
+template <class KeyType, class ValType>
+void HashTable<KeyType, ValType>::insert(KeyType key, ValType value) {
+       Pair<KeyType, ValType> newpair;
+       newpair.key = key;
+       newpair.val = value;
+
+       table[hash(key)].push_back(newpair);
+}
+
+template <class KeyType, class ValType>
+void HashTable<KeyType, ValType>::remove(KeyType key) {
+
+       unsigned int pos = hash(key);
+
+       typename std::list<Pair<KeyType, ValType> >::iterator iter = table[pos].begin();
+       
+       while(iter != table[pos].end()) {
+               if(iter->key == key) {
+                       table[pos].erase(iter);
+                       return;
+               }
+               iter++;
+       }
+}
+
+template <class KeyType, class ValType>
+Pair<KeyType, ValType> *HashTable<KeyType, ValType>::find(KeyType key) {
+
+       unsigned int pos = hash(key);
+
+       typename std::list<Pair<KeyType, ValType> >::iterator iter = table[pos].begin();
+       while(iter != table[pos].end()) {
+               if(iter->key == key) {
+                       return &(*iter);
+               }
+               iter++;
+       }
+
+       return 0;
+}
+
+template <class KeyType, class ValType>
+void HashTable<KeyType, ValType>::set_data_destructor(void (*destructor)(ValType)) {
+       data_destructor = destructor;
+}
+
+#endif // _HASHTABLE_HPP_
diff --git a/src/3dengfx/src/common/linkedlist.hpp b/src/3dengfx/src/common/linkedlist.hpp
new file mode 100644 (file)
index 0000000..4cb380b
--- /dev/null
@@ -0,0 +1,260 @@
+/*
+Copyright 2004 John Tsiombikas <nuclear@siggraph.org>
+
+This file is part of the eternal demo.
+
+The eternal library is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+The eternal demo is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with the eternal demo; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#ifndef _LINKEDLIST_H_
+#define _LINKEDLIST_H_
+
+template <class T>
+struct ListNode {
+       T data;
+       ListNode<T> *next, *prev;
+};
+
+
+template <class T>
+class LinkedList {
+private:
+       ListNode<T> *head, *tail;
+       int sz;
+
+public:
+
+       LinkedList();
+       ~LinkedList();
+
+       inline ListNode<T> *begin();
+       inline const ListNode<T> *begin() const;
+       inline ListNode<T> *end();
+       inline const ListNode<T> *end() const;
+
+       void push_back(ListNode<T> *node);
+       void push_back(T data);
+
+       void insert(ListNode<T> *pos, ListNode<T> *node);
+       void insert(ListNode<T> *pos, T data);
+
+       void remove(ListNode<T> *node);
+       ListNode<T> *erase(ListNode<T> *node);
+
+       ListNode<T> *find(T key);
+
+       int count_nodes();
+       inline int size() const;
+
+       void operator =(LinkedList &rhs);
+};
+
+
+/////////// implementation //////////
+template <class T>
+LinkedList<T>::LinkedList() {
+       head = tail = 0;
+       sz = 0;
+}
+
+
+template <class T>
+LinkedList<T>::~LinkedList() {
+
+       while(head) {
+               erase(head);
+       }
+}
+
+template <class T>
+ListNode<T> *LinkedList<T>::begin() {
+       return head;
+}
+
+template <class T>
+const ListNode<T> *LinkedList<T>::begin() const {
+       return head;
+}
+
+template <class T>
+ListNode<T> *LinkedList<T>::end() {
+       return tail;
+}
+
+template <class T>
+const ListNode<T> *LinkedList<T>::end() const {
+       return tail;
+}
+
+template <class T>
+void LinkedList<T>::push_back(ListNode<T> *node) {
+
+       if(!head) {             // empty list
+               head = tail = node;
+               node->next = node->prev = 0;
+       } else {
+               tail->next = node;
+               node->prev = tail;
+               tail = node;
+               node->next = 0;
+       }
+
+       sz++;
+}
+
+template <class T>
+void LinkedList<T>::push_back(T data) {
+
+       ListNode<T> *node = new ListNode<T>;
+       node->data = data;
+
+       if(!head) {             // empty list
+               head = tail = node;
+               node->next = node->prev = 0;
+       } else {
+               tail->next = node;
+               node->prev = tail;
+               tail = node;
+               node->next = 0;
+       }
+
+       sz++;
+}
+
+template <class T>
+void LinkedList<T>::insert(ListNode<T> *pos, ListNode<T> *node) {
+
+       if(!head) {
+               head = tail = node;
+               node->next = node->prev = 0;
+       } else {
+               node->prev = pos->prev;
+               pos->prev = node;
+               node->next = pos;
+               if(head == pos) head = node; else node->prev->next = node;
+       }
+
+       sz++;
+}
+
+template <class T>
+void LinkedList<T>::insert(ListNode<T> *pos, T data) {
+
+       ListNode<T> *node = new ListNode<T>;
+       node->data = data;
+
+       if(!head) {
+               head = tail = node;
+               node->next = node->prev = 0;
+       } else {
+               node->prev = pos->prev;
+               pos->prev = node;
+               node->next = pos;
+               if(head == pos) head = node; else node->prev->next = node;
+       }
+
+       sz++;
+}
+
+template <class T>
+void LinkedList<T>::remove(ListNode<T> *node) {
+
+       if(!node) return;       // e.g. remove(head) on an empty list
+
+       if(node->prev) {
+               node->prev->next = node->next;
+       } else {
+               head = node->next;
+       }
+
+       if(node->next) {
+               node->next->prev = node->prev;
+       } else {
+               tail = node->prev;
+       }
+
+       sz--;
+}
+
+template <class T>
+ListNode<T> *LinkedList<T>::erase(ListNode<T> *node) {
+
+       if(!node) return 0;     // e.g. erase(head) on an empty list
+
+       if(node->prev) {
+               node->prev->next = node->next;
+       } else {
+               head = node->next;
+       }
+
+       if(node->next) {
+               node->next->prev = node->prev;
+       } else {
+               tail = node->prev;
+       }
+
+       ListNode<T> *destr = node;
+       node = node->next;
+       
+       delete destr;
+
+       sz--;
+
+       return node;
+}
+
+template <class T>
+ListNode<T> *LinkedList<T>::find(T key) {
+       
+       ListNode<T> *iter = head;
+       while(iter) {
+               if(iter->data == key) return iter;
+               iter = iter->next;
+       }
+
+       return 0;       // null pointer if not found
+}
+
+template <class T>
+int LinkedList<T>::count_nodes() {
+
+       sz = 0;
+
+       ListNode<T> *iter = head;
+       while(iter) {
+               sz++;
+               iter = iter->next;
+       }
+
+       return sz;
+}
+
+template <class T>
+int LinkedList<T>::size() const {
+       return sz;
+}
+
+
+template <class T>
+void LinkedList<T>::operator =(LinkedList<T> &rhs) {
+       
+       ListNode<T> *src = rhs.begin();
+       while(src) {
+               push_back(src->data);
+               src = src->next;
+       }
+}
+
+
+#endif // _LINKEDLIST_H_
diff --git a/src/3dengfx/src/common/locator.c b/src/3dengfx/src/common/locator.c
new file mode 100644 (file)
index 0000000..79f3732
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+This is a small cross-platform resource file locator library.
+Author: John Tsiombikas <nuclear@siggraph.org> 2004
+
+This library is public domain, you are free to do whatever you like with it,
+NO WARANTY whatsoever is provided with this library, use it at your own risk.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "locator.h"
+
+#ifdef HAVE_CONFIG
+#include "config.h"
+#endif /* HAVE_CONFIG */
+
+#ifdef __unix__
+#define __USE_BSD      /* to include readlink() prototype */
+#include <unistd.h>
+
+#define DIR_SEP                '/'
+#define HOME_ENV       "HOME"
+
+#else  /* assume WIN32 */
+#include <windows.h>
+
+#define DIR_SEP                '\\'
+#define HOME_ENV       "USERPROFILE"
+
+#endif /* __unix__ */
+
+
+#ifndef PREFIX
+#define PREFIX ""
+#endif /* PREFIX */
+
+#define MAX_PATH       1024
+#define CONF_ENV       "NLOC_CONFIG_PATH"
+#define DATA_ENV       "NLOC_DATA_PATH"
+#define LOC_FUNC_COUNT 2
+
+typedef const char *(*loc_func_type)(const char*);
+
+static const char *locate_config(const char *file);
+static const char *locate_data(const char *file);
+static const char *exec_path(void);
+
+static char path[MAX_PATH];
+static loc_func_type loc_func[LOC_FUNC_COUNT] = {locate_config, locate_data};
+
+const char *loc_get_path(const char *file, enum loc_file_type file_type) {
+       if(file_type >= LOC_FUNC_COUNT) return 0;
+       return loc_func[file_type](file);
+}
+
+static const char *locate_config(const char *file) {
+       FILE *fp;
+       char *env, *pptr = path;
+       const char *ex_path, *fptr = file;
+       
+       /* first try $NLOC_CONFIG_PATH/file */
+       env = getenv(CONF_ENV);
+       if(env) {
+               while(*env) *pptr++ = *env++;
+               if(*(env - 1) != DIR_SEP) *pptr++ = DIR_SEP;
+               while(*fptr) *pptr++ = *fptr++;
+               *pptr++ = 0;
+               
+               fprintf(stderr, "trying: %s\n", path);
+               if((fp = fopen(path, "r"))) {
+                       fclose(fp);
+                       return path;
+               }
+       }
+
+       /* then try $HOME/.file */
+       pptr = path;
+       fptr = file;
+       env = getenv(HOME_ENV);
+       if(env) {
+               while(*env) *pptr++ = *env++;
+               if(*(env - 1) != DIR_SEP) *pptr++ = DIR_SEP;
+#ifdef __unix__
+               *pptr++ = '.';
+#endif /* __unix__ */
+               while(*fptr) *pptr++ = *fptr++;
+               *pptr++ = 0;
+
+               fprintf(stderr, "trying: %s\n", path);
+               if((fp = fopen(path, "r"))) {
+                       fclose(fp);
+                       return path;
+               }
+       }
+
+#ifdef __unix__
+       /* then PREFIX/etc/file */
+       strcpy(path, PREFIX);
+       strcat(path, "/etc/");
+       strcat(path, file);
+       
+       fprintf(stderr, "trying: %s\n", path);
+       if((fp = fopen(path, "r"))) {
+               fclose(fp);
+               return path;
+       }
+#else
+       /* or something similar on win32 */
+       env = getenv("ALLUSERSPROFILE");
+       if(env) {
+               strcpy(path, env);
+               strcat(path, "\\");
+               strcat(path, file);
+
+               fprintf(stderr, "trying: %s\n", path);
+               if((fp = fopen(path, "r"))) {
+                       fclose(fp);
+                       return path;
+               }
+       }
+#endif /* __unix__ */
+
+
+       /* finally as a last resort try the executable directory, this may not work */
+       if((ex_path = exec_path())) {
+               strcpy(path, ex_path);
+               strcat(path, file);
+
+               fprintf(stderr, "trying: %s\n", path);
+               if((fp = fopen(path, "r"))) {
+                       fclose(fp);
+                       return path;
+               }
+       }
+
+       return 0;
+}
+
+/* TODO: not implemented yet */
+static const char *locate_data(const char *file) {
+       return 0;
+}
+
+static const char *exec_path(void) {
+       static char path[MAX_PATH];
+       int ccount = 0;
+       char *ptr;
+       
+#ifdef __linux__
+       ccount = readlink("/proc/self/exe", path, MAX_PATH - 1);
+#endif /* __linux__ */
+
+#ifdef __FreeBSD__
+       ccount = readlink("/proc/curproc/file", path, MAX_PATH - 1);
+#endif /* __FreeBSD__ */
+       
+#ifdef WIN32
+       ccount = GetModuleFileName(0, path, MAX_PATH - 1);      
+#endif /* WIN32 */
+       
+       if(!ccount) return 0;
+       
+       path[ccount] = 0;
+       
+       ptr = strrchr(path, DIR_SEP);
+       if(!ptr) return 0;
+       
+       *(ptr + 1) = 0;
+
+       return path;
+}
diff --git a/src/3dengfx/src/common/locator.h b/src/3dengfx/src/common/locator.h
new file mode 100644 (file)
index 0000000..2dfc322
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+This is a small cross-platform resource file locator library.
+Author: John Tsiombikas <nuclear@siggraph.org> 2004
+
+This library is public domain, you are free to do whatever you like with it,
+NO WARANTY whatsoever is provided with this library, use it at your own risk.
+*/
+
+#ifndef _LOCATOR_H_
+#define _LOCATOR_H_
+
+enum loc_file_type {
+       LOC_FILE_CONFIG,
+       LOC_FILE_DATA
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+const char *loc_get_path(const char *file, enum loc_file_type file_type);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _LOCATOR_H_ */
diff --git a/src/3dengfx/src/common/makefile.part b/src/3dengfx/src/common/makefile.part
new file mode 100644 (file)
index 0000000..2e754a5
--- /dev/null
@@ -0,0 +1,8 @@
+common_obj =\
+       src/common/config_parser.o\
+       src/common/timer.o\
+       src/common/string_hash.o\
+       src/common/fps_counter.o\
+       src/common/err_msg.o\
+       src/common/locator.o\
+       src/common/byteorder.o
diff --git a/src/3dengfx/src/common/psort.hpp b/src/3dengfx/src/common/psort.hpp
new file mode 100644 (file)
index 0000000..3944753
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+Copyright (C) 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* Priority sort template function
+ * 
+ * Author: Mihalis Georgoulopoulos 2005
+ */
+
+#include <cstring>
+#include <algorithm>
+
+#ifndef _PSORT_HEADER_
+#define _PSORT_HEADER_
+
+#define SORT_LOHI      false
+#define SORT_HILO      true
+
+template <class T> int less(const T* a, const T* b)
+{
+       return (*a < *b);
+}
+
+template <class T> int greater(const T* a, const T* b)
+{
+       return !(*a < *b);
+}
+
+template <class T, class P> void sort(T *elements, P *priorities, unsigned int n, bool hilo)
+{
+       int (*criterion)(const P*, const P*);
+
+       if (hilo)
+               criterion = greater;
+       else
+               criterion = less;
+
+       P **pointers = new P*[n];
+       for (unsigned int i=0; i<n; i++)
+               pointers[i] = priorities + i;
+
+       // sort priority pointers
+       std::sort(pointers, pointers + n, criterion);
+       
+       // collect sorted items
+       T *sorted_el = new T[n];
+       P *sorted_pr = new P[n];
+       for (unsigned int i=0; i<n; i++)
+       {
+               sorted_el[i] = elements[pointers[i] - priorities];
+               sorted_pr[i] = *pointers[i];
+       }
+
+       memcpy(elements, sorted_el, n * sizeof(T));
+       memcpy(priorities, sorted_pr, n * sizeof(P));
+       
+       // cleanup
+       delete [] pointers;
+       delete [] sorted_el;
+       delete [] sorted_pr;
+}
+
+#endif // ndef _PSORT_HEADER_
diff --git a/src/3dengfx/src/common/string_hash.cpp b/src/3dengfx/src/common/string_hash.cpp
new file mode 100644 (file)
index 0000000..9146299
--- /dev/null
@@ -0,0 +1,28 @@
+// This code belongs to the public domain.
+
+#include <string>
+#include <string.h>
+
+/*
+ * Hashing algorithm for strings from:
+ * Sedgewick's "Algorithms in C++, third edition" 
+ * parts 1-4, Chapter 14 (hashing) p.593
+ * 
+ * Modified to work on C++ string class objects by John Tsiombikas
+ */
+unsigned int string_hash(const std::string &key, unsigned long size) {
+       int hash = 0, a = 31415, b = 27183;
+       char *str = new char[key.length() + 1];
+       strcpy(str, key.c_str());
+
+       char *sptr = str;
+       
+       while(*sptr) {
+               hash = (a * hash + *sptr++) % size;
+               a = a * b % (size - 1);
+       }
+       
+       delete [] str;
+       
+       return (unsigned int)(hash < 0 ? (hash + size) : hash);
+}
diff --git a/src/3dengfx/src/common/string_hash.hpp b/src/3dengfx/src/common/string_hash.hpp
new file mode 100644 (file)
index 0000000..f076213
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef _STRING_HASH_HPP_
+#define _STRING_HASH_HPP_
+
+#include <string>
+
+unsigned int string_hash(const std::string &key, unsigned long size);
+
+#endif // _STRING_HASH_HPP_
diff --git a/src/3dengfx/src/common/timer.c b/src/3dengfx/src/common/timer.c
new file mode 100644 (file)
index 0000000..cdc39ce
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+Copyright 2004 John Tsiombikas <nuclear@siggraph.org>
+
+This is a cross-platform millisecond resolution timer library.
+
+This library is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#if defined(__unix__) || defined(unix)
+#include <time.h>
+#include <sys/time.h>
+
+#else  /* assume win32 */
+#include <windows.h>
+
+#endif /* __unix__ */
+
+#include "timer.h"
+
+/* BEWARE: this function will not work correctly if we go back in time
+ * and try to use it during the first second of 1-1-1970
+ */
+static unsigned long sys_get_msec(void) {
+#if defined(__unix__) || defined(unix)
+       static struct timeval timeval, first_timeval;
+       
+       gettimeofday(&timeval, 0);
+
+       if(first_timeval.tv_sec == 0) {
+               first_timeval = timeval;
+               return 0;
+       }
+       return (timeval.tv_sec - first_timeval.tv_sec) * 1000 + (timeval.tv_usec - first_timeval.tv_usec) / 1000;
+#else
+       return GetTickCount();
+#endif /* __unix__ */
+}
+
+
+void timer_start(ntimer *timer) {
+       timer->state = TSTATE_RUNNING;
+       timer->stopped_interval += timer_getmsec(timer) - timer->stop;
+       timer->stop = 0;
+}
+
+void timer_stop(ntimer *timer) {
+       timer->stop = timer_getmsec(timer);
+       timer->state = TSTATE_PAUSED;
+}
+
+void timer_reset(ntimer *timer) {
+       timer->state = TSTATE_RESET;
+       timer->start = sys_get_msec();
+       timer->stop = 0;
+       timer->stopped_interval = 0;
+       timer->offset = 0;
+}
+
+void timer_fwd(ntimer *timer, unsigned long msec) {
+       timer->offset += msec;
+       if(timer->state != TSTATE_RUNNING) {
+               timer->stop += msec;
+       }
+}
+
+void timer_back(ntimer *timer, unsigned long msec) {
+       timer->offset -= msec;
+       if(timer->state != TSTATE_RUNNING) {
+               timer->stop -= msec;
+       }
+}
+
+#define MAX(a, b)      ((a) > (b) ? (a) : (b))
+
+unsigned long timer_getmsec(ntimer *timer) {
+       if(timer->state == TSTATE_RUNNING) {
+               long time = (long)sys_get_msec() - timer->start - timer->stopped_interval + timer->offset;
+               if(time < 0) {
+                       timer_reset(timer);
+                       timer_start(timer);
+                       return 0;
+               }
+               return time;
+       } else {
+               return MAX(timer->stop, 0);
+       }
+       return 0;       /* can't happen */
+}
+
+unsigned long timer_getsec(ntimer *timer) {
+       return timer_getmsec(timer) / 1000;
+}
diff --git a/src/3dengfx/src/common/timer.h b/src/3dengfx/src/common/timer.h
new file mode 100644 (file)
index 0000000..82a5e40
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+Copyright 2004 John Tsiombikas <nuclear@siggraph.org>
+
+This is a cross-platform millisecond resolution timer library.
+
+This library is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef _TIMER_H_
+#define _TIMER_H_
+
+enum timer_state {TSTATE_RUNNING, TSTATE_PAUSED, TSTATE_RESET};
+
+typedef struct ntimer {
+       long stop, start, stopped_interval;
+       long offset;
+       enum timer_state state;
+} ntimer;
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+void timer_start(ntimer *timer);
+void timer_stop(ntimer *timer);
+void timer_reset(ntimer *timer);
+
+void timer_fwd(ntimer *timer, unsigned long msec);
+void timer_back(ntimer *timer, unsigned long msec);
+
+unsigned long timer_getmsec(ntimer *timer);
+unsigned long timer_getsec(ntimer *timer); 
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _TIMER_H_ */
diff --git a/src/3dengfx/src/common/types.h b/src/3dengfx/src/common/types.h
new file mode 100644 (file)
index 0000000..8e39518
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+Copyright (C) 2006 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* type.h finds the appropriate way to define sized integer types
+ * and also defines the standard scalar type based on the configuration.
+ */
+#ifndef FOO_TYPES_H_
+#define FOO_TYPES_H_
+
+#include "3dengfx_config.h"
+
+#ifdef SINGLE_PRECISION_MATH
+typedef float scalar_t;
+#else
+typedef double scalar_t;
+#endif /* floating point precision */
+
+#include <stdlib.h>            /* to get __GLIBC__ defined if applicable */
+
+#if defined(__MACH__) || defined(__MINGW32__)
+#define HAVE_STDINT_H
+#endif /* explicitly set stdint.h availability for some platform */
+
+#if (__STDC_VERSION__ >= 199900) || defined(__GLIBC__) || defined(HAVE_STDINT_H)
+#include <stdint.h>
+#elif defined(unix) || defined(__unix__)
+#include <sys/types.h>
+#elif defined(_MSC_VER)
+typedef __int8 int8_t;
+typedef unsigned __int8 uint8_t;
+typedef __int16 int16_t;
+typedef unsigned __int16 uint16_t;
+typedef __int32 int32_t;
+typedef unsigned __int32 uint32_t;
+typedef __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+#else
+#error "unsupported platform, or detection failed"
+#endif /* stdint detection */
+
+#endif /* FOO_TYPES_H_ */
diff --git a/src/3dengfx/src/dsys/cmd.cpp b/src/3dengfx/src/dsys/cmd.cpp
new file mode 100644 (file)
index 0000000..c99ff27
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+This file is part of 3dengfx demosystem.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* demosystem script controlled commands
+ *
+ * Author: John Tsiombikas 2005
+ */
+
+#include <cassert>
+#include "cmd.hpp"
+#include "script.h"
+#include "dsys.hpp"
+#include "part.hpp"
+#include "fx.hpp"
+#include "common/err_msg.h"
+
+using namespace dsys;
+using namespace cmd;
+
+// command handler prototypes
+static bool start_part(const char *pname, const char **args);
+static bool end_part(const char *pname, const char **args);
+static bool rename_part(const char *pname, const char **args);
+static bool set_render_target(const char *pname, const char **args);
+static bool set_clear(const char *pname, const char **args);
+static bool end(const char *unused, const char **args);
+static bool effect(const char *fxname, const char **args);
+
+static bool (*ftbl[64])(const char*, const char**);
+
+void cmd::register_commands() {
+       ftbl[CMD_START_PART] = start_part;
+       ftbl[CMD_END_PART] = end_part;
+       ftbl[CMD_RENAME_PART] = rename_part;
+       ftbl[CMD_SET_RTARGET] = set_render_target;
+       ftbl[CMD_SET_CLEAR] = set_clear;
+       ftbl[CMD_END] = end;
+       ftbl[CMD_FX] = effect;
+}
+
+bool cmd::command(CommandType cmd_id, const char *pname, const char **args) {
+       assert(ftbl[cmd_id]);
+
+       return ftbl[cmd_id](pname, args);
+}
+
+static bool start_part(const char *pname, const char **args) {
+       Part *part = get_part(pname);
+       if(part) {
+               info("start_part(%s)", pname);
+               start_part(part);
+               return true;
+       }
+       return false;
+}
+
+static bool end_part(const char *pname, const char **args) {
+       Part *part = get_part(pname);
+       if(part) {
+               info("end_part(%s)", pname);
+               stop_part(part);
+               return true;
+       }
+       return false;
+}
+
+static bool rename_part(const char *pname, const char **args) {
+       Part *part = get_part(pname);
+       if(part && args[0]) {
+               info("rename_part(%s, %s)", pname, args[0]);
+               remove_part(part);
+               part->set_name(args[0]);
+               add_part(part);
+               return true;
+       }
+       return false;
+}
+
+static bool set_render_target(const char *pname, const char **args) {
+       Part *part = get_part(pname);
+       if(part && args[0]) {
+               int tnum;
+
+               // check for valid render target specifier (fb, t0, t1, t2, t3)
+               if(!strcmp(args[0], "fb")) {
+                       tnum = (int)RT_FB;
+               } else {
+                       if(args[0][0] != 't' || !isdigit(args[0][1]) || args[0][2] ||
+                               (tnum = atoi(args[0]+1)) < 0 || tnum > 3) {
+                               return false;
+                       }
+               }
+
+               info("set_rtarg(%s, %s)", pname, args[0]);
+               part->set_target((RenderTarget)tnum);
+               return true;
+       }
+       return false;
+}
+
+static bool set_clear(const char *pname, const char **args) {
+       Part *part = get_part(pname);
+       if(part && args[0]) {
+               bool enable;
+               if(!strcmp(args[0], "true")) {
+                       enable = true;
+               } else if(!strcmp(args[0], "false")) {
+                       enable = false;
+               } else {
+                       return false;
+               }
+
+               info("set_clear(%s, %s)", pname, enable ? "true" : "false");
+               part->set_clear(enable);
+               return true;
+       }
+       return false;
+}
+
+static bool end(const char *unused, const char **args) {
+       if(unused && *unused) return false;
+
+       info("end");
+       end_demo();
+       return true;
+}
+
+static bool effect(const char *fxname, const char **args) {
+       ImageFx *fx;
+       
+       if(!strcmp(fxname, "neg")) {
+               fx = new FxNegative;
+       } else if(!strcmp(fxname, "flash")) {
+               fx = new FxFlash;
+       } else if(!strcmp(fxname, "overlay")) {
+               fx = new FxOverlay;
+       } else if(!strcmp(fxname, "fade")) {
+               fx = new FxFade;
+       } else {
+               error("unknown effect: %s, ignoring", fxname);
+               return false;
+       }
+
+       if(!fx->parse_script_args(args)) {
+               error("fx(%s): invalid syntax", fxname);
+               delete fx;
+               return false;
+       }
+
+       info("fx(%s)", fxname);
+       add_image_fx(fx);
+
+       return true;
+}
diff --git a/src/3dengfx/src/dsys/cmd.h b/src/3dengfx/src/dsys/cmd.h
new file mode 100644 (file)
index 0000000..e124d4a
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+This file is part of the 3dengfx demo system.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program demo is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifdef CMD
+#undef CMD
+#endif /* defined(CMD) */
+
+#ifdef NEED_COMMAND_STRINGS
+#define CMD(command)   #command
+#else
+#define CMD(command)   CMD_##command
+#endif /* weird hack */
+
+/* Here is the place to add/remove commands accepted by the demosystem */
+#define COMMANDS       \
+       CMD(START_PART),\
+       CMD(END_PART),\
+       CMD(RENAME_PART),\
+       CMD(SET_RTARGET),\
+       CMD(SET_CLEAR),\
+       CMD(END),\
+       CMD(FX)
diff --git a/src/3dengfx/src/dsys/cmd.hpp b/src/3dengfx/src/dsys/cmd.hpp
new file mode 100644 (file)
index 0000000..c65ae13
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+This file is part of 3dengfx demosystem.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* demosystem script controlled commands
+ *
+ * Author: John Tsiombikas 2005
+ */
+
+#ifndef _CMD_HPP_
+#define _CMD_HPP_
+
+#include "script.h"
+
+namespace cmd {
+       void register_commands();
+
+       bool command(CommandType cmd_id, const char *pname, const char **args);
+}
+
+#endif // _CMD_HPP_
diff --git a/src/3dengfx/src/dsys/demosys.hpp b/src/3dengfx/src/dsys/demosys.hpp
new file mode 100644 (file)
index 0000000..e0a2041
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+Copyright 2004 John Tsiombikas <nuclear@siggraph.org>
+
+This file is part of the eternal demo.
+
+The eternal library is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+The eternal demo is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with the eternal demo; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#ifndef _DEMOSYS_HPP_
+#define _DEMOSYS_HPP_
+
+#include "dsys.hpp"
+#include "fx.hpp"
+#include "part.hpp"
+#include "scene_part.hpp"
+
+#endif // _DEMOSYS_HPP_
diff --git a/src/3dengfx/src/dsys/dsys.cpp b/src/3dengfx/src/dsys/dsys.cpp
new file mode 100644 (file)
index 0000000..0490bb6
--- /dev/null
@@ -0,0 +1,285 @@
+/*
+This file is part of 3dengfx demosystem.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "3dengfx_config.h"
+
+#include <iostream>
+#include <algorithm>
+#include <string>
+#include <map>
+#include "dsys.hpp"
+#include "part.hpp"
+#include "fx.hpp"
+#include "cmd.hpp"
+#include "script.h"
+#include "3dengfx/3dengfx.hpp"
+#include "n3dmath2/n3dmath2.hpp"
+#include "common/timer.h"
+#include "common/err_msg.h"
+
+#if defined(__unix__) || defined(unix)
+#include <unistd.h>
+#include <sys/stat.h>
+#endif // unix
+
+using namespace dsys;
+using namespace std;
+
+static int execute_script(DemoScript *ds, unsigned long time);
+
+Texture *dsys::tex[4];
+unsigned int dsys::rtex_size_x, dsys::rtex_size_y;
+Matrix4x4 dsys::tex_mat[4];
+
+typedef map<string, Part*> PartTree;
+static PartTree parts;
+static PartTree running;
+
+static ntimer timer;
+
+static char script_fname[256];
+static DemoScript *ds;
+
+static bool demo_running = false;
+static bool seq_render = false;
+static unsigned long seq_time, seq_dt;
+
+static int best_tex_size(int n) {
+       int i;
+       for(i=64; i<2048; i*=2) {
+               if(i*2 > n) return i;
+       }
+
+       return 2048;
+}
+
+bool dsys::init() {
+       int scrx = get_graphics_init_parameters()->x;
+       int scry = get_graphics_init_parameters()->y;
+
+       int next_size_x, next_size_y;
+       
+       rtex_size_x = best_tex_size(scrx - 1);
+       rtex_size_y = best_tex_size(scry - 1);
+       
+       next_size_x = rtex_size_x * 2;
+       next_size_y = rtex_size_y * 2;
+               
+       info("allocating dsys render targets:");
+
+       //if (!engfx_state::sys_caps.non_power_of_two_textures)
+       //{
+               // make a high-res texture and 3 low-res
+               for(int i=0; i<4; i++) {
+                       int x = (i > 1) ? rtex_size_x : next_size_x;
+                       int y = (i > 1) ? rtex_size_y : next_size_y;
+                       tex[i] = new Texture(x, y);
+                       info("  %d - %dx%d", i, x, y);
+               }
+
+               tex_mat[0].set_scaling(Vector3((float)scrx / (float)next_size_x, (float)scry / (float)next_size_y, 1));
+               tex_mat[1].set_scaling(Vector3((float)scrx / (float)next_size_x, (float)scry / (float)next_size_y, 1));
+
+               tex_mat[2] = Matrix4x4::identity_matrix;
+               tex_mat[3] = Matrix4x4::identity_matrix;
+       /*}
+       else
+       {
+               for (int i=0; i<4; i++)
+               {
+                       tex[i] = new Texture(scrx, scry);
+                       info("  %d - %dx%d", i, scrx, scry);
+                       tex_mat[i] = Matrix4x4::identity_matrix;
+               }
+       }*/
+
+       strcpy(script_fname, "demoscript");
+
+       cmd::register_commands();
+       
+       return true;
+}
+
+void dsys::clean_up() {
+       for(int i=0; i<4; i++) {
+               if(tex[i]) delete tex[i];
+               tex[i] = 0;
+       }
+}
+
+void dsys::use_rt_tex(RenderTarget rt) {
+       set_texture(0, tex[rt]);
+       set_matrix(XFORM_TEXTURE, tex_mat[rt]);
+}
+
+void dsys::set_demo_script(const char *fname) {
+       strcpy(script_fname, fname);
+}
+
+
+unsigned long dsys::get_demo_time() {
+       return seq_render ? seq_time : timer_getmsec(&timer);
+}
+
+
+void dsys::add_part(Part *part) {
+       if(!part->get_name()) {
+               error("dsys::add_part - trying to add a nameless part...");
+               return;
+       }
+       parts[string(part->get_name())] = part;
+}
+
+void dsys::remove_part(Part *part) {
+       PartTree::iterator iter = parts.find(part->get_name());
+       parts.erase(iter);
+}
+
+void dsys::start_part(Part *part) {
+       running[part->get_name()] = part;
+       part->start();
+}
+
+void dsys::stop_part(Part *part) {
+       part->stop();
+       PartTree::iterator iter = running.find(part->get_name());
+       if(iter != running.end()) {
+               running.erase(iter);
+       } else {
+               error("stop_part() called for unknown part: %s\n", part->get_name());
+       }
+}
+
+Part *dsys::get_part(const char *pname) {
+       PartTree::iterator iter = parts.find(pname);
+       return iter != parts.end() ? iter->second : 0;
+}
+
+Part *dsys::get_running(const char *pname) {
+       PartTree::iterator iter = running.find(pname);
+       return iter != running.end() ? iter->second : 0;
+}
+
+
+bool dsys::start_demo() {
+       if(!(ds = open_script(script_fname))) {
+               return false;
+       }
+       demo_running = true;
+       timer_reset(&timer);
+       timer_start(&timer);
+       return true;
+}
+
+#define PATH_MAX 2048
+static char curr_dir[PATH_MAX];
+
+bool dsys::render_demo(int fps, const char *out_dir) {
+       if(!(ds = open_script(script_fname))) {
+               return false;
+       }
+       
+#if defined(__unix__) || defined(unix)
+       // change to the specified directory
+       getcwd(curr_dir, PATH_MAX);
+
+       struct stat sbuf;
+       if(stat(out_dir, &sbuf) == -1) {
+               mkdir(out_dir, 0770);
+       }       
+       
+       chdir(out_dir);
+#endif // __unix__
+
+       demo_running = true;
+       seq_render = true;
+       seq_time = 0;
+       seq_dt = 1000 / fps;
+
+       return true;
+}
+
+void dsys::end_demo() {
+#if defined(__unix__) || defined(unix)
+       if(seq_render) {
+               chdir(curr_dir);
+       }
+#endif // unix
+       
+       if(demo_running) {
+               close_script(ds);
+               demo_running = false;
+       }
+}
+
+
+static void update_node(const pair<string, Part*> &p) {
+       p.second->update_graphics();
+}
+
+int dsys::update_graphics() {
+       if(!demo_running) {
+               return 1;
+       }
+
+       unsigned long time = get_demo_time();
+
+       int res;
+       while((res = execute_script(ds, time)) != 1) {
+               if(res == EOF) {
+                       end_demo();
+                       return -1;
+               }
+       }
+
+       // update graphics
+       clear(Color(0.0f, 0.0f, 0.0f));
+       clear_zbuffer_stencil(1.0f, 0);
+       
+       for_each(running.begin(), running.end(), update_node);
+
+       // apply any post effects
+       apply_image_fx(time);
+
+       if(seq_render) {
+               screen_capture();
+               seq_time += seq_dt;
+       }
+               
+       flip();
+       return 0;
+}
+
+static int execute_script(DemoScript *ds, unsigned long time) {
+       DemoCommand command;
+       
+       int res = get_next_command(ds, &command, time);
+       if(res == EOF || res == 1) {
+               return res;
+       }
+
+       if(!cmd::command(command.type, command.argv[0], command.argv + 1)) {
+               error("error in demoscript command execution!");
+       }
+       free_command(&command);
+
+       return demo_running ? 0 : -1;
+}
+
diff --git a/src/3dengfx/src/dsys/dsys.hpp b/src/3dengfx/src/dsys/dsys.hpp
new file mode 100644 (file)
index 0000000..6ea937b
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+This file is part of the 3dengfx demo system.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program demo is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#ifndef _DSYS_HPP_
+#define _DSYS_HPP_
+
+#include "3dengfx/textures.hpp"
+
+namespace dsys {
+
+       class Part;
+
+       // NOTE: the order in this enum is IMPORTANT, do not shuffle around
+       enum RenderTarget {RT_TEX0, RT_TEX1, RT_TEX2, RT_TEX3, RT_FB};
+
+       // the texture targets
+       extern Texture *tex[4];
+       extern unsigned int rtex_size_x, rtex_size_y;
+       extern Matrix4x4 tex_mat[4];
+
+       bool init();
+       void clean_up();
+
+       void use_rt_tex(RenderTarget rt);
+
+       void set_demo_script(const char *fname);
+
+       unsigned long get_demo_time();
+
+       void add_part(Part *part);
+       void remove_part(Part *part);
+       void start_part(Part *part);
+       void stop_part(Part *part);
+
+       Part *get_part(const char *pname);
+       Part *get_running(const char *pname);
+       
+       bool start_demo();
+       bool render_demo(int fps = 25, const char *out_dir = "frames");
+       void end_demo();
+       int update_graphics();
+}
+
+#endif // _DSYS_HPP_
diff --git a/src/3dengfx/src/dsys/fx.cpp b/src/3dengfx/src/dsys/fx.cpp
new file mode 100644 (file)
index 0000000..c089bd3
--- /dev/null
@@ -0,0 +1,513 @@
+/*
+This file is part of the 3dengfx demo system.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "3dengfx_config.h"
+
+#include <list>
+#include <algorithm>
+#include "fx.hpp"
+#include "dsys.hpp"
+#include "script.h"
+#include "3dengfx/3dengfx.hpp"
+#include "common/err_msg.h"
+
+
+static bool str_to_color(const char *str, Color *col);
+
+
+void dsys::radial_blur(Texture *tex, float ammount, const Vector2 &origin, bool additive) {
+       Vector2 c1(0.0f, 0.0f), c2(1.0f, 1.0f);
+
+       set_alpha_blending(true);
+       if(additive) {
+               set_blend_func(BLEND_SRC_ALPHA, BLEND_ONE);
+       } else {
+               set_blend_func(BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA);
+       }
+       
+       ammount += 1.0f;
+       int quad_count = (int)(ammount * 20.0f);
+       float dscale = (ammount - 1.0f) / (float)quad_count;
+       float scale = 1.0f;
+       for(int i=0; i<quad_count; i++) {
+               Vector2 v1 = c1, v2 = c2;
+               v1 -= origin;
+               v1 *= scale;
+               v1 += origin;
+
+               v2 -= origin;
+               v2 *= scale;
+               v2 += origin;
+               
+               float alpha = (float)((quad_count-1) - i) / (float)quad_count;
+               dsys::overlay(tex, v1, v2, Color(1.0f, 1.0f, 1.0f, alpha), false);
+               scale += dscale;
+       }
+
+       set_alpha_blending(false);
+}
+
+void dsys::dir_blur(Texture *tex, float ammount, int dir) {
+       Vector2 c1(0.0f, 1.0f), c2(1.0f, 0.0f);
+       
+       ammount *= 0.5f;
+       int quad_count = (int)(ammount * 100.0f);
+       float offs_inc = ammount / (float)(quad_count/2);
+       float offs = 0.0f;
+       for(int i=0; i<quad_count/2; i++) {
+               Vector2 off_vec = dir == BLUR_DIR_X ? Vector2(offs, 0) : Vector2(0, offs);
+
+               float alpha = 1.0f - offs / ammount;
+               dsys::overlay(tex, c1 + off_vec, c2 + off_vec, Color(1.0f, 1.0f, 1.0f, alpha));
+               //dsys::overlay(tex, c1 - off_vec, c2 - off_vec, Color(1.0f, 1.0f, 1.0f, alpha));
+               offs += offs_inc;
+       }
+}
+
+/*
+static Vector2 *blur_pos;
+static int pos_count;
+
+void dsys::blur(Texture *tex, float ammount, bool additive) {
+       //additive = true;
+
+       set_alpha_blending(true);
+       if(additive) {
+               set_blend_func(BLEND_SRC_ALPHA, BLEND_ONE);
+       } else {
+               set_blend_func(BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA);
+       }
+
+       int quad_count = (int)(ammount * 700.0f);
+
+       if(quad_count != pos_count) {
+               if(blur_pos) delete [] blur_pos;
+               blur_pos = new Vector2[quad_count];
+
+               for(int i=0; i<quad_count; i++) {
+                       blur_pos[i] = Vector2(frand(1.0f) - 0.5f, frand(1.0f) - 0.5f);
+                       blur_pos[i] *= ammount;
+               }
+               pos_count = quad_count;
+       }
+       
+       for(int i=0; i<quad_count; i++) {
+               float dist = blur_pos[i].length_sq();
+               float alpha = 1.0f / dist;
+               dsys::overlay(tex, Vector2(0, 0) + blur_pos[i], Vector2(1, 1) + blur_pos[i], Color(1.0f, 1.0f, 1.0f, alpha), false);
+       }
+
+       set_alpha_blending(false);
+}
+*/
+
+void dsys::overlay(Texture *tex, const Vector2 &corner1, const Vector2 &corner2, const Color &color, GfxProg *pprog, bool handle_blending) {
+       glMatrixMode(GL_MODELVIEW);
+       glPushMatrix();
+       glLoadIdentity();
+       
+       glMatrixMode(GL_PROJECTION);
+       glPushMatrix();
+       glLoadIdentity();
+       glOrtho(0.0, 1.0, 1.0, 0.0, 0.0, 1.0);
+
+       set_lighting(false);
+       set_zbuffering(false);
+       set_backface_culling(false);
+       if(handle_blending) {
+               set_alpha_blending(true);
+               set_blend_func(BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA);
+       }
+
+       if(tex) {
+               enable_texture_unit(0);
+               disable_texture_unit(1);
+               set_texture_unit_color(0, TOP_REPLACE, TARG_TEXTURE, TARG_COLOR);
+               set_texture_unit_alpha(0, TOP_MODULATE, TARG_TEXTURE, TARG_COLOR);
+               set_texture_coord_index(0, 0);
+               set_texture(0, tex);
+               set_texture_addressing(0, TEXADDR_CLAMP, TEXADDR_CLAMP);
+
+               for(int i=0; i<4; i++) {
+                       if(tex == dsys::tex[i]) {
+                               glMatrixMode(GL_TEXTURE);
+                               load_matrix_gl(dsys::tex_mat[i]);
+                               break;
+                       }
+               }
+       }
+
+       if(pprog) {
+               set_gfx_program(pprog);
+       }
+       
+       glBegin(GL_QUADS);
+       glColor4f(color.r, color.g, color.b, color.a);
+       glTexCoord2f(0.0f, 1.0f);
+       glVertex3f(corner1.x, corner1.y, -0.5);
+       glTexCoord2f(1.0f, 1.0f);
+       glVertex3f(corner2.x, corner1.y, -0.5);
+       glTexCoord2f(1.0f, 0.0f);
+       glVertex3f(corner2.x, corner2.y, -0.5);
+       glTexCoord2f(0.0f, 0.0f);
+       glVertex3f(corner1.x, corner2.y, -0.5);
+       glEnd();
+
+       if(pprog) {
+               set_gfx_program(0);
+       }
+       
+       if(tex) {
+               for(int i=0; i<4; i++) {
+                       if(tex == dsys::tex[i]) {
+                               glMatrixMode(GL_TEXTURE);
+                               load_matrix_gl(Matrix4x4::identity_matrix);
+                               break;
+                       }
+               }
+               set_texture_addressing(0, TEXADDR_WRAP, TEXADDR_WRAP);
+               disable_texture_unit(0);
+       }
+       if(handle_blending) set_alpha_blending(false);
+       set_backface_culling(true);
+       set_zbuffering(true);
+       set_lighting(true);
+
+       glMatrixMode(GL_PROJECTION);
+       glPopMatrix();
+       glMatrixMode(GL_MODELVIEW);
+       glPopMatrix();
+}
+
+void dsys::negative(const Vector2 &corner1, const Vector2 &corner2) {
+       set_alpha_blending(true);
+       set_blend_func(BLEND_ONE_MINUS_DST_COLOR, BLEND_ZERO);
+       dsys::overlay(0, corner1, corner2, Color(1.0f, 1.0f, 1.0f, 1.0f), 0, false);
+       set_alpha_blending(false);
+}
+
+void dsys::flash(unsigned long time, unsigned long when, unsigned long dur, const Color &col) {
+       long start = when - dur/2;
+       long end = when + dur/2;
+       
+       if((long)time >= start && (long)time < end) {
+               scalar_t t = (scalar_t)time / 1000.0;
+               scalar_t dt = (scalar_t)dur / 1000.0;
+               scalar_t wt = (scalar_t)when / 1000.0;
+               scalar_t half_dt = dt / 2.0;
+               
+               scalar_t alpha = cos(pi * (t - wt) / half_dt);
+
+               dsys::overlay(0, Vector3(0,0), Vector3(1,1), Color(col.r, col.g, col.b, alpha));
+       }
+}
+
+
+
+// ------------- Image Effect manager --------------
+
+using std::list;
+using namespace dsys;
+
+static list<ImageFx*> fx_list;
+
+void dsys::add_image_fx(ImageFx *fx) {
+       fx_list.push_back(fx);
+}
+
+void dsys::remove_image_fx(ImageFx *fx) {
+       fx_list.erase(find(fx_list.begin(), fx_list.end(), fx));
+}
+
+void dsys::apply_image_fx(unsigned long time) {
+       list<ImageFx*>::iterator iter = fx_list.begin();
+
+       while(iter != fx_list.end()) {
+               (*iter++)->apply(time);
+       }
+}
+
+
+// -------------- Image Effect class --------------
+
+ImageFx::ImageFx() {
+       time = 0;
+       duration = 0;
+}
+
+ImageFx::~ImageFx() {}
+
+bool ImageFx::parse_script_args(const char **args) {
+       long t, d;
+
+       if(!args[0] || (t = str_to_time(args[0])) == -1) {
+               return false;
+       }
+
+       if(!args[1] || (d = str_to_time(args[1])) == -1) {
+               return false;
+       }
+
+       time = t;
+       duration = d;
+       return true;
+}
+
+void ImageFx::set_time(unsigned long time) {
+       this->time = time;
+}
+
+void ImageFx::set_duration(unsigned long dur) {
+       duration = dur;
+}
+
+
+// ------------- Negative (inverse video) effect ---------------
+
+FxNegative::~FxNegative() {}
+
+void FxNegative::apply(unsigned long time) {
+       if(time < this->time || time > this->time + duration) return;
+
+       negative();
+}
+
+// ------------ Screen Flash -------------
+
+FxFlash::~FxFlash() {}
+
+FxFlash::FxFlash() {
+       color = Color(1.0, 1.0, 1.0);
+}
+
+bool FxFlash::parse_script_args(const char **args) {
+       if(!ImageFx::parse_script_args(args)) {
+               return false;
+       }
+
+       if(args[2]) {
+               if(!str_to_color(args[2], &color)) return false;
+       }
+
+       return true;
+}
+
+void FxFlash::set_color(const Color &col) {
+       color = col;
+}
+
+void FxFlash::apply(unsigned long time) {
+       flash(time, this->time, duration, color);
+}
+
+
+// ------------- Fade in/out -------------
+
+FxFade::FxFade() {
+       color1 = Color(0.0, 0.0, 0.0);
+       color2 = Color(1.0, 1.0, 1.0);
+       tex1 = tex2 = 0;
+}
+
+FxFade::~FxFade() {}
+
+bool FxFade::parse_script_args(const char **args) {
+       if(!ImageFx::parse_script_args(args)) {
+               return false;
+       }
+
+       if(args[2]) {
+               if(!str_to_color(args[2], &color1)) return false;
+       }
+
+       if(args[3] && !(args[3][0] == '0' && args[3][1] == 0)) {
+               // texture register? (t0, t1, t2, t3)
+               if(args[3][0] == 't' && isdigit(args[3][1]) && !args[3][2]) {
+                       int reg = args[3][1] - '0';
+                       if(reg > 3) return false;
+                       tex1 = dsys::tex[reg];
+               } else {        // or a texture from file?
+                       if(!(tex1 = get_texture(args[3]))) {
+                               return false;
+                       }
+               }
+       }
+
+       if(args[4]) {
+               if(!str_to_color(args[4], &color2)) return false;
+       }
+
+       if(args[5] && !(args[5][0] == '0' && args[5][1] == 0)) {
+               // texture register? (t0, t1, t2, t3)
+               if(args[5][0] == 't' && isdigit(args[5][1]) && !args[5][2]) {
+                       int reg = args[5][1] - '0';
+                       if(reg > 3) return false;
+                       tex2 = dsys::tex[reg];
+               } else {        // or a texture from file?
+                       if(!(tex2 = get_texture(args[5]))) {
+                               return false;
+                       }
+               }
+       }
+
+       return true;
+}
+
+void FxFade::apply(unsigned long time) {
+       if(time >= this->time && time < this->time + duration) {
+               float fsec = (float)(time - this->time) / 1000.0;
+               float t = fsec / ((float)duration / 1000.0);
+
+               if(tex1) {
+                       set_texture(0, tex1);
+                       enable_texture_unit(0);
+               }
+               
+               if(tex2) {
+                       set_texture(1, tex2);
+                       enable_texture_unit(1);
+
+                       set_texture_constant(1, t);
+                       set_texture_unit_color(1, TOP_LERP, TARG_PREV, TARG_TEXTURE, TARG_CONSTANT);
+               }
+
+               set_alpha_blending(true);
+               set_blend_func(BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA);
+               set_lighting(false);
+
+               Color col = color1 + (color2 - color1) * t;
+               col.a = color1.a + (color2.a - color1.a) * t;
+               
+               draw_scr_quad(Vector2(0, 0), Vector2(1, 1), col);
+
+               set_lighting(true);
+               set_alpha_blending(false);
+
+               if(tex1) disable_texture_unit(0);
+               if(tex2) disable_texture_unit(1);
+       }
+}
+
+// ------------ Image Overlay ------------
+
+
+FxOverlay::FxOverlay() {
+       tex = 0;
+       shader = 0;
+}
+
+FxOverlay::~FxOverlay() {
+       delete shader;
+}
+
+bool FxOverlay::parse_script_args(const char **args) {
+       if(!ImageFx::parse_script_args(args)) {
+               return false;
+       }
+       if(!args[2]) return false;
+
+       // texture register? (t0, t1, t2, t3)
+       if(args[2][0] == 't' && isdigit(args[2][1]) && !args[2][2]) {
+               int reg = args[2][1] - '0';
+               if(reg > 3) return false;
+               tex = dsys::tex[reg];
+       } else {        // or a texture from file?
+               if(!(tex = get_texture(args[2]))) {
+                       return false;
+               }
+       }
+
+       // check if a shader is specified
+       if(args[3]) {
+               Shader sdr = get_shader(args[3], PROG_PIXEL);
+               if(!sdr) {
+                       error("failed loading shader %s", args[3]);
+                       return false;
+               }
+
+               shader = new GfxProg(0, sdr);
+               shader->link();
+       }
+       return true;
+}
+
+void FxOverlay::set_texture(Texture *tex) {
+       this->tex = tex;
+}
+
+void FxOverlay::set_shader(GfxProg *sdr) {
+       shader = sdr;
+}
+
+void FxOverlay::apply(unsigned long time) {
+       if(time >= this->time && time < this->time + duration) {
+               if(shader) {
+                       float fsec = (float)(time - this->time) / 1000.0;
+                       shader->set_parameter("time", fsec);
+
+                       float t = fsec / ((float)duration / 1000.0f);
+                       shader->set_parameter("t", t);
+
+                       float ease = (t < 0.25 || t >= 0.75) ? fabs(sin(t * 2.0 * pi)) : 1.0;
+                       shader->set_parameter("ease", ease);
+
+                       float ease_sin = sin(t * pi);
+                       shader->set_parameter("ease_sin", ease_sin);
+               }
+               overlay(tex, Vector2(0, 0), Vector2(1, 1), Color(1, 1, 1), shader);
+       }
+}
+
+
+
+// just a little helper function to get a color out of an <r,g,b> string
+static bool str_to_color(const char *str, Color *col) {
+       // get red
+       if(*str++ != '<') return false;
+       if(!isdigit(*str) && *str != '.') return false;
+       col->r = atof(str);
+
+       while(isdigit(*str) || *str == '.') str++;
+       if(*str++ != ',') return false;
+
+       // get green
+       if(!isdigit(*str) && *str != '.') return false;
+       col->g = atof(str);
+
+       while(isdigit(*str) || *str == '.') str++;
+       if(*str++ != ',') return false;
+
+       // get blue
+       if(!isdigit(*str) && *str != '.') return false;
+       col->b = atof(str);
+       
+       while(isdigit(*str) || *str == '.') str++;
+       if(*str != ',') {
+               col->a = 1.0;
+               return *str == '>' ? true : false;
+       }
+
+       // get alpha
+       if(!isdigit(*++str) && *str != '.') return false;
+       col->a = atof(str);
+       
+       while(isdigit(*str) || *str == '.') str++;
+       return *str == '>' ? true : false;
+}
diff --git a/src/3dengfx/src/dsys/fx.hpp b/src/3dengfx/src/dsys/fx.hpp
new file mode 100644 (file)
index 0000000..04b6360
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+This file is part of the 3dengfx demo system.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#ifndef _FX_HPP_
+#define _FX_HPP_
+
+#include "n3dmath2/n3dmath2.hpp"
+#include "gfx/color.hpp"
+#include "3dengfx/3denginefx_types.hpp"
+
+class Texture;
+
+namespace dsys {
+
+       enum {BLUR_DIR_X, BLUR_DIR_Y};
+       
+       // effects
+       void radial_blur(Texture *tex, float ammount, const Vector2 &origin = Vector2(0.5f, 0.5f), bool additive = false);
+       void dir_blur(Texture *tex, float ammount, int dir);
+       //void blur(Texture *tex, float ammount, bool additive = false);
+       void overlay(Texture *tex, const Vector2 &corner1, const Vector2 &corner2, const Color &color, GfxProg *pprog=0, bool handle_blending = true);
+       void negative(const Vector2 &corner1 = Vector2(0,0), const Vector2 &corner2 = Vector2(1,1));
+       void flash(unsigned long time, unsigned long when, unsigned long dur, const Color &col = Color(1,1,1));
+       
+       // integration with the scripting system
+       
+       class ImageFx;
+
+       void add_image_fx(ImageFx *fx);
+       void remove_image_fx(ImageFx *fx);
+       void apply_image_fx(unsigned long time);
+
+       class ImageFx {
+       protected:
+               unsigned long time, duration;
+
+       public:
+               ImageFx();
+               virtual ~ImageFx();
+               virtual bool parse_script_args(const char **args);
+
+               virtual void set_time(unsigned long time);
+               virtual void set_duration(unsigned long dur);
+
+               virtual void apply(unsigned long time) = 0;
+       };
+
+       class FxNegative : public ImageFx {
+       public:
+               virtual ~FxNegative();
+               virtual void apply(unsigned long time);
+       };
+
+       class FxFlash : public ImageFx {
+       protected:
+               Color color;
+
+       public:
+               FxFlash();
+               virtual ~FxFlash();
+               virtual bool parse_script_args(const char **args);
+               
+               virtual void set_color(const Color &col);
+               virtual void apply(unsigned long time);
+       };
+
+       class FxFade : public ImageFx {
+       protected:
+               Color color1, color2;
+               Texture *tex1, *tex2;
+
+       public:
+               FxFade();
+               virtual ~FxFade();
+               virtual bool parse_script_args(const char **args);
+
+               virtual void apply(unsigned long time);
+       };
+
+       class FxOverlay : public ImageFx {
+       protected:
+               Texture *tex;
+               GfxProg *shader;
+
+       public:
+               FxOverlay();
+               virtual ~FxOverlay();
+               virtual bool parse_script_args(const char **args);
+
+               virtual void set_texture(Texture *tex);
+               virtual void set_shader(GfxProg *sdr);
+               virtual void apply(unsigned long time);
+       };
+}
+
+#endif // _FX_HPP_
diff --git a/src/3dengfx/src/dsys/makefile.part b/src/3dengfx/src/dsys/makefile.part
new file mode 100644 (file)
index 0000000..14be496
--- /dev/null
@@ -0,0 +1,7 @@
+dsys_obj = \
+       src/dsys/dsys.o\
+       src/dsys/fx.o\
+       src/dsys/part.o\
+       src/dsys/scene_part.o\
+       src/dsys/script.o\
+       src/dsys/cmd.o
diff --git a/src/3dengfx/src/dsys/part.cpp b/src/3dengfx/src/dsys/part.cpp
new file mode 100644 (file)
index 0000000..e1ceba4
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+This file is part of the 3dengfx demo system.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program demo is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "3dengfx_config.h"
+
+#include <iostream>
+#include <cstring>
+#include "part.hpp"
+#include "3dengfx/3dengfx.hpp"
+
+using namespace dsys;
+
+Part::Part(const char *name) {
+       if(name) {
+               this->name = new char[strlen(name)+1];
+               strcpy(this->name, name);
+       } else {
+               this->name = 0;
+       }
+       
+       target = RT_FB;
+       clear_fb = false;
+       //timer_reset(&timer);
+}
+
+Part::~Part() {
+       if(name) delete [] name;
+}
+
+
+void Part::pre_draw() {
+       if(target != RT_FB) {
+               ::set_render_target(dsys::tex[target]);
+       }
+       
+       if(clear_fb) {
+               clear(Color(0, 0, 0));
+               clear_zbuffer_stencil(1.0f, 0);
+       }
+       time = dsys::get_demo_time() - start_time;
+       //timer_getmsec(&timer);
+}
+
+void Part::post_draw() {
+       if(target != RT_FB) {
+               ::set_render_target(0);
+       }
+
+       // reset states
+       for(int i=0; i<8; i++) {
+               glDisable(GL_LIGHT0 + i);
+       }
+
+       set_ambient_light(0.0f);
+}
+
+void Part::set_name(const char *name) {
+       this->name = new char[strlen(name)+1];
+       strcpy(this->name, name);
+}
+
+const char *Part::get_name() const {
+       return name;
+}
+
+void Part::set_clear(bool enable) {
+       clear_fb = enable;
+}
+
+void Part::start() {
+       //timer_start(&timer);
+       start_time = dsys::get_demo_time();
+}
+
+void Part::stop() {
+       //timer_stop(&timer);
+}
+
+void Part::set_target(RenderTarget targ) {
+       target = targ;
+}
+
+void Part::update_graphics() {
+       pre_draw();
+       draw_part();
+       post_draw();
+}
+
+bool Part::operator <(const Part &part) const {
+       if(!name) return true;
+       if(!part.name) return false;
+       return strcmp(name, part.name) < 0;
+}
diff --git a/src/3dengfx/src/dsys/part.hpp b/src/3dengfx/src/dsys/part.hpp
new file mode 100644 (file)
index 0000000..02e35ec
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+This file is part of the 3dengfx demo system.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program demo is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef _PART_HPP_
+#define _PART_HPP_
+
+#include "common/timer.h"
+#include "dsys.hpp"
+
+namespace dsys {
+
+       class Part {
+       protected:
+               char *name;
+               //ntimer timer;
+               unsigned long start_time;
+               unsigned long time;
+               dsys::RenderTarget target;
+               bool clear_fb;
+
+               virtual void pre_draw();
+               virtual void draw_part() = 0;
+               virtual void post_draw();
+
+       public:
+
+               Part(const char *name = 0);
+               virtual ~Part();
+
+               void set_name(const char *name);
+               const char *get_name() const;
+               virtual void set_clear(bool enable);
+
+               virtual void start();
+               virtual void stop();
+
+               virtual void set_target(RenderTarget targ);
+
+               virtual void update_graphics();
+
+               /* the < operator compares the names,
+                * intended for use by the binary tree.
+                */
+               bool operator <(const Part &part) const;
+       };
+}
+
+#endif // _PART_HPP_
diff --git a/src/3dengfx/src/dsys/scene_part.cpp b/src/3dengfx/src/dsys/scene_part.cpp
new file mode 100644 (file)
index 0000000..f6e7d2c
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+This file is part of the 3dengfx demo system.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program demo is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* Scene derived class for ready 3d scenes
+ *
+ * Author: John Tsiombikas 2005
+ */
+
+#include "scene_part.hpp"
+#include "3dengfx/sceneloader.hpp"
+#include "common/err_msg.h"
+
+using namespace dsys;
+
+ScenePart::ScenePart(const char *name, Scene *scene) : Part(name) {
+       this->scene = scene;
+}
+
+ScenePart::ScenePart(const char *name, const char *scene_file) : Part(name) {
+       if(!(scene = load_scene(scene_file))) {
+               error("ScenePart: %s, failed loading scene: %s", name, scene_file);
+               scene = 0;
+       }
+}
+
+ScenePart::~ScenePart() {
+       if(scene) delete scene;
+}
+
+void ScenePart::draw_part() {
+       scene->render(time);
+}
+
+void ScenePart::set_scene(Scene *scene) {
+       this->scene = scene;
+}
diff --git a/src/3dengfx/src/dsys/scene_part.hpp b/src/3dengfx/src/dsys/scene_part.hpp
new file mode 100644 (file)
index 0000000..66c5536
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+This file is part of the 3dengfx demo system.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* Scene derived class for ready 3d scenes
+ *
+ * Author: John Tsiombikas 2005
+ */
+
+#ifndef _SCENE_PART_HPP_
+#define _SCENE_PART_HPP_
+
+#include "part.hpp"
+#include "3dengfx/3dscene.hpp"
+
+namespace dsys {
+
+       class ScenePart : public Part {
+       protected:
+               Scene *scene;
+
+               virtual void draw_part();
+
+       public:
+               ScenePart(const char *name = 0, Scene *scene = 0);
+               ScenePart(const char *name, const char *scene_file);
+               virtual ~ScenePart();
+
+               void set_scene(Scene *scene);
+       };
+}
+
+#endif // _SCRENE_PART_HPP_
diff --git a/src/3dengfx/src/dsys/script.c b/src/3dengfx/src/dsys/script.c
new file mode 100644 (file)
index 0000000..c40daca
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+This file is part of the 3dengfx demo system.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program demo is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+#include "3dengfx_config.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <ctype.h>
+#include <assert.h>
+#include "script.h"
+
+#define NEED_COMMAND_STRINGS
+#include "cmd.h"
+
+#define BUF_LEN                1024
+
+static char *cmd_symb[] = {COMMANDS, 0};
+
+DemoScript *open_script(const char *fname) {
+       DemoScript *script = malloc(sizeof(DemoScript));
+       
+       if(!(script->file = fopen(fname, "r"))) {
+               free(script);
+               return 0;
+       }               
+       script->fname = malloc(strlen(fname)+1);
+       strcpy(script->fname, fname);
+
+       script->line_buffer = malloc(BUF_LEN);
+       script->line_buffer[0] = 0;
+
+       script->line = 0;
+
+       return script;
+}
+
+void close_script(DemoScript *ds) {
+       fclose(ds->file);
+       free(ds->fname);
+       free(ds);
+}
+
+
+static char *skip_spaces(char *ptr) {
+       while(*ptr && *ptr != '\n' && isspace(*ptr)) ptr++;
+       return ptr;
+}
+
+int get_next_command(DemoScript *ds, DemoCommand *cmd, unsigned long time) {
+       char *ptr;
+       char *cmd_tok;
+       int i;
+       
+       /* get next line if one is available */
+       if(ds->line_buffer[0] == 0) {
+               if(!fgets(ds->line_buffer, BUF_LEN, ds->file)) {
+                       return EOF;
+               }
+               ds->line++;
+       }
+
+       ptr = skip_spaces(ds->line_buffer);
+
+       /* skip comments and empty lines */
+       if(*ptr == '#' || *ptr == '\n') {
+               ds->line_buffer[0] = 0;
+               return get_next_command(ds, cmd, time);
+       }
+
+       /* retrieve command time */
+       cmd->time = atoi(ptr);
+       
+       /* skip timestamp and following whitespace */
+       while(*ptr && *ptr != '\n' && (isdigit(*ptr) || isspace(*ptr) || (isdigit(*(ptr-1)) && *ptr == 's'))) {
+               if(*ptr == 's') cmd->time *= 1000;
+               ptr++;
+       }
+       if(!*ptr || *ptr == '\n') {
+               fprintf(stderr, "Skipping invalid line %ld: %s\n", ds->line, ds->line_buffer);
+               ds->line_buffer[0] = 0;
+               return get_next_command(ds, cmd, time);
+       }
+       
+       if(cmd->time > time) {
+               return 1;       /* time is in the future */
+       }
+
+       /* seperate command name substring (cmd_tok), ptr keeps the rest */
+       cmd_tok = ptr;
+       while(*ptr && !isspace(*ptr)) ptr++;
+       *ptr++ = 0;
+
+       /* make the command name upper-case */
+       for(i=0; cmd_tok[i]; i++) {
+               cmd_tok[i] = toupper(cmd_tok[i]);
+       }
+
+       /* match the command string with the available commands */
+       cmd->type = (CommandType)UINT_MAX;
+       for(i=0; cmd_symb[i]; i++) {
+               if(!strcmp(cmd_tok, cmd_symb[i])) {
+                       cmd->type = i;
+                       break;
+               }
+       }
+       
+       if(cmd->type == (CommandType)UINT_MAX) {
+               fprintf(stderr, "Skipping invalid line %ld: Unrecognized command %s\n", ds->line, cmd_tok);
+               ds->line_buffer[0] = 0;
+               return get_next_command(ds, cmd, time);
+       }
+
+       /* tokenize the rest of the arguments and put them into argv */
+       cmd_tok = ptr = skip_spaces(ptr);
+       cmd->argc = *ptr ? 1 : 0;
+
+       while(*ptr && *ptr != '\n') {
+               if(isspace(*ptr)) {
+                       ptr = skip_spaces(ptr);
+                       if(*ptr && *ptr != '\n') cmd->argc++;
+               } else {
+                       ptr++;
+               }
+       }
+       
+       cmd->argv = malloc((cmd->argc + 1) * sizeof(char*));
+       for(i=0; i<cmd->argc; i++) {
+               ptr = strtok(i ? 0 : cmd_tok, " \t\n");
+               assert(ptr);
+
+               cmd->argv[i] = malloc(strlen(ptr) + 1);
+               strcpy((char*)cmd->argv[i], ptr);
+       }
+       cmd->argv[i] = 0;
+       
+       /*
+       if(!*ptr || *ptr == '\n') {
+               cmd->args = 0;
+       } else {
+               unsigned int len = strlen(ptr);
+               cmd->args = malloc(len + 1);
+               strcpy(cmd->args, ptr);
+               if(cmd->args[len - 1] == '\n') {
+                       cmd->args[len - 1] = 0;
+               }
+       }
+       */
+       ds->line_buffer[0] = 0;
+       
+       return 0;
+}
+
+void free_command(DemoCommand *cmd) {
+       int i;
+       for(i=0; i<cmd->argc; i++) {
+               free((void*)cmd->argv[i]);
+       }
+       free(cmd->argv);
+}
+
+long str_to_time(const char *str) {
+       long time;
+       
+       if(!isdigit(*str)) return -1;
+
+       time = atol(str);
+
+       while(isdigit(*str)) str++;
+       
+       return *str == 's' ? time * 1000 : time;
+}
diff --git a/src/3dengfx/src/dsys/script.h b/src/3dengfx/src/dsys/script.h
new file mode 100644 (file)
index 0000000..b995c6c
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+This file is part of the 3dengfx demo system.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program demo is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef _SCRIPT_H_
+#define _SCRIPT_H_
+
+#include <stdio.h>
+#include "cmd.h"
+
+typedef struct DemoScript {
+       char *fname;
+       FILE *file;
+       char *line_buffer;
+       long line;
+} DemoScript;
+
+typedef enum CommandType {
+       COMMANDS
+} CommandType;
+
+typedef struct DemoCommand {
+       unsigned long time;
+       CommandType type;
+       const char **argv;
+       int argc;
+} DemoCommand;
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+DemoScript *open_script(const char *fname);
+void close_script(DemoScript *ds);
+
+/* returns EOF on eof, 0 for successfull retrieval of command an 1 if
+ * the command on the next line is to be executed at the future
+ */
+int get_next_command(DemoScript *ds, DemoCommand *cmd, unsigned long time);
+void free_command(DemoCommand *cmd);
+
+long str_to_time(const char *str);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _SCRIPT_H_ */
diff --git a/src/3dengfx/src/fxwt/fxwt.cpp b/src/3dengfx/src/fxwt/fxwt.cpp
new file mode 100644 (file)
index 0000000..d75561b
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+This file is part of fxwt, the window system toolkit of 3dengfx.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* main fxwt event handling and system abstraction.
+ *
+ * Author: John Tsiombikas 2004
+ * Modified:
+ *             John Tsiombikas 2005
+ */
+
+#include <iostream>
+#include <list>
+#include <stdlib.h>
+#include "3dengfx/3denginefx.hpp"
+#include "common/err_msg.h"
+#include "fxwt.hpp"
+#include "text.hpp"
+#include "gfx_library.h"
+
+using std::list;
+
+namespace fxwt {
+       list<void (*)()> disp_handlers;
+       list<void (*)()> idle_handlers;
+       list<void (*)(int)> keyb_handlers;
+       list<void (*)(int, int)> motion_handlers;
+       list<void (*)(int, int, int, int)> button_handlers;
+       
+       bool button_state[6];
+       int screenx, screeny;
+}
+
+using namespace fxwt;
+
+void fxwt::init() {
+       fxwt::text_init();
+
+       const GraphicsInitParameters *gip = get_graphics_init_parameters();
+       screenx = gip->x;
+       screeny = gip->y;
+}
+
+void fxwt::set_display_handler(void (*handler)()) {
+       disp_handlers.push_back(handler);
+}
+
+void fxwt::set_idle_handler(void (*handler)()) {
+       idle_handlers.push_back(handler);
+}
+
+void fxwt::set_keyboard_handler(void (*handler)(int)) {
+       keyb_handlers.push_back(handler);
+}
+
+void fxwt::set_motion_handler(void (*handler)(int, int)) {
+       motion_handlers.push_back(handler);
+}
+
+void fxwt::set_button_handler(void (*handler)(int, int, int, int)) {
+       button_handlers.push_back(handler);
+}
+
+void fxwt::remove_display_handler(void (*handler)()) {
+       disp_handlers.remove(handler);
+}
+
+void fxwt::remove_idle_handler(void (*handler)()) {
+       idle_handlers.remove(handler);
+}
+
+void fxwt::remove_keyboard_handler(void (*handler)(int)) {
+       keyb_handlers.remove(handler);
+}
+
+void fxwt::remove_motion_handler(void (*handler)(int, int)) {
+       motion_handlers.remove(handler);
+}
+
+void fxwt::remove_button_handler(void (*handler)(int, int, int, int)) {
+       button_handlers.remove(handler);
+}
+
+bool fxwt::mouse_button_pressed(int bn) {
+       return button_state[bn];
+}
diff --git a/src/3dengfx/src/fxwt/fxwt.hpp b/src/3dengfx/src/fxwt/fxwt.hpp
new file mode 100644 (file)
index 0000000..b7684c2
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+This file is part of fxwt, the window system toolkit of 3dengfx.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* main fxwt event handling and system abstraction.
+ *
+ * Author: John Tsiombikas 2004
+ */
+
+#ifndef _FXWT_HPP_
+#define _FXWT_HPP_
+
+#include <list>
+
+#include "text.hpp"
+#include "init.hpp"
+#include "keysyms.hpp"
+
+namespace fxwt {
+
+       enum {
+               BN_LEFT                 = 1,
+               BN_MIDDLE               = 2,
+               BN_RIGHT                = 3,
+               BN_WHEELUP              = 4,
+               BN_WHEELDOWN    = 5
+       };
+
+       extern std::list<void (*)()> disp_handlers;
+       extern std::list<void (*)()> idle_handlers;
+       extern std::list<void (*)(int)> keyb_handlers;
+       extern std::list<void (*)(int, int)> motion_handlers;
+       extern std::list<void (*)(int, int, int, int)> button_handlers;
+       
+       extern bool button_state[6];
+       extern int screenx, screeny;
+
+       void init();
+
+       void set_display_handler(void (*handler)());
+       void set_idle_handler(void (*handler)());
+       void set_keyboard_handler(void (*handler)(int));
+       void set_motion_handler(void (*handler)(int, int));
+       void set_button_handler(void (*handler)(int, int, int, int));
+
+       void remove_display_handler(void (*handler)());
+       void remove_idle_handler(void (*handler)());
+       void remove_keyboard_handler(void (*handler)(int));
+       void remove_motion_handler(void (*handler)(int, int));
+       void remove_button_handler(void (*handler)(int, int, int, int));
+
+       bool mouse_button_pressed(int bn);
+
+       Vector2 get_mouse_pos_normalized();
+
+       void set_window_title(const char *title);
+       void swap_buffers();
+       
+       int main_loop();
+}
+
+#endif /* _FXWT_HPP_ */
diff --git a/src/3dengfx/src/fxwt/fxwt_glut.cpp b/src/3dengfx/src/fxwt/fxwt_glut.cpp
new file mode 100644 (file)
index 0000000..eded410
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+This file is part of fxwt, the window system toolkit of 3dengfx.
+
+Copyright (C) 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* main fxwt event handling and window system abstraction through GLUT.
+ *
+ * Author: John Tsiombikas 2005
+ */
+
+#include "3dengfx_config.h"
+
+#if GFX_LIBRARY == GLUT
+
+#include "gfx_library.h"
+#include "fxwt.hpp"
+#include "3dengfx/3denginefx.hpp"
+#include "common/err_msg.h"
+
+#if defined(__unix__) || defined(unix)
+#include <unistd.h>
+#ifdef _POSIX_PRIORITY_SCHEDULING
+#include <sched.h>
+#endif // _POSIX_PRIORITY_SCHEDULING
+#endif // __unix__
+
+#if defined(WIN32) || defined(__WIN32__)
+#include <windows.h>
+#endif // WIN32
+
+using std::list;
+using namespace fxwt;
+
+static void glut_disp_handler();
+static void glut_idle_handler();
+static void glut_keyb_handler(unsigned char key, int x, int y);
+static void glut_motion_handler(int x, int y);
+static void glut_button_handler(int bn, int state, int x, int y);
+
+extern int fxwt_glut_win;
+
+Vector2 fxwt::get_mouse_pos_normalized() {
+       // TODO: implement this
+       return Vector2(0, 0);
+}
+
+void fxwt::set_window_title(const char *title) {
+       glutSetWindow(fxwt_glut_win);
+       glutSetWindowTitle(title);
+}
+
+void fxwt::swap_buffers() {
+       glutSetWindow(fxwt_glut_win);
+       glutSwapBuffers();
+#if defined(_POSIX_PRIORITY_SCHEDULING)
+       sched_yield();
+#elif defined(WIN32)
+       Sleep(0);
+#endif
+
+}
+
+int fxwt::main_loop() {
+       set_verbosity(3);
+
+       // register glut event handlers
+       glutSetWindow(fxwt_glut_win);
+       glutDisplayFunc(glut_disp_handler);
+       if(!idle_handlers.empty()) glutIdleFunc(glut_idle_handler);
+       glutKeyboardFunc(glut_keyb_handler);
+       if(!motion_handlers.empty()) {
+               glutMotionFunc(glut_motion_handler);
+               glutPassiveMotionFunc(glut_motion_handler);
+       }
+       glutMouseFunc(glut_button_handler);
+
+       glutMainLoop();
+       return 0;
+}
+
+static void glut_disp_handler() {
+       list<void (*)()>::iterator iter = disp_handlers.begin();
+       while(iter != disp_handlers.end()) {
+               (*iter++)();
+       }
+}
+static void glut_idle_handler() {
+       list<void (*)()>::iterator iter = idle_handlers.begin();
+       while(iter != idle_handlers.end()) {
+               (*iter++)();
+       }
+}
+
+static void glut_keyb_handler(unsigned char key, int x, int y) {
+       list<void (*)(int)>::iterator iter = keyb_handlers.begin();
+       while(iter != keyb_handlers.end()) {
+               (*iter++)(key);
+       }
+}
+
+static void glut_motion_handler(int x, int y) {
+       list<void (*)(int, int)>::iterator iter = motion_handlers.begin();
+       while(iter != motion_handlers.end()) {
+               (*iter++)(x, y);
+       }
+}
+
+static void glut_button_handler(int bn, int state, int x, int y) {
+       bn++;
+       button_state[bn] = state == GLUT_DOWN;
+       list<void (*)(int, int, int, int)>::iterator iter = button_handlers.begin();
+       while(iter != button_handlers.end()) {
+               (*iter++)(bn, state == GLUT_DOWN, x, y);
+       }
+}
+
+#endif // GFX_LIBRARY == GLUT
diff --git a/src/3dengfx/src/fxwt/fxwt_gtk.cpp b/src/3dengfx/src/fxwt/fxwt_gtk.cpp
new file mode 100644 (file)
index 0000000..11606a4
--- /dev/null
@@ -0,0 +1,192 @@
+/*
+This file is part of fxwt, the window system toolkit of 3dengfx.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* main fxwt event handling and system abstraction.
+ *
+ * Author: John Tsiombikas 2004
+ */
+
+#include "3dengfx_config.h"
+
+#if GFX_LIBRARY == GTK
+
+#include "gfx_library.h"
+
+static GdkGLContext *gl_context;
+static GdkGLDrawable *gl_drawable;
+
+Vector2 fxwt::get_mouse_pos_normalized() {
+       //TODO: implement this
+       Vector2(0, 0);
+}
+
+void fxwt::set_window_title(const char *title) {
+       // TODO: implement this
+}
+
+void fxwt::swap_buffers() {
+       gdk_gl_drawable_swap_buffers(gl_drawable);
+}
+
+int fxwt::main_loop() {
+       set_verbosity(3);
+       gtk_main();
+       return 0;
+}
+
+static void gtk_idle_add(GtkWidget *widget);
+static void gtk_idle_remove(GtkWidget *widget);
+static gboolean gtk_key(GtkWidget *widget, GdkEventKey *event, gpointer data);
+static gboolean gtk_idle(GtkWidget *widget);
+static gboolean gtk_visible(GtkWidget *widget, GdkEventVisibility *event, gpointer data);
+static gboolean gtk_map(GtkWidget *widget, GdkEventAny *event, gpointer data);
+static gboolean gtk_unmap(GtkWidget *widget, GdkEventAny *event, gpointer data);
+static gboolean gtk_expose(GtkWidget *widget, GdkEventExpose *event, gpointer data);
+static gboolean gtk_realize(GtkWidget *widget, gpointer data);
+//static gboolean gtk_reshape(GtkWidget *widget, GdkEventConfigure *event, gpointer data);
+
+static bool realized; 
+static unsigned int idle_id;
+
+void set_gtk_callbacks(GtkWidget *widget) {
+       gtk_widget_add_events(widget, GDK_VISIBILITY_NOTIFY_MASK | GDK_KEY_PRESS_MASK);
+       
+       g_signal_connect_after(g_object(widget), "realize", g_callback(GtkRealize), 0);
+       //g_signal_connect(g_object(widget), "configure_event", g_callback(GtkReshape), 0);
+       g_signal_connect(g_object(widget), "expose_event", g_callback(GtkExpose), 0);
+       g_signal_connect(g_object(widget), "map_event", g_callback(GtkMap), 0);
+       g_signal_connect(g_object(widget), "unmap_event", g_callback(GtkUnmap), 0);
+       g_signal_connect(g_object(widget), "visibility_notify_event", g_callback(GtkVisible), 0);
+
+       g_signal_connect(g_object(widget), "key_press_event", g_callback(GtkKey), 0);
+}
+
+static gboolean gtk_key(GtkWidget *widget, GdkEventKey *event, gpointer data) {
+       std::cout << __func__ << std::endl;
+       if(event->type == GDK_KEY_PRESS) {
+               list<void (*)(int)>::iterator iter = keyb_handlers.begin();
+               while(iter != keyb_handlers.end()) {
+                       (*iter++)(event->keyval);
+               }
+       }
+       return TRUE;
+}
+
+static void gtk_idle_add(GtkWidget *widget) {
+       if(!idle_id && !idle_handlers.empty()) {
+               idle_id = g_idle_add_full(GDK_PRIORITY_REDRAW, (GSourceFunc)GtkIdle, widget, 0);
+       }
+}
+
+static void gtk_idle_remove(GtkWidget *widget) {
+       if(idle_id) {
+               g_source_remove(idle_id);
+               idle_id = 0;
+       }
+}
+
+static gboolean gtk_visible(GtkWidget *widget, GdkEventVisibility *event, gpointer data) {
+       if(event->state == GDK_VISIBILITY_FULLY_OBSCURED) {
+               gtk_idle_remove(widget);
+       } else {
+               gtk_idle_add(widget);
+       }
+       return TRUE;
+}
+
+static gboolean gtk_map(GtkWidget *widget, GdkEventAny *event, gpointer data) {
+       gtk_idle_add(widget);
+       return TRUE;
+}
+
+static gboolean gtk_unmap(GtkWidget *widget, GdkEventAny *event, gpointer data) {
+       gtk_idle_remove(widget);
+       return TRUE;
+}
+
+static gboolean gtk_expose(GtkWidget *widget, GdkEventExpose *event, gpointer data) {
+       gdk_gl_drawable_gl_begin(gl_drawable, gl_context);
+       
+       if(!realized) {
+               return TRUE;
+       }
+
+       list<void (*)()>::iterator iter = disp_handlers.begin();
+       while(iter != disp_handlers.end()) {
+               (*iter++)();
+       }
+
+       gdk_gl_drawable_gl_end(gl_drawable);
+       
+       return TRUE;
+}
+
+static gboolean gtk_idle(GtkWidget *widget) {
+       if(!realized) return TRUE;
+       
+       gdk_window_invalidate_rect(widget->window, &widget->allocation, FALSE);
+       gdk_window_process_updates(widget->window, FALSE);
+       
+       return TRUE;
+}
+
+static gboolean gtk_realize(GtkWidget *widget, gpointer data) {
+       gl_context = gtk_widget_get_gl_context(widget);
+       gl_drawable = gtk_widget_get_gl_drawable(widget);
+  
+       if(!gdk_gl_drawable_gl_begin(gl_drawable, gl_context)) {
+               error("%s: this shouldn't happen", __func__);
+               return FALSE;
+       }
+       
+       if(!start_gl()) {
+               exit(-1);
+       }
+       
+       gdk_gl_drawable_gl_end(gl_drawable);
+
+       realized = true;
+       return TRUE;
+}
+
+#if 0
+static gboolean gtk_reshape(GtkWidget *widget, GdkEventConfigure *event, gpointer data) {
+       GLfloat h = (GLfloat) (widget->allocation.height) / (GLfloat) (widget->allocation.width);
+
+       /*** OpenGL BEGIN ***/
+       if(!gdk_gl_drawable_gl_begin(gldrawable, glcontext)) {
+               return FALSE;
+       }
+       
+       glViewport (0, 0, widget->allocation.width, widget->allocation.height);
+       glMatrixMode (GL_PROJECTION);
+       glLoadIdentity ();
+       glFrustum (-1.0, 1.0, -h, h, 5.0, 60.0);
+       glMatrixMode (GL_MODELVIEW);
+       glLoadIdentity ();
+       glTranslatef (0.0, 0.0, -40.0);
+       
+       gdk_gl_drawable_gl_end (gldrawable);
+       /*** OpenGL END ***/
+       return TRUE;
+}
+#endif
+
+#endif // GFX_LIBRARY == GTK
diff --git a/src/3dengfx/src/fxwt/fxwt_sdl.cpp b/src/3dengfx/src/fxwt/fxwt_sdl.cpp
new file mode 100644 (file)
index 0000000..e0cd95e
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+This file is part of fxwt, the window system toolkit of 3dengfx.
+
+Copyright (C) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* main fxwt event handling and window system abstraction through SDL.
+ *
+ * Author: John Tsiombikas 2004
+ */
+
+#include "3dengfx_config.h"
+
+#if GFX_LIBRARY == SDL
+
+#include "gfx_library.h"
+#include "fxwt.hpp"
+#include "3dengfx/3denginefx.hpp"
+#include "common/err_msg.h"
+
+#ifdef __unix__
+#include <unistd.h>
+#ifdef _POSIX_PRIORITY_SCHEDULING
+#include <sched.h>
+#endif // _POSIX_PRIORITY_SCHEDULING
+#endif // __unix__
+
+#ifdef WIN32
+#include <windows.h>
+#endif // WIN32
+
+using std::list;
+using namespace fxwt;
+
+static void handle_event(const SDL_Event &event);
+
+Vector2 fxwt::get_mouse_pos_normalized() {
+       int x, y;
+       SDL_GetMouseState(&x, &y);
+
+       return Vector2((scalar_t)x / (scalar_t)screenx, (scalar_t)y / (scalar_t)screeny);
+}
+
+void fxwt::set_window_title(const char *title) {
+       SDL_WM_SetCaption(title, 0);
+}
+
+void fxwt::swap_buffers() {
+       SDL_GL_SwapBuffers();
+#if defined(_POSIX_PRIORITY_SCHEDULING)
+       sched_yield();
+#elif defined(WIN32)
+       Sleep(0);
+#endif
+}
+
+int fxwt::main_loop() {
+       set_verbosity(3);
+       
+       SDL_EnableKeyRepeat(300, 20);
+
+       while(1) {
+               SDL_Event event;
+
+               if(!idle_handlers.empty()) {
+                       while(SDL_PollEvent(&event)) {
+                               handle_event(event);
+                       }
+                       
+                       list<void (*)()>::iterator iter = idle_handlers.begin();
+                       while(iter != idle_handlers.end()) {
+                               (*iter++)();
+                       }
+               } else {
+                       SDL_WaitEvent(&event);
+                       handle_event(event);
+               }
+       }
+
+       return 0;
+}
+
+static void handle_event(const SDL_Event &event) {
+       switch(event.type) {
+       case SDL_KEYDOWN:
+               {
+                       list<void (*)(int)>::iterator iter = keyb_handlers.begin();
+                       while(iter != keyb_handlers.end()) {
+                               (*iter++)(event.key.keysym.sym);
+                       }
+               }
+               break;
+
+       case SDL_VIDEOEXPOSE:
+               {
+                       list<void (*)()>::iterator iter = disp_handlers.begin();
+                       while(iter != disp_handlers.end()) {
+                               (*iter++)();
+                       }
+               }
+               break;
+
+       case SDL_MOUSEMOTION:
+               {
+                       list<void (*)(int, int)>::iterator iter = motion_handlers.begin();
+                       while(iter != motion_handlers.end()) {
+                               (*iter++)(event.motion.x, event.motion.y);
+                       }
+               }
+               break;
+
+       case SDL_MOUSEBUTTONDOWN:
+       case SDL_MOUSEBUTTONUP:
+               {
+                       button_state[event.button.button] = event.button.state;
+                       list<void (*)(int, int, int, int)>::iterator iter = button_handlers.begin();
+                       while(iter != button_handlers.end()) {
+                               (*iter++)(event.button.button, event.button.state == SDL_PRESSED, event.button.x, event.button.y);
+                       }
+               }
+               break;
+
+       case SDL_QUIT:
+               exit(0);
+
+       default:
+               break;
+       }
+}
+
+
+#endif // GFX_LIBRARY == SDL
diff --git a/src/3dengfx/src/fxwt/fxwt_win32.cpp b/src/3dengfx/src/fxwt/fxwt_win32.cpp
new file mode 100644 (file)
index 0000000..5ac437e
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+This file is part of fxwt, the window system toolkit of 3dengfx.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* main fxwt event handling and system abstraction.
+ *
+ * Author: John Tsiombikas 2004
+ * modified: Mihalis Georgoulopoulos 2006
+ */
+
+#include "3dengfx_config.h"
+
+#if GFX_LIBRARY == NATIVE && NATIVE_LIB == NATIVE_WIN32
+
+#include "gfx_library.h"
+#include "fxwt.hpp"
+#include "3dengfx/3denginefx.hpp"
+#include "common/err_msg.h"
+
+using std::list;
+using namespace fxwt;
+
+long CALLBACK fxwt_win32_handle_event(HWND__ *win, unsigned int msg, unsigned int wparam, long lparam);
+static void button_event(int bn, bool state, int x, int y);
+static int vkey_to_keysym(unsigned int vkey);
+
+extern HWND__ *fxwt_win32_win;
+extern HDC__ *fxwt_win32_dc;
+
+Vector2 fxwt::get_mouse_pos_normalized() {
+       return Vector2(0, 0);
+}
+
+void fxwt::set_window_title(const char *title) {
+       SetWindowText(fxwt_win32_win, title);
+}
+
+void fxwt::swap_buffers() {
+       SwapBuffers(fxwt_win32_dc);
+       Sleep(0);
+}
+
+int fxwt::main_loop() {
+       set_verbosity(3);
+
+       while(1) {
+               if(!idle_handlers.empty()) {
+                       MSG event;
+                       while(PeekMessage(&event, 0, 0, 0, PM_REMOVE)) {
+                               TranslateMessage(&event);
+                               DispatchMessage(&event);
+                       }
+
+                       list<void (*)()>::iterator iter = idle_handlers.begin();
+                       while(iter != idle_handlers.end()) {
+                               (*iter++)();
+                       }
+               } else {
+                       MSG event;
+                       if(!GetMessage(&event, 0, 0, 0)) break;
+                       TranslateMessage(&event);
+                       DispatchMessage(&event);
+               }
+       }
+
+       return 0;
+}
+
+long CALLBACK fxwt_win32_handle_event(HWND__ *win, unsigned int msg, unsigned int wparam, long lparam) {
+       static int window_mapped;
+
+       switch(msg) {
+       case WM_SHOWWINDOW:
+               if(wparam) {
+                       window_mapped = 1;
+               } else {
+            window_mapped = 0;
+               }
+               break;
+
+       case WM_PAINT:
+               if(window_mapped) {
+                       list<void (*)()>::iterator iter = disp_handlers.begin();
+                       while(iter != disp_handlers.end()) {
+                               (*iter++)();
+                       }
+               }
+               break;
+
+       case WM_CLOSE:
+               exit(0);
+
+       case WM_KEYDOWN:
+               {
+                       list<void (*)(int)>::iterator iter = keyb_handlers.begin();
+                       while(iter != keyb_handlers.end()) {
+                               (*iter++)(vkey_to_keysym(wparam));
+                       }
+               }
+               break;
+
+       case WM_CHAR:
+               {
+                       list<void (*)(int)>::iterator iter = keyb_handlers.begin();
+                       while(iter != keyb_handlers.end()) {
+                               (*iter++)(wparam);
+                       }
+               }
+               break;
+
+       case WM_MOUSEMOVE:
+               {
+                       list<void (*)(int, int)>::iterator iter = motion_handlers.begin();
+                       while(iter != motion_handlers.end()) {
+                               (*iter++)(LOWORD(lparam), HIWORD(lparam));
+                       }
+               }
+               break;
+
+       case WM_MOUSEWHEEL:
+               {
+                       int bn = HIWORD(wparam) > 0 ? BN_WHEELUP : BN_WHEELDOWN;
+                       button_event(bn, true, LOWORD(lparam), HIWORD(lparam));
+               }
+               break;
+
+       case WM_LBUTTONDOWN:
+               button_event(BN_LEFT, true, LOWORD(lparam), HIWORD(lparam));
+               break;
+               
+       case WM_MBUTTONDOWN:
+               button_event(BN_MIDDLE, true, LOWORD(lparam), HIWORD(lparam));
+               break;
+               
+       case WM_RBUTTONDOWN:
+               button_event(BN_RIGHT, true, LOWORD(lparam), HIWORD(lparam));
+               break;
+
+       case WM_LBUTTONUP:
+               button_event(BN_LEFT, false, LOWORD(lparam), HIWORD(lparam));
+               break;
+               
+       case WM_MBUTTONUP:
+               button_event(BN_MIDDLE, false, LOWORD(lparam), HIWORD(lparam));
+               break;
+               
+       case WM_RBUTTONUP:
+               button_event(BN_RIGHT, false, LOWORD(lparam), HIWORD(lparam));
+               break;
+
+
+       default:
+               break;
+       //      DefWindowProc(win, msg, wparam, lparam);
+       }
+
+       return DefWindowProc(win, msg, wparam, lparam);
+}
+
+static void button_event(int bn, bool state, int x, int y) {
+       button_state[bn] = state;
+       list<void (*)(int, int, int, int)>::iterator iter = button_handlers.begin();
+       while(iter != button_handlers.end()) {
+               (*iter++)(bn, state, x, y);
+       }
+}
+
+
+static int win32_keysyms[] = 
+{
+//     0               1               2               3               4               5               6               7               8               9
+       0,              0,              0,              0,              0,              0,              0,              0,              8,              9,              // 000
+       0,              0,              12,             13,             0,              0,              304,    306,    0,              19,             // 010
+       301,    0,              0,              0,              0,              0,              0,              27,             0,              0,              // 020
+       0,              0,              0,              280,    281,    279,    278,    276,    273,    275,    // 030
+       274,    0,              0,              0,              0,              0,              0,              0,              0,              0,              // 040
+       0,              0,              0,              0,              0,              0,              0,              0,              0,              0,              // 050
+       0,              0,              0,              0,              0,              0,              0,              0,              0,              0,              // 060
+       0,              0,              0,              0,              0,              0,              0,              0,              0,              0,              // 070
+       0,              0,              0,              0,              0,              0,              0,              0,              0,              0,              // 080
+       0,              311,    312,    0,              0,              0,              256,    257,    258,    259,    // 090
+       260,    261,    262,    263,    264,    265,    268,    270,    0,              269,    // 100
+       0,              267,    282,    283,    284,    285,    286,    287,    288,    289,    // 110
+       290,    291,    292,    293,    294,    295,    296,    0,              127,    0,              // 120
+       0,              0,              0,              0,              0,              0,              0,              0,              0,              0,              // 130
+       0,              0,              0,              0,              300,    302,                                                                    // 140
+};
+
+static int vkey_to_keysym(unsigned int vkey) {
+       if (vkey < 146) return win32_keysyms[vkey];
+       return 0;
+}
+
+#endif // GFX_LIBRARY == NATIVE && NATIVE_LIB == NATIVE_WIN32
diff --git a/src/3dengfx/src/fxwt/fxwt_x.cpp b/src/3dengfx/src/fxwt/fxwt_x.cpp
new file mode 100644 (file)
index 0000000..bb7cfaa
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+This file is part of fxwt, the window system toolkit of 3dengfx.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* main fxwt event handling and system abstraction.
+ *
+ * Author: John Tsiombikas 2004
+ */
+
+#include "3dengfx_config.h"
+
+#if GFX_LIBRARY == NATIVE && NATIVE_LIB == NATIVE_X11
+
+#include "gfx_library.h"
+#include "fxwt.hpp"
+#include "3dengfx/3denginefx.hpp"
+#include "common/err_msg.h"
+
+#ifdef __unix__
+#include <unistd.h>
+#ifdef _POSIX_PRIORITY_SCHEDULING
+#include <sched.h>
+#endif // _POSIX_PRIORITY_SCHEDULING
+#endif // __unix__
+
+using std::list;
+using namespace fxwt;
+
+static void handle_event(const XEvent &event);
+
+extern Display *fxwt_x_dpy;
+extern ::Window fxwt_x_win;
+
+Vector2 fxwt::get_mouse_pos_normalized() {
+       return Vector2(0, 0);
+}
+
+void fxwt::set_window_title(const char *title) {
+       XTextProperty tp_wname;
+       XStringListToTextProperty((char**)&title, 1, &tp_wname);
+       XSetWMName(fxwt_x_dpy, fxwt_x_win, &tp_wname);
+       XFree(tp_wname.value);
+}
+
+void fxwt::swap_buffers() {
+       glXSwapBuffers(fxwt_x_dpy, fxwt_x_win);
+#ifdef _POSIX_PRIORITY_SCHEDULING
+       sched_yield();
+#endif
+}
+
+int fxwt::main_loop() {
+       set_verbosity(3);
+
+       while(1) {
+               if(!idle_handlers.empty()) {
+                       while(XPending(fxwt_x_dpy)) {
+                               XEvent event;
+                               XNextEvent(fxwt_x_dpy, &event);
+                               handle_event(event);
+                       }
+                       
+                       list<void (*)()>::iterator iter = idle_handlers.begin();
+                       while(iter != idle_handlers.end()) {
+                               (*iter++)();
+                       }
+               } else {
+                       XEvent event;
+                       XNextEvent(fxwt_x_dpy, &event);
+                       handle_event(event);
+               }
+       }
+
+       return 0;
+}
+
+static void handle_event(const XEvent &event) {
+       static int window_mapped;
+
+       switch(event.type) {
+       case MapNotify:
+               window_mapped = 1;
+               break;
+
+       case UnmapNotify:
+               window_mapped = 0;
+               break;
+
+       case Expose:
+               if(window_mapped && event.xexpose.count == 0) {
+                       list<void (*)()>::iterator iter = disp_handlers.begin();
+                       while(iter != disp_handlers.end()) {
+                               (*iter++)();
+                       }
+               }
+               break;
+
+       case ClientMessage:
+               {
+                       char *atom_name = XGetAtomName(fxwt_x_dpy, event.xclient.message_type);
+                       if(!strcmp(atom_name, "WM_PROTOCOLS")) {
+                               XFree(atom_name);
+                               exit(0);
+                       }
+                       XFree(atom_name);
+               }
+               break;
+
+       case KeyPress:
+               {
+                       KeySym keysym = XLookupKeysym((XKeyEvent*)&event.xkey, 0);
+                       //key_state[keysym] = 1;
+
+                       list<void (*)(int)>::iterator iter = keyb_handlers.begin();
+                       while(iter != keyb_handlers.end()) {
+                               (*iter++)(keysym & 0xff);
+                       }
+               }
+               break;
+
+       case MotionNotify:
+               {
+                       list<void (*)(int, int)>::iterator iter = motion_handlers.begin();
+                       while(iter != motion_handlers.end()) {
+                               (*iter++)(event.xmotion.x, event.xmotion.y);
+                       }
+               }
+               break;
+
+
+       case ButtonPress:
+               {
+                       bool state;
+                       if(1) {
+                               state = true;
+                       } else {
+       case ButtonRelease:
+                               state = false;
+                       }
+                       button_state[event.xbutton.button] = state;
+                       
+                       list<void (*)(int, int, int, int)>::iterator iter = button_handlers.begin();
+                       while(iter != button_handlers.end()) {
+                               (*iter++)(event.xbutton.button, state, event.xbutton.x, event.xbutton.y);
+                       }
+               }
+               break;
+
+       default:
+               break;
+       }
+}
+
+#endif // GFX_LIBRARY == NATIVE && NATIVE_LIB == NATIVE_X11
diff --git a/src/3dengfx/src/fxwt/gfx_library.h b/src/3dengfx/src/fxwt/gfx_library.h
new file mode 100644 (file)
index 0000000..c06385d
--- /dev/null
@@ -0,0 +1,60 @@
+#ifndef _GFX_LIBRARY_H_
+#define _GFX_LIBRARY_H_
+
+#include "3dengfx_config.h"
+
+#ifndef GFX_LIBRARY
+#error "no gfx library specified, please reconfigure"
+#endif /* GFX_LIBRARY */
+
+#if GFX_LIBRARY == SDL
+#include "SDL.h"
+#define glGetProcAddress(x) SDL_GL_GetProcAddress(x)
+#endif /* SDL */
+
+#if GFX_LIBRARY == GLUT
+#include <GL/glut.h>
+#endif /* GLUT */
+
+#if GFX_LIBRARY == GTK
+#include <gtk/gtk.h>
+#include <gtk/gtkgl.h>
+#endif /* GTK */
+
+#if GFX_LIBRARY == GTKMM
+#include <gtkmm.h>
+#include <gtkglmm.h>
+#endif /* GTKMM */
+
+#if GFX_LIBRARY == NATIVE
+
+#if NATIVE_LIB == NATIVE_X11
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <GL/glx.h>
+#endif /* X11 */
+
+#if NATIVE_LIB == NATIVE_WIN32
+#include <windows.h>
+#endif /* WIN32 */
+
+#endif /* GFX_LIBRARY == NATIVE */
+
+#if GFX_LIBRARY != SDL
+
+#if defined(__unix__)
+#include <GL/glx.h>
+
+#define glGetProcAddress(x)            glXGetProcAddress((unsigned char*)x)
+
+#ifndef GLX_ARB_get_proc_address
+void *glXGetProcAddress(const char *name);
+#endif /* GLX_ARB_get_proc_address */
+
+#elif defined(WIN32) || defined(__WIN32__)
+#define glGetProcAddress(x)            wglGetProcAddress(x)
+#endif /* __unix__ */
+
+#endif /* GFX_LIBRARY != SDL */
+
+#endif /* _GFX_LIBRARY_H_ */
diff --git a/src/3dengfx/src/fxwt/init.cpp b/src/3dengfx/src/fxwt/init.cpp
new file mode 100644 (file)
index 0000000..66eccfc
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+Copyright 2004 John Tsiombikas <nuclear@siggraph.org>
+
+This file is part of the 3dengfx, realtime visualization system.
+
+3dengfx is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+3dengfx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with 3dengfx; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* master init source, includes all the specific ones
+ *
+ * Author: John Tsiombikas 2004
+ */
+
+#include <stdlib.h>
+#include "init.hpp"
+#include "gfx_library.h"
+#include "3dengfx/3denginefx.hpp"
+#include "common/err_msg.h"
diff --git a/src/3dengfx/src/fxwt/init.hpp b/src/3dengfx/src/fxwt/init.hpp
new file mode 100644 (file)
index 0000000..9168b29
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef _FXWT_INIT_HPP_
+#define _FXWT_INIT_HPP_
+
+#include "gfx_library.h"
+#include "3dengfx/3denginefx_types.hpp"
+
+#if GFX_LIBRARY == GTK
+extern GtkWidget *gl_drawing_area;
+#endif // GTK
+
+namespace fxwt {
+       bool init_graphics(GraphicsInitParameters *gip);
+       void destroy_graphics();
+
+       void swap_buffers();
+}
+
+#endif // _FXWT_INIT_HPP_
diff --git a/src/3dengfx/src/fxwt/init_glut.cpp b/src/3dengfx/src/fxwt/init_glut.cpp
new file mode 100644 (file)
index 0000000..3481f2f
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+This file is part of the 3dengfx, realtime visualization system.
+
+Copyright (C) 2005 John Tsiombikas <nuclear@siggraph.org>
+
+3dengfx is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+3dengfx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with 3dengfx; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* OpenGL through GLUT
+ *
+ * Author: John Tsiombikas 2005
+ * Modified: John Tsiombikas 2006
+ */
+
+#include "3dengfx_config.h"
+
+#if GFX_LIBRARY == GLUT
+
+#include <stdlib.h>
+#include "init.hpp"
+#include "gfx_library.h"
+#include "3dengfx/3denginefx.hpp"
+#include "common/err_msg.h"
+
+int fxwt_glut_win;
+
+bool fxwt::init_graphics(GraphicsInitParameters *gparams) {
+       info("Initializing GLUT");
+
+       // fabricate the command line args
+       char *argv[] = {"3dengfx", 0};
+       int argc = 1;
+       
+       glutInit(&argc, argv);
+       glutInitWindowSize(gparams->x, gparams->y);
+
+       info("Trying to set video mode %dx%dx%d, d:%d s:%d %s", gparams->x, gparams->y, gparams->bpp, gparams->depth_bits, gparams->stencil_bits, gparams->fullscreen ? "fullscreen" : "windowed");
+
+       // determine color bits
+       int color_bits;
+       if(gparams->dont_care_flags & DONT_CARE_BPP) {
+               color_bits = 1;
+       } else {
+               switch(gparams->bpp) {
+               case 32:
+               case 24:
+                       color_bits = 8;
+                       break;
+
+               case 16:
+               case 15:
+                       color_bits = 5;
+                       break;
+
+               case 12:
+                       color_bits = 4;
+                       break;
+
+               default:
+                       error("%s: Tried to set unsupported pixel format: %d bpp", __func__, gparams->bpp);
+               }
+       }
+       
+       // construct the display mode
+       unsigned int disp_mode = GLUT_RGBA | GLUT_DOUBLE;
+       if(gparams->depth_bits) disp_mode |= GLUT_DEPTH;
+       if(gparams->stencil_bits) disp_mode |= GLUT_STENCIL;    
+       glutInitDisplayMode(disp_mode);
+
+       fxwt_glut_win = glutCreateWindow("3dengfx/glut");
+
+       int arbits, agbits, abbits, azbits, astencilbits;
+       arbits = glutGet(GLUT_WINDOW_RED_SIZE);
+       agbits = glutGet(GLUT_WINDOW_GREEN_SIZE);
+       abbits = glutGet(GLUT_WINDOW_BLUE_SIZE);
+       azbits = glutGet(GLUT_WINDOW_DEPTH_SIZE);
+       astencilbits = glutGet(GLUT_WINDOW_STENCIL_SIZE);
+       
+       info("Initialized video mode:");
+       info("    bpp: %d (%d%d%d)", arbits + agbits + abbits, arbits, agbits, abbits);
+       info("zbuffer: %d", azbits);
+       info("stencil: %d", astencilbits);
+
+       /* if the dont_care_flags does not contain DONT_CARE_BPP and our color bits
+        * does not match, we should return failure, however we test against
+        * the difference allowing a +/-1 difference in order to allow for 16bpp
+        * formats of either 565 or 555 and consider them equal.
+        */
+       if(!(gparams->dont_care_flags & DONT_CARE_BPP) && abs(arbits - color_bits) > 1 && abs(agbits - color_bits) > 1 && abs(abbits - color_bits) > 1) {
+               error("%s: Could not set requested exact bpp mode", __func__);
+               glutDestroyWindow(fxwt_glut_win);
+               return false;
+       }
+
+       // now if we don't have DONT_CARE_DEPTH in the dont_care_flags check for 
+       // exact depth buffer format, however consider 24 and 32 bit the same
+       if(!(gparams->dont_care_flags & DONT_CARE_DEPTH) && azbits != gparams->depth_bits) {
+               if(!(gparams->depth_bits == 32 && azbits == 24 || gparams->depth_bits == 24 && azbits == 32)) {
+                       error("%s: Could not set requested exact zbuffer depth", __func__);
+                       glutDestroyWindow(fxwt_glut_win);
+                       return false;
+               }
+       }
+
+       // if we don't have DONT_CARE_STENCIL make sure we have the stencil format
+       // that was asked.
+       if(!(gparams->dont_care_flags & DONT_CARE_STENCIL) && astencilbits != gparams->stencil_bits) {
+               error("%s: Could not set exact stencil format", __func__);
+               glutDestroyWindow(fxwt_glut_win);
+               return false;
+       }
+
+       return true;
+}
+
+void fxwt::destroy_graphics() {
+       info("Shutting down GLUT");
+       glutDestroyWindow(fxwt_glut_win);
+}
+
+#ifdef __unix__
+#include <GL/glx.h>
+
+#ifndef GLX_ARB_get_proc_address
+#include <dlfcn.h>
+
+void *glXGetProcAddress(const char *name) {
+       char *err_str;
+       void *sym;
+       void *so = dlopen("libGL.so", RTLD_LAZY);
+       if(!so) {
+               perror("dlopen failed");
+               return 0;
+       }
+       
+       dlerror();
+       sym = dlsym(so, name);
+       if((err_str = dlerror())) {
+               fprintf(stderr, "dlsym failed: %s\n", err_str);
+               sym = 0;
+       }
+       
+       dlclose(so);
+       return sym;
+}
+#endif // GLX_ARB_get_proc_address
+
+#endif // __unix__
+
+#endif // GFX_LIBRARY == GLUT
diff --git a/src/3dengfx/src/fxwt/init_gtk.cpp b/src/3dengfx/src/fxwt/init_gtk.cpp
new file mode 100644 (file)
index 0000000..279bdef
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+Copyright 2004 John Tsiombikas <nuclear@siggraph.org>
+
+This file is part of the 3dengfx, realtime visualization system.
+
+3dengfx is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+3dengfx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with 3dengfx; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* OpenGL through GTK
+ *
+ * Author: John Tsiombikas 2004
+ */
+
+#include "3dengfx_config.h"
+
+#if GFX_LIBRARY == GTK
+
+#include <stdlib.h>
+#include "init.hpp"
+#include "gfx_library.h"
+#include "3dengfx/3denginefx.hpp"
+#include "common/err_msg.h"
+
+GtkWidget *gl_window;
+GtkWidget *gl_drawing_area;
+GdkGLConfig *glconfig;
+
+bool fxwt::init_graphics(GraphicsInitParameters *gparams) {
+       info("Initializing GTK and GTK-GLext");
+
+       char *argv[] = {"foo", (char*)0};
+       int argc = 1;
+       gtk_gl_init(&argc, (char***)&argv);
+
+       info("Trying to set video mode %dx%dx%d, d:%d s:%d %s",gparams->x, gparams->y, gparams->bpp, gparams->depth_bits, gparams->stencil_bits, gparams->fullscreen ? "fullscreen" : "windowed");
+
+       int rbits, gbits, bbits;
+       switch(gparams->bpp) {
+       case 32:
+               rbits = gbits = bbits = 8;
+               break;
+               
+       case 16:
+               rbits = bbits = 6;
+               gbits = 5;
+               break;
+               
+       default:
+               error("%s: Tried to set unsupported pixel format: %d bpp", __func__, gparams->bpp);
+               return false;
+       }
+
+       int gdkgl_attr[] = {
+               GDK_GL_USE_GL, GDK_GL_DOUBLEBUFFER, GDK_GL_RGBA,
+               GDK_GL_RED_SIZE, rbits,
+               GDK_GL_GREEN_SIZE, gbits,
+               GDK_GL_BLUE_SIZE, bbits,
+               GDK_GL_DEPTH_SIZE, gparams->depth_bits,
+               GDK_GL_STENCIL_SIZE, gparams->stencil_bits,
+               GDK_GL_ATTRIB_LIST_NONE
+       };
+
+       //GdkGLConfig *glconfig;
+       if(!(glconfig = gdk_gl_config_new(gdkgl_attr))) {
+               if(gparams->depth_bits == 32) gdkgl_attr[10] = 24;
+
+               if(!(glconfig = gdk_gl_config_new(gdkgl_attr))) {
+                       error("%s: Could not set requested video mode", __func__);
+               }
+       }
+
+       // now check the actual video mode we got
+       int arbits, agbits, abbits, azbits, astencilbits;
+       gdk_gl_config_get_attrib(glconfig, GDK_GL_RED_SIZE, &arbits);
+       gdk_gl_config_get_attrib(glconfig, GDK_GL_GREEN_SIZE, &agbits);
+       gdk_gl_config_get_attrib(glconfig, GDK_GL_BLUE_SIZE, &abbits);
+       gdk_gl_config_get_attrib(glconfig, GDK_GL_DEPTH_SIZE, &azbits);
+       gdk_gl_config_get_attrib(glconfig, GDK_GL_STENCIL_SIZE, &astencilbits);
+
+       info("Initialized video mode:");
+       info("    bpp: %d (%d%d%d)", arbits + agbits + abbits, arbits, agbits, abbits);
+       info("zbuffer: %d", azbits);
+       info("stencil: %d", astencilbits);
+
+       /* if the dont_care_flags does not contain DONT_CARE_BPP and our color bits
+        * does not match, we should return failure, however we test against
+        * the difference allowing a +/-1 difference in order to allow for 16bpp
+        * formats of either 565 or 555 and consider them equal.
+        */
+       if(!(gparams->dont_care_flags & DONT_CARE_BPP) && abs(arbits - rbits) > 1 && abs(agbits - gbits) > 1 && abs(abbits - bbits) > 1) {
+               error("%s: Could not set requested exact bpp mode", __func__);
+               return false;
+       }
+
+       // now if we don't have DONT_CARE_DEPTH in the dont_care_flags check for 
+       // exact depth buffer format, however consider 24 and 32 bit the same
+       if(!(gparams->dont_care_flags & DONT_CARE_DEPTH) && azbits != gparams->depth_bits) {
+               if(!(gparams->depth_bits == 32 && azbits == 24 || gparams->depth_bits == 24 && azbits == 32)) {
+                       error("%s: Could not set requested exact zbuffer depth", __func__);
+                       return false;
+               }
+       }
+
+       // if we don't have DONT_CARE_STENCIL make sure we have the stencil format
+       // that was asked.
+       if(!(gparams->dont_care_flags & DONT_CARE_STENCIL) && astencilbits != gparams->stencil_bits) {
+               error("%s: Could not set exact stencil format", __func__);
+               return false;
+       }
+
+       //gl_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+       //gtk_window_set_title(gtk_window(gl_window), "3dengfx visualization window");
+       //gtk_container_set_reallocate_redraws(gtk_container(gl_window), TRUE);
+       //g_signal_connect(g_object(gl_window), "delete_event", g_callback(gtk_main_quit), NULL);
+               
+       gl_drawing_area = gtk_drawing_area_new();
+       gtk_widget_set_size_request(gl_drawing_area, gparams->x, gparams->y);
+       
+       if(!gtk_widget_set_gl_capability(gl_drawing_area, glconfig, 0, TRUE, GDK_GL_RGBA_TYPE)) {
+               error("%s: gtk_widget_set_gl_capability() failed", __func__);
+               return false;
+       }
+
+       extern void set_gtk_callbacks(GtkWidget*);
+       set_gtk_callbacks(gl_drawing_area);
+
+       //gtk_container_add(gtk_container(gl_window), gl_drawing_area);
+       //gtk_widget_show(gl_drawing_area);
+       //gtk_widget_show(gl_window);
+
+       return true;
+}
+
+void fxwt::destroy_graphics() {
+       info("Shutting down GTK+");
+}
+
+#endif // GTK
diff --git a/src/3dengfx/src/fxwt/init_sdl.cpp b/src/3dengfx/src/fxwt/init_sdl.cpp
new file mode 100644 (file)
index 0000000..5f53d86
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+This file is part of the 3dengfx, realtime visualization system.
+
+Copyright (C) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+3dengfx is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+3dengfx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with 3dengfx; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* OpenGL through SDL
+ *
+ * Author: John Tsiombikas 2004
+ */
+
+#include "3dengfx_config.h"
+
+#if GFX_LIBRARY == SDL
+
+#include <stdlib.h>
+#include "init.hpp"
+#include "gfx_library.h"
+#include "3dengfx/3denginefx.hpp"
+#include "common/err_msg.h"
+
+bool fxwt::init_graphics(GraphicsInitParameters *gparams) {
+       info("Initializing SDL");
+
+       if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_AUDIO | SDL_INIT_NOPARACHUTE) == -1) {
+               error("%s: Could not initialize SDL library.", __func__);
+               return false;
+       }
+
+       if(!gparams->fullscreen) {
+               const SDL_VideoInfo *vid_inf = SDL_GetVideoInfo();
+               gparams->bpp = vid_inf->vfmt->BitsPerPixel;
+       }
+
+       info("Trying to set video mode %dx%dx%d, d:%d s:%d %s", gparams->x, gparams->y, gparams->bpp, gparams->depth_bits, gparams->stencil_bits, gparams->fullscreen ? "fullscreen" : "windowed");
+       
+       int rbits, gbits, bbits;
+       switch(gparams->bpp) {
+       case 32:
+               rbits = gbits = bbits = 8;
+               break;
+               
+       case 16:
+               rbits = bbits = 5;
+               gbits = 6;
+               break;
+               
+       default:
+               error("%s: Tried to set unsupported pixel format: %d bpp", __func__, gparams->bpp);
+               return false;
+       }
+
+       SDL_GL_SetAttribute(SDL_GL_RED_SIZE, rbits);
+       SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, gbits);
+       SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, bbits);
+       SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, gparams->depth_bits);
+       SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, gparams->stencil_bits);
+       SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+
+       unsigned long flags = SDL_OPENGL;
+       if(gparams->fullscreen) flags |= SDL_FULLSCREEN;
+       if(!SDL_SetVideoMode(gparams->x, gparams->y, gparams->bpp, flags)) {
+               if(gparams->depth_bits == 32) gparams->depth_bits = 24;
+               SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, gparams->depth_bits);
+               
+               if(!SDL_SetVideoMode(gparams->x, gparams->y, gparams->bpp, flags)) {
+                       error("%s: Could not set requested video mode", __func__);
+               }
+       }
+
+       // now check the actual video mode we got
+       int arbits, agbits, abbits, azbits, astencilbits;
+       SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &arbits);
+       SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &agbits);
+       SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &abbits);
+       SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &azbits);
+       SDL_GL_GetAttribute(SDL_GL_STENCIL_SIZE, &astencilbits);
+
+       info("Initialized video mode:");
+       info("    bpp: %d (%d%d%d)", arbits + agbits + abbits, arbits, agbits, abbits);
+       info("zbuffer: %d", azbits);
+       info("stencil: %d", astencilbits);
+
+       /* if the dont_care_flags does not contain DONT_CARE_BPP and our color bits
+        * does not match, we should return failure, however we test against
+        * the difference allowing a +/-1 difference in order to allow for 16bpp
+        * formats of either 565 or 555 and consider them equal.
+        */
+       if(!(gparams->dont_care_flags & DONT_CARE_BPP) && abs(arbits - rbits) > 1 && abs(agbits - gbits) > 1 && abs(abbits - bbits) > 1) {
+               error("%s: Could not set requested exact bpp mode", __func__);
+               return false;
+       }
+       
+       // now if we don't have DONT_CARE_DEPTH in the dont_care_flags check for 
+       // exact depth buffer format, however consider 24 and 32 bit the same
+       if(!(gparams->dont_care_flags & DONT_CARE_DEPTH) && azbits != gparams->depth_bits) {
+               if(!(gparams->depth_bits == 32 && azbits == 24 || gparams->depth_bits == 24 && azbits == 32)) {
+                       error("%s: Could not set requested exact zbuffer depth", __func__);
+                       return false;
+               }
+       }
+
+       // if we don't have DONT_CARE_STENCIL make sure we have the stencil format
+       // that was asked.
+       if(!(gparams->dont_care_flags & DONT_CARE_STENCIL) && astencilbits != gparams->stencil_bits) {
+               error("%s: Could not set exact stencil format", __func__);
+               return false;
+       }
+
+       return true;
+}
+
+
+void fxwt::destroy_graphics() {
+       info("Shutting down SDL...");
+       SDL_Quit();
+}
+#endif // SDL
diff --git a/src/3dengfx/src/fxwt/init_win32.cpp b/src/3dengfx/src/fxwt/init_win32.cpp
new file mode 100644 (file)
index 0000000..200acc7
--- /dev/null
@@ -0,0 +1,268 @@
+/*
+This file is part of the 3dengfx, realtime visualization system.
+
+Copyright (C) 2005 John Tsiombikas <nuclear@siggraph.org>
+
+3dengfx is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+3dengfx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with 3dengfx; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* OpenGL through Win32
+ *
+ * Author: John Tsiombikas 2005
+ * modified: Mihalis Georgoulopoulos 2006
+ */
+
+#include "3dengfx_config.h"
+
+#if GFX_LIBRARY == NATIVE && NATIVE_LIB == NATIVE_WIN32
+
+#include <stdlib.h>
+#include "init.hpp"
+#include "gfx_library.h"
+#include "3dengfx/3denginefx.hpp"
+#include "common/err_msg.h"
+
+long CALLBACK fxwt_win32_handle_event(HWND__ *win, unsigned int msg, unsigned int wparam, long lparam);
+
+HWND__ *fxwt_win32_win;
+HDC__ *fxwt_win32_dc;
+static HGLRC__ *wgl_ctx;
+
+static bool win32_video_mode_switch(int width, int height, int bpp, bool dontcare_bpp);
+static void win32_reset_video_mode();
+
+bool fxwt::init_graphics(GraphicsInitParameters *gparams) {
+       HWND__ *win;
+       HDC__ *dc;
+
+       info("Initializing WGL");
+       HINSTANCE pid = GetModuleHandle(0);
+
+       WNDCLASSEX wc;
+       memset(&wc, 0, sizeof wc);
+       wc.cbSize = sizeof wc;
+       wc.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);
+       wc.hCursor = LoadCursor(0, IDC_ARROW);
+       wc.hIcon = wc.hIconSm = LoadIcon(0, IDI_APPLICATION);
+       wc.hInstance = pid;
+       wc.lpfnWndProc = fxwt_win32_handle_event;
+       wc.lpszClassName = "win32_sucks_big_time";
+       wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
+       RegisterClassEx(&wc);
+
+       //unsigned long style = WS_OVERLAPPEDWINDOW /*| WS_VISIBLE*/ | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
+       
+       unsigned long desktop_w = GetSystemMetrics(SM_CXSCREEN);
+       unsigned long desktop_h = GetSystemMetrics(SM_CYSCREEN);
+       
+       unsigned long style, width, height;
+       width = gparams->x;
+       height = gparams->y;
+       if (gparams->fullscreen)
+       {       
+               style = WS_POPUP;
+               if (!win32_video_mode_switch(gparams->x, gparams->y, 32, (gparams->dont_care_flags & DONT_CARE_BPP)))
+                       return false;
+       }
+       else
+       {
+               style = WS_OVERLAPPED | WS_SYSMENU;
+       }
+       
+       
+       win = CreateWindow("win32_sucks_big_time", "3dengfx/win32", 
+                       style, 
+                       0, 0, 
+                       width, height, 
+                       0, 0, pid, 0);
+       dc = GetDC(win);
+
+       // decide window placement
+       // if the window is smaller than the desktop, center 
+       // the window in the desktop
+       unsigned long placement_x = 0;
+       unsigned long placement_y = 0;
+       
+       if (gparams->x < desktop_w)
+               placement_x = (desktop_w - gparams->x) / 2;
+       if (gparams->y < desktop_h)
+               placement_y = (desktop_h - gparams->y) / 2;
+
+       // adjust window size to make the client area big enough
+       // to fit the framebuffer
+       RECT client_rect;
+       GetClientRect(win, &client_rect);
+
+       unsigned long new_width = gparams->x + (gparams->x - client_rect.right);
+       unsigned long new_height = gparams->y + (gparams->y - client_rect.bottom);
+       
+       if (!gparams->fullscreen)
+       {
+               MoveWindow(win, placement_x, placement_y,
+                                       new_width, new_height, false);
+       }
+
+       // show the window
+       ShowWindow(win, SW_SHOW);
+       UpdateWindow(win);
+       SetFocus(win);
+       
+       // determine color bits
+       int color_bits;
+       if(gparams->dont_care_flags & DONT_CARE_BPP) {
+               color_bits = 1;
+       } else {
+               switch(gparams->bpp) {
+               case 32:
+               case 24:
+                       color_bits = 8;
+                       break;
+
+               case 16:
+               case 15:
+                       color_bits = 5;
+                       break;
+
+               case 12:
+                       color_bits = 4;
+                       break;
+
+               default:
+                       error("%s: Tried to set unsupported pixel format: %d bpp", __func__, gparams->bpp);
+               }
+       }
+
+       // determine stencil bits
+       int stencil_bits = gparams->stencil_bits;
+       if(gparams->dont_care_flags & DONT_CARE_STENCIL) {
+               stencil_bits = 1;
+       }
+
+       // determine zbuffer bits
+       int zbits = gparams->depth_bits == 32 ? 24 : gparams->depth_bits;
+
+       PIXELFORMATDESCRIPTOR pfd;
+       memset(&pfd, 0, sizeof pfd);
+       pfd.nSize = sizeof pfd;
+       pfd.nVersion = 1;
+       pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW;
+       pfd.iPixelType = PFD_TYPE_RGBA;
+       pfd.cColorBits = gparams->bpp;
+       pfd.cDepthBits = zbits;
+       pfd.cStencilBits = stencil_bits;
+       pfd.iLayerType = PFD_MAIN_PLANE;
+
+       info("Trying to set video mode %dx%dx%d, d:%d s:%d %s", gparams->x, gparams->y, gparams->bpp, gparams->depth_bits, gparams->stencil_bits, gparams->fullscreen ? "fullscreen" : "windowed");
+
+       int pix_format = ChoosePixelFormat(dc, &pfd);
+       if(!pix_format) {
+               error("ChoosePixelFormat() failed: %d", GetLastError());
+               ReleaseDC(win, dc);
+               DestroyWindow(win);
+               return false;
+       }
+
+       //TODO: examine if the pixelformat is correct
+
+       if(!SetPixelFormat(dc, pix_format, &pfd)) {
+               error("SetPixelFormat() failed");
+               ReleaseDC(win, dc);
+               DestroyWindow(win);
+               return false;
+       }
+
+       if(!(wgl_ctx = wglCreateContext(dc))) {
+               error("wglCreateContext() failed");
+               ReleaseDC(win, dc);
+               DestroyWindow(win);
+               return false;
+       }
+
+       if(wglMakeCurrent(dc, wgl_ctx) == FALSE) {
+        error("wglMakeCurrent() failed");
+               wglDeleteContext(wgl_ctx);
+               ReleaseDC(win, dc);
+               DestroyWindow(win);
+               return false;
+       }
+
+       fxwt_win32_dc = dc;
+       fxwt_win32_win = win;
+
+       if (gparams->fullscreen)
+               ShowCursor(0);
+
+       return true;
+}
+
+void fxwt::destroy_graphics() {
+       info("Shutting down WGL");
+       wglMakeCurrent(0, 0);
+       wglDeleteContext(wgl_ctx);
+       ReleaseDC(fxwt_win32_win, fxwt_win32_dc);
+       DestroyWindow(fxwt_win32_win);
+
+       info("Resetting video mode");
+       win32_reset_video_mode();
+
+       ShowCursor(1);
+}
+
+static bool win32_video_mode_switch(int width, int height, int bpp, bool dontcare_bpp)
+{
+       // enumerate display modes
+       std::vector<DEVMODE> modes;
+       DEVMODE curr_mode;
+       curr_mode.dmSize = sizeof(DEVMODE);
+               
+       for (int i=0; ; i++)
+       {
+               if (! EnumDisplaySettings(0, i, &curr_mode))
+                       break;
+               modes.push_back(curr_mode);
+       }
+       
+       int best_mode = -1;
+       unsigned int best_bpp = 1;
+       if (!dontcare_bpp) best_bpp = bpp;
+       
+       for (int i=0; i<modes.size(); i++)
+       {
+               if (modes[i].dmPelsWidth == width &&
+                       modes[i].dmPelsHeight == height)
+               {
+                       if (modes[i].dmBitsPerPel >= best_bpp)
+                       {
+                               best_bpp = modes[i].dmBitsPerPel;
+                               best_mode = i;
+                       }
+               }
+       }
+
+       if (best_mode == -1) return false;
+       
+       if (ChangeDisplaySettings(&modes[best_mode], CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL)
+               return true;
+
+       return false;
+}
+
+// resets the video mode to the default mode in the registry
+static void win32_reset_video_mode()
+{
+       ChangeDisplaySettings(0, 0);
+}
+
+#endif // GFX_LIBRARY == NATIVE && NATIVE_LIB == NATIVE_WIN32
diff --git a/src/3dengfx/src/fxwt/init_x.cpp b/src/3dengfx/src/fxwt/init_x.cpp
new file mode 100644 (file)
index 0000000..74b28d5
--- /dev/null
@@ -0,0 +1,312 @@
+/*
+This file is part of 3dengfx, realtime visualization system.
+Copyright (C) 2004, 2005, 2006 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* OpenGL through GLX (X Window System)
+ *
+ * Author: John Tsiombikas 2005
+ */
+
+#include "3dengfx_config.h"
+
+#if GFX_LIBRARY == NATIVE && NATIVE_LIB == NATIVE_X11
+
+#include <stdlib.h>
+#include "init.hpp"
+#include "gfx_library.h"
+#include "3dengfx/3denginefx.hpp"
+#include "common/err_msg.h"
+
+#ifdef USE_XF86VIDMODE
+#include <X11/extensions/xf86vmode.h>
+
+static XF86VidModeModeInfo orig_mode;
+#endif // USE_XF86VIDMODE
+
+Display *fxwt_x_dpy;
+Window fxwt_x_win;
+static GLXContext glx_ctx;
+static bool fullscreen = false;
+
+bool fxwt::init_graphics(GraphicsInitParameters *gparams) {
+       Display *dpy;
+       Window win;
+       info("Initializing GLX");
+
+       if(!(dpy = XOpenDisplay(0))) {
+               error("Could not connect to the X server");
+               return false;
+       }
+
+       int screen = DefaultScreen(dpy);
+       Window root_win = RootWindow(dpy, screen);
+
+       info("Trying to set video mode %dx%dx%d, d:%d s:%d %s", gparams->x, gparams->y, gparams->bpp, gparams->depth_bits, gparams->stencil_bits, gparams->fullscreen ? "fullscreen" : "windowed");
+       
+       // determine color bits
+       int color_bits = 1;
+       if(!(gparams->dont_care_flags & DONT_CARE_BPP)) {
+               switch(gparams->bpp) {
+               case 32:
+               case 24:
+                       color_bits = 8;
+                       break;
+
+               case 16:
+               case 15:
+                       color_bits = 5;
+                       break;
+
+               case 12:
+                       color_bits = 4;
+                       break;
+
+               default:
+                       error("%s: Tried to set unsupported pixel format: %d bpp", __func__, gparams->bpp);
+               }
+       }
+
+       // determine stencil bits
+       int stencil_bits = gparams->stencil_bits;
+       if(gparams->dont_care_flags & DONT_CARE_STENCIL) {
+               stencil_bits = 1;
+       }
+
+       // determine zbuffer bits
+       int zbits = gparams->depth_bits == 32 ? 24 : gparams->depth_bits;
+       if(gparams->dont_care_flags & DONT_CARE_BPP) {
+               zbits = 1;
+       }
+       
+       int glx_attrib[] = {
+               GLX_RGBA, GLX_DOUBLEBUFFER,
+               GLX_RED_SIZE, color_bits,
+               GLX_GREEN_SIZE, color_bits,
+               GLX_BLUE_SIZE, color_bits,
+               GLX_DEPTH_SIZE, zbits,
+               GLX_STENCIL_SIZE, stencil_bits,
+               None
+       };
+
+       XVisualInfo *vis_info;
+       if(!(vis_info = glXChooseVisual(dpy, screen, glx_attrib))) {
+               error("%s: Could not set requested video mode", __func__);
+               XCloseDisplay(dpy);
+               return false;
+       }
+
+       // check the video mode we got
+       int arbits, agbits, abbits, azbits, astencilbits;
+       glXGetConfig(dpy, vis_info, GLX_RED_SIZE, &arbits);
+       glXGetConfig(dpy, vis_info, GLX_GREEN_SIZE, &agbits);
+       glXGetConfig(dpy, vis_info, GLX_BLUE_SIZE, &abbits);
+       glXGetConfig(dpy, vis_info, GLX_DEPTH_SIZE, &azbits);
+       glXGetConfig(dpy, vis_info, GLX_STENCIL_SIZE, &astencilbits);
+
+       info("Initialized video mode:");
+       info("    bpp: %d (%d%d%d)", arbits + agbits + abbits, arbits, agbits, abbits);
+       info("zbuffer: %d", azbits);
+       info("stencil: %d", astencilbits);
+
+       /* if the dont_care_flags does not contain DONT_CARE_BPP and our color bits
+        * does not match, we should return failure, however we test against
+        * the difference allowing a +/-1 difference in order to allow for 16bpp
+        * formats of either 565 or 555 and consider them equal.
+        */
+       if(!(gparams->dont_care_flags & DONT_CARE_BPP) && abs(arbits - color_bits) > 1 && abs(agbits - color_bits) > 1 && abs(abbits - color_bits) > 1) {
+               error("%s: Could not set requested exact bpp mode", __func__);
+               XFree(vis_info);
+               XCloseDisplay(dpy);
+               return false;
+       }
+
+       // now if we don't have DONT_CARE_DEPTH in the dont_care_flags check for 
+       // exact depth buffer format, however consider 24 and 32 bit the same
+       if(!(gparams->dont_care_flags & DONT_CARE_DEPTH) && azbits != zbits) {
+               if(!(zbits == 32 && azbits == 24 || zbits == 24 && azbits == 32)) {
+                       error("%s: Could not set requested exact zbuffer depth", __func__);
+                       XFree(vis_info);
+                       XCloseDisplay(dpy);
+                       return false;
+               }
+       }
+
+       // if we don't have DONT_CARE_STENCIL make sure we have the stencil format
+       // that was asked.
+       if(!(gparams->dont_care_flags & DONT_CARE_STENCIL) && astencilbits != gparams->stencil_bits) {
+               error("%s: Could not set exact stencil format", __func__);
+               XFree(vis_info);
+               XCloseDisplay(dpy);
+               return false;
+       }
+
+       // everything is ok, create the context
+       if(!(glx_ctx = glXCreateContext(dpy, vis_info, 0, True))) {
+               error("%s: Failed to create GLX context", __func__);
+               XFree(vis_info);
+               XCloseDisplay(dpy);
+               return false;
+       }
+
+       XSetWindowAttributes xattr;
+       xattr.background_pixel = xattr.border_pixel = BlackPixel(dpy, screen);
+       xattr.colormap = XCreateColormap(dpy, root_win, vis_info->visual, AllocNone);
+
+       if(gparams->fullscreen) {
+               // TODO: also test for "XFree86-VidModeExtension"
+#ifdef USE_XF86VIDMODE
+               info("Using XF86VidMode extension for fullscreen resolution switch.");
+               
+               XF86VidModeModeInfo **modes;
+               XF86VidModeModeInfo *vid_mode = 0;
+               int mode_count;
+               
+               XF86VidModeGetAllModeLines(dpy, screen, &mode_count, &modes);
+               orig_mode = *modes[0];
+
+               for(int i=0; i<mode_count; i++) {
+                       if(modes[i]->hdisplay == gparams->x && modes[i]->vdisplay == gparams->y) {
+                               vid_mode = modes[i];
+                       }
+               }
+               if(!vid_mode) {
+                       error("Could not set requested video mode");
+                       XFree(modes);
+                       XFree(vis_info);
+                       XCloseDisplay(dpy);
+                       return -1;
+               }
+               
+               XF86VidModeSwitchToMode(dpy, screen, vid_mode);
+               XF86VidModeSetViewPort(dpy, screen, 0, 0);
+               XFree(modes);
+
+               xattr.override_redirect = True;
+               win = XCreateWindow(dpy, root_win, 0, 0, gparams->x, gparams->y, 0, vis_info->depth,
+                               InputOutput, vis_info->visual, CWColormap | CWBackPixel | CWBorderPixel | CWOverrideRedirect, &xattr);
+
+               XWarpPointer(dpy, None, win, 0, 0, 0, 0, 0, 0);
+               XMapRaised(dpy, win);
+        XGrabKeyboard(dpy, win, True, GrabModeAsync, GrabModeAsync, CurrentTime);
+        XGrabPointer(dpy, win, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, win, None, CurrentTime);
+#else
+               info("Resolution switching is not compiled or not supported by the X server, using a full-screen window.");
+
+               XWindowAttributes root_attr;
+               XGetWindowAttributes(dpy, root_win, &root_attr);
+
+               gparams->x = root_attr.width;
+               gparams->y = root_attr.height;
+               xattr.override_redirect = True;
+               win = XCreateWindow(dpy, root_win, 0, 0, gparams->x, gparams->y, 0, vis_info->depth,
+                               InputOutput, vis_info->visual, CWColormap | CWBackPixel | CWBorderPixel | CWOverrideRedirect, &xattr);
+
+               XWarpPointer(dpy, None, win, 0, 0, 0, 0, 0, 0);
+               XMapRaised(dpy, win);
+        XGrabKeyboard(dpy, win, True, GrabModeAsync, GrabModeAsync, CurrentTime);
+        XGrabPointer(dpy, win, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, win, None, CurrentTime);
+#endif // USE_XF86VIDMODE
+
+               fullscreen = true;
+       } else {
+               win = XCreateWindow(dpy, root_win, 0, 0, gparams->x, gparams->y, 0, vis_info->depth,
+                               InputOutput, vis_info->visual, CWColormap | CWBackPixel | CWBorderPixel, &xattr);
+       }
+
+       long events = ExposureMask | StructureNotifyMask | KeyPressMask;        // expose and key events
+       events |= ButtonPressMask | ButtonReleaseMask | PointerMotionMask;      // mouse events
+       XSelectInput(dpy, win, events);
+               
+       // set WM cooperation settings
+       Atom wm_delete = XInternAtom(dpy, "WM_DELETE_WINDOW", True);
+       XSetWMProtocols(dpy, win, &wm_delete, 1);
+
+       XTextProperty tp_wname;
+       static char *win_title = "3dengfx/X";
+       XStringListToTextProperty(&win_title, 1, &tp_wname);
+       XSetWMName(dpy, win, &tp_wname);
+       XFree(tp_wname.value);
+
+       XClassHint class_hint;
+       class_hint.res_name = "3dengfx";
+       class_hint.res_class = "3dengfx_graphics";
+       XSetClassHint(dpy, win, &class_hint);
+
+       XFree(vis_info);
+
+       if(glXMakeCurrent(dpy, win, glx_ctx) == False) {
+               error("%s: Failed to make the GLX context current", __func__);
+               glXDestroyContext(dpy, glx_ctx);
+               XDestroyWindow(dpy, win);
+               XCloseDisplay(dpy);
+               return false;
+       }
+
+       if(!glXIsDirect(dpy, glx_ctx)) {
+               warning("using indirect rendering, which might be slow...");
+       }
+
+       XMapWindow(dpy, win);
+       XFlush(dpy);
+
+       fxwt_x_dpy = dpy;
+       fxwt_x_win = win;
+       
+       return true;
+}
+
+void fxwt::destroy_graphics() {
+       info("Shutting down GLX");
+       glXDestroyContext(fxwt_x_dpy, glx_ctx);
+       XDestroyWindow(fxwt_x_dpy, fxwt_x_win);
+
+#ifdef USE_XF86VIDMODE
+       if(fullscreen) {
+               XF86VidModeSwitchToMode(fxwt_x_dpy, DefaultScreen(fxwt_x_dpy), &orig_mode);
+               XF86VidModeSetViewPort(fxwt_x_dpy, DefaultScreen(fxwt_x_dpy), 0, 0);
+       }
+#endif // USE_XF86VIDMODE
+       
+       XCloseDisplay(fxwt_x_dpy);
+}
+
+#ifndef GLX_ARB_get_proc_address
+#include <dlfcn.h>
+
+void *glXGetProcAddress(const char *name) {
+       char *err_str;
+       void *sym;
+       void *so = dlopen("libGL.so", RTLD_LAZY);
+       if(!so) {
+               perror("dlopen failed");
+               return 0;
+       }
+       
+       dlerror();
+       sym = dlsym(so, name);
+       if((err_str = dlerror())) {
+               fprintf(stderr, "dlsym failed: %s\n", err_str);
+               sym = 0;
+       }
+       
+       dlclose(so);
+       return sym;
+}
+#endif
+
+#endif // GFX_LIBRARY == NATIVE && NATIVE_LIB == NATIVE_X11
diff --git a/src/3dengfx/src/fxwt/keysyms.hpp b/src/3dengfx/src/fxwt/keysyms.hpp
new file mode 100644 (file)
index 0000000..d329990
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+This file is part of fxwt, the window system toolkit of 3dengfx.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef _KEYSYMS_HPP_
+#define _KEYSYMS_HPP_
+
+// keysyms taken from SDL
+
+namespace fxwt {
+       enum {
+               KEY_BACKSPACE   = 8,
+               KEY_TAB                 = 9,
+               KEY_CLEAR               = 12,
+               KEY_RETURN              = 13,
+               KEY_PAUSE               = 19,
+               KEY_ESCAPE              = 27,
+               KEY_DELETE              = 127,
+       
+               /* Numeric keypad */
+               KEY_KP0                 = 256,
+               KEY_KP1                 = 257,
+               KEY_KP2                 = 258,
+               KEY_KP3                 = 259,
+               KEY_KP4                 = 260,
+               KEY_KP5                 = 261,
+               KEY_KP6                 = 262,
+               KEY_KP7                 = 263,
+               KEY_KP8                 = 264,
+               KEY_KP9                 = 265,
+               KEY_KP_PERIOD   = 266,
+               KEY_KP_DIVIDE   = 267,
+               KEY_KP_MULTIPLY = 268,
+               KEY_KP_MINUS    = 269,
+               KEY_KP_PLUS             = 270,
+               KEY_KP_ENTER    = 271,
+               KEY_KP_EQUALS   = 272,
+
+               /* Arrows + Home/End pad */
+               KEY_UP                  = 273,
+               KEY_DOWN                = 274,
+               KEY_RIGHT               = 275,
+               KEY_LEFT                = 276,
+               KEY_INSERT              = 277,
+               KEY_HOME                = 278,
+               KEY_END                 = 279,
+               KEY_PAGEUP              = 280,
+               KEY_PAGEDOWN    = 281,
+
+               /* Function keys */
+               KEY_F1                  = 282,
+               KEY_F2                  = 283,
+               KEY_F3                  = 284,
+               KEY_F4                  = 285,
+               KEY_F5                  = 286,
+               KEY_F6                  = 287,
+               KEY_F7                  = 288,
+               KEY_F8                  = 289,
+               KEY_F9                  = 290,
+               KEY_F10                 = 291,
+               KEY_F11                 = 292,
+               KEY_F12                 = 293,
+               KEY_F13                 = 294,
+               KEY_F14                 = 295,
+               KEY_F15                 = 296,
+
+               /* Key state modifier keys */
+               KEY_NUMLOCK             = 300,
+               KEY_CAPSLOCK    = 301,
+               KEY_SCROLLOCK   = 302,
+               KEY_RSHIFT              = 303,
+               KEY_LSHIFT              = 304,
+               KEY_RCTRL               = 305,
+               KEY_LCTRL               = 306,
+               KEY_RALT                = 307,
+               KEY_LALT                = 308,
+               KEY_RMETA               = 309,
+               KEY_LMETA               = 310,
+               KEY_LSUPER              = 311,          /* Left "Windows" key */
+               KEY_RSUPER              = 312,          /* Right "Windows" key */
+               KEY_MODE                = 313           /* "Alt Gr" key */
+       };
+}
+
+#endif // _KEYSYMS_HPP_
diff --git a/src/3dengfx/src/fxwt/makefile.part b/src/3dengfx/src/fxwt/makefile.part
new file mode 100644 (file)
index 0000000..bd7bfbe
--- /dev/null
@@ -0,0 +1,13 @@
+fxwt_obj =\
+       src/fxwt/fxwt.o\
+       src/fxwt/text.o\
+       src/fxwt/fxwt_sdl.o\
+       src/fxwt/init_sdl.o\
+       src/fxwt/fxwt_x.o\
+       src/fxwt/init_x.o\
+       src/fxwt/fxwt_win32.o\
+       src/fxwt/init_win32.o\
+       src/fxwt/fxwt_glut.o\
+       src/fxwt/init_glut.o\
+       src/fxwt/fxwt_gtk.o\
+       src/fxwt/init_gtk.o
diff --git a/src/3dengfx/src/fxwt/text.cpp b/src/3dengfx/src/fxwt/text.cpp
new file mode 100644 (file)
index 0000000..85b34c6
--- /dev/null
@@ -0,0 +1,427 @@
+/*
+This file is part of fxwt, the window system toolkit of 3dengfx.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* True type text rendering and management.
+ *
+ * Author: John Tsiombikas 2005
+ */
+
+#include "3dengfx_config.h"
+
+#ifndef FXWT_NO_FREETYPE
+#include <vector>
+#include <cstdio>
+#include <cassert>
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include "text.hpp"
+#include "3dengfx/textures.hpp"
+#include "3dengfx/texman.hpp"
+#include "common/hashtable.hpp"
+#include "dsys/demosys.hpp"
+#include "common/err_msg.h"
+#include "common/string_hash.hpp"
+#include "gfx/img_manip.hpp"
+
+using namespace std;
+using namespace fxwt;
+
+struct Text {
+       Texture *texture;
+       scalar_t aspect;
+};
+
+static const char *find_font_file(const char *font);
+static string gen_key_str(const char *text);
+static void draw_free_type_bitmap(FT_Bitmap *ftbm, PixelBuffer *pbuf, int x, int y);
+static PixelBuffer *create_text_image(const char *str, FT_Face face, int font_size);
+static int next_pow_two(int num);
+static Texture *pixel_buf_to_texture(const PixelBuffer &pbuf);
+
+static FT_LibraryRec_ *ft;
+static vector<FT_FaceRec_*> face_list;
+static HashTable<string, Text> text_table;
+static FT_FaceRec_ *font;
+static int font_size = 64;
+static scalar_t latest_fetched_aspect = 1;
+static TextRenderMode render_mode = TEXT_TRANSPARENT;
+
+/* This list MUST correspond to the enum Font at text.hpp
+ * so take care to keep them in sync.
+ */
+static const char *font_names[] = {
+       "FreeSans",
+       "FreeSerif",
+       "FreeMono",
+       "Bitstream Vera Sans",
+       "Bitstream Vera Serif",
+       "Bitstream Vera Sans Mono",
+       "Verdana",
+       "Times New Roman",
+       "Courier New"
+};
+
+// update these lists when adding a new font
+static Font font_style_list[3][4] = {
+       // sans-serif fonts
+       {FONT_FREE_SANS, FONT_MS_SANS, FONT_VERA_SANS, FONT_NULL},
+       // serif fonts
+       {FONT_FREE_SERIF, FONT_MS_SERIF, FONT_VERA_SERIF, FONT_NULL},
+       // monospaced fonts
+       {FONT_FREE_MONO, FONT_MS_MONO, FONT_VERA_MONO, FONT_NULL}
+};
+
+
+#if defined(__unix__)
+#define VERDANA_FILE                   "Verdana.ttf"
+#define TIMES_NEW_ROMAN_FILE   "Times_New_Roman.ttf"
+#define COURIER_NEW_FILE               "Courier_New.ttf"
+#elif defined(WIN32) || defined(__WIN32__)
+#define VERDANA_FILE                   "verdana.ttf"
+#define TIMES_NEW_ROMAN_FILE   "times.ttf"
+#define COURIER_NEW_FILE               "cour.ttf"
+#endif
+
+bool fxwt::text_init() {
+       
+       set_verbosity(2);
+
+       text_table.set_hash_function(string_hash);
+
+       if(FT_Init_FreeType(&ft) != 0) return false;
+       
+       static const char *fonts[] = {
+               "FreeSans.ttf", "FreeSerif.ttf", "FreeMono.ttf",                        // freefonts
+               "Vera.ttf", "VeraSe.ttf", "VeraMono.ttf",                                       // bitstream vera fonts
+               VERDANA_FILE, TIMES_NEW_ROMAN_FILE, COURIER_NEW_FILE,           // MS fonts
+               0
+       };
+
+       const char **fptr = fonts;
+       while(*fptr) {
+               const char *font_path = find_font_file(*fptr++);
+               if(font_path) {
+                       FT_Face face;
+                       if(FT_New_Face(ft, font_path, 0, &face) == 0) {
+                               info("Loaded font \"%s\" (%s)", font_path, face->family_name);
+                               if(!font) font = face;
+                       }
+                       face_list.push_back(face);
+               }
+       }
+
+       atexit(fxwt::text_close);
+
+       set_verbosity(3);
+
+       return true;
+}
+
+void fxwt::text_close() {
+       // TODO: free the textures
+       
+       for(size_t i=0; i<face_list.size(); i++) {
+               FT_Done_Face(face_list[i]);
+       }
+       FT_Done_FreeType(ft);
+}
+
+void fxwt::set_text_render_mode(TextRenderMode mode) {
+       render_mode = mode;
+}
+
+void fxwt::set_font_size(int sz) {
+       font_size = sz;
+}
+
+int fxwt::get_font_size() {
+       return font_size;
+}
+
+bool fxwt::set_font(Font fnt) {
+       for(size_t i=0; i<face_list.size(); i++) {
+               if(!strcmp(face_list[i]->family_name, font_names[fnt])) {
+                       font = face_list[i];    
+                       return true;
+               }
+       }       
+       return false;
+}
+
+bool fxwt::set_font(FontStyle fstyle) {
+       int i = 0;
+       while(font_style_list[fstyle][i] != FONT_NULL) {
+               if(set_font(font_style_list[fstyle][i++])) return true;
+       }
+       return false;
+}
+
+const char *fxwt::get_font_name(Font fnt) {
+       return font_names[fnt];
+}
+
+Texture *fxwt::get_text(const char *text_str) {
+       Pair<string, Text> *res;
+       if((res = text_table.find(gen_key_str(text_str)))) {
+               latest_fetched_aspect = res->val.aspect;
+               return res->val.texture;
+       }
+
+       PixelBuffer *text_img = create_text_image(text_str, font, font_size);
+       scalar_t aspect = (scalar_t)text_img->width / (scalar_t)text_img->height;
+       Texture *tex = pixel_buf_to_texture(*text_img);
+       delete text_img;
+
+       Text text = {tex, aspect};
+       text_table.insert(gen_key_str(text_str), text);
+       
+       latest_fetched_aspect = aspect;
+       return tex;
+}
+
+
+void fxwt::print_text(const char *text_str, const Vector2 &pos, scalar_t size, const Color &col) {
+       Texture *tex = get_text(text_str);
+       Vector2 sz_vec(size * latest_fetched_aspect, size);
+       
+       dsys::overlay(tex, pos, pos + sz_vec, col);
+}
+
+static const char *find_font_file(const char *font) {
+       static char path[512];
+       FILE *fp;
+
+       // TODO: add data path search through the locator
+       if((fp = fopen(font, "r"))) {
+               fclose(fp);
+               return font;
+       }
+
+#ifdef __unix__
+       // try /usr/share/fonts/truetype
+       sprintf(path, "/usr/share/fonts/truetype/%s", font);
+       if((fp = fopen(path, "r"))) {
+               fclose(fp);
+               return path;
+       }
+
+       // try /usr/share/fonts/truetype/freefont
+       sprintf(path, "/usr/share/fonts/truetype/freefont/%s", font);
+       if((fp = fopen(path, "r"))) {
+               fclose(fp);
+               return path;
+       }
+
+       // try /usr/share/fonts/truetype/ttf-bitstream-vera
+       sprintf(path, "/usr/share/fonts/truetype/ttf-bitstream-vera/%s", font);
+       if((fp = fopen(path, "r"))) {
+               fclose(fp);
+               return path;
+       }
+#endif /* __unix__ */
+
+#ifdef WIN32
+       // try %windir%\fonts
+       sprintf(path, "%s\\fonts\\%s", getenv("WINDIR"), font);
+       if((fp = fopen(path, "r"))) {
+               fclose(fp);
+               return path;
+       }
+#endif /* WIN32 */
+
+       return 0;
+}
+
+static string gen_key_str(const char *text) {
+       if(font->family_name) {
+               return string(font->family_name) + string("##") + string(text);
+       }
+       return string(text);
+}
+
+
+static void draw_free_type_bitmap(FT_Bitmap *ftbm, PixelBuffer *pbuf, int x, int y) {
+       int i, j;
+       Pixel *dptr = pbuf->buffer + y * pbuf->width + x;
+       unsigned char *sptr = (unsigned char*)ftbm->buffer;
+
+       assert(x >= 0);
+       assert(y >= 0);
+
+       for(i=0; i<ftbm->rows; i++) {
+               if(i + y >= (int)pbuf->height) break;
+               
+               for(j=0; j<ftbm->width; j++) {
+                       if(j + x >= (int)pbuf->width) break;
+
+                       Pixel pixel = *sptr++;
+                       
+                       if(render_mode == TEXT_TRANSPARENT) {
+                               *dptr++ = 0x00ffffff | (pixel << 24);
+                       } else {
+                               *dptr++ = 0xff000000 | (pixel << 8) | (pixel << 16) | pixel;
+                       }
+               }
+
+               sptr += ftbm->pitch - j;
+               dptr += pbuf->width - j;
+       }
+}
+
+static PixelBuffer *create_text_image(const char *str, FT_Face face, int font_size) {
+       FT_GlyphSlot slot = face->glyph;
+       FT_Set_Pixel_Sizes(face, 0, font_size); // set size
+
+       size_t len = strlen(str);
+       PixelBuffer tmp_buf(len * font_size * 2, font_size * 2);
+       memset(tmp_buf.buffer, 0, tmp_buf.width * tmp_buf.height * sizeof(Pixel));
+
+       int pen_x = 0;
+       int pen_y = font_size;
+
+       for(size_t i=0; i<len; i++) {
+               if(FT_Load_Char(face, *str++, FT_LOAD_RENDER) != 0) {
+                       cerr << "aaaaaaaa!\n";
+                       continue;
+               }
+
+               draw_free_type_bitmap(&slot->bitmap, &tmp_buf, pen_x + slot->bitmap_left, pen_y - slot->bitmap_top);
+
+               pen_x += slot->advance.x >> 6;
+       }
+
+       assert(pen_x <= (int)tmp_buf.width);
+
+       PixelBuffer *pbuf = new PixelBuffer(pen_x, (int)(font_size * 1.5));
+       
+       Pixel *dptr = pbuf->buffer;
+       Pixel *sptr = tmp_buf.buffer;
+
+       for(size_t i=0; i<pbuf->height; i++) {
+               memcpy(dptr, sptr, pbuf->width * sizeof(Pixel));
+               dptr += pbuf->width;
+               sptr += tmp_buf.width;
+       }
+
+       return pbuf;
+}
+
+static int next_pow_two(int num) {
+       int val = 1;
+       while(val < num) val <<= 1;
+       return val;
+}
+
+static Texture *pixel_buf_to_texture(const PixelBuffer &pbuf) {
+
+       int w, h;
+       Texture *tex;
+       
+       if (engfx_state::sys_caps.non_power_of_two_textures)
+       {
+               w = pbuf.width;
+               h = pbuf.height;
+               tex = new Texture(w, h);
+               tex->set_pixel_data(pbuf);
+       }
+       else
+       {
+               w = next_pow_two(pbuf.width);
+               h = next_pow_two(pbuf.height);
+               PixelBuffer tmp = pbuf;
+               resample_pixel_buffer(&tmp, w, h);
+               tex = new Texture(w, h);
+               tex->set_pixel_data(tmp);
+       }
+
+       /*tex->lock();
+
+       float dx = (float)pbuf.width / (float)w;
+       float dy = (float)pbuf.height / (float)h;
+
+       for(int j=0; j<h; j++) {
+               for(int i=0; i<w; i++) {
+                       int x = (int)(((float)i * dx) + 0.5);
+                       int y = (int)(((float)j * dy) + 0.5);
+                       tex->buffer[j * w + i] = pbuf.buffer[y * pbuf.width + x];
+               }
+       }
+
+       tex->unlock();*/
+       return tex;
+}
+
+#else          // if we excluded freetype dependencies from compilation
+
+#include "text.hpp"
+#include "common/err_msg.h"
+
+using namespace fxwt;
+
+#define FT_NOT_COMPILED                "some text-rendering function is called, but freetype support is not compiled in"
+
+bool fxwt::text_init() {
+       return false;
+}
+
+void fxwt::text_close() {}
+
+void fxwt::set_text_render_mode(TextRenderMode mode) {
+       error(FT_NOT_COMPILED);
+}
+
+void fxwt::set_font_size(int sz) {
+       error(FT_NOT_COMPILED);
+}
+
+int fxwt::get_font_size() {
+       error(FT_NOT_COMPILED);
+       return 0;
+}
+
+bool fxwt::set_font(Font fnt) {
+       error(FT_NOT_COMPILED);
+       return false;
+}
+
+bool fxwt::set_font(FontStyle fstyle) {
+       error(FT_NOT_COMPILED);
+       return false;
+}
+
+const char *fxwt::get_font_name(Font fnt) {
+       error(FT_NOT_COMPILED);
+       return 0;
+}
+
+Texture *fxwt::get_text(const char *text_str) {
+       error(FT_NOT_COMPILED);
+       return 0;
+}
+
+void fxwt::print_text(const char *text_str, const Vector2 &pos, scalar_t size, const Color &col) {
+       static bool first = true;
+       if(first) {
+               error(FT_NOT_COMPILED);
+               first = false;
+       }
+}
+
+#endif // FXWT_NO_FREETYPE
diff --git a/src/3dengfx/src/fxwt/text.hpp b/src/3dengfx/src/fxwt/text.hpp
new file mode 100644 (file)
index 0000000..5b8cc12
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+This file is part of fxwt, the window system toolkit of 3dengfx.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* True type text rendering and management.
+ *
+ * Author: John Tsiombikas 2005
+ */
+
+#ifndef _TEXT_HPP_
+#define _TEXT_HPP_
+
+#include "3dengfx/textures.hpp"
+#include "n3dmath2/n3dmath2.hpp"
+#include "gfx/color.hpp"
+
+namespace fxwt {
+
+       enum Font {
+               FONT_FREE_SANS,
+               FONT_FREE_SERIF,
+               FONT_FREE_MONO,
+
+               FONT_VERA_SANS,
+               FONT_VERA_SERIF,
+               FONT_VERA_MONO,
+               
+               FONT_VERDANA,
+               FONT_TIMES_NEW_ROMAN,
+               FONT_COURIER_NEW,
+               
+               FONT_MS_SANS = FONT_VERDANA,
+               FONT_MS_SERIF = FONT_TIMES_NEW_ROMAN,
+               FONT_MS_MONO = FONT_COURIER_NEW,
+
+               FONT_NULL       /* keep this last */
+       };
+
+       enum FontStyle {
+               FONT_SANS,
+               FONT_SERIF,
+               FONT_MONO
+       };
+
+       enum TextRenderMode {TEXT_TRANSPARENT, TEXT_OPAQUE};
+       
+       bool text_init();
+       void text_close();
+
+       void set_text_render_mode(TextRenderMode mode);
+
+       void set_font_size(int sz);
+       int get_font_size();
+
+       bool set_font(Font fnt);
+       bool set_font(FontStyle fstyle);
+
+       const char *get_font_name(Font fnt);
+
+       Texture *get_text(const char *text_str);
+
+       void print_text(const char *text_str, const Vector2 &pos, scalar_t size, const Color &col = Color(1,1,1));
+}
+
+#endif /* _TEXT_HPP_ */
diff --git a/src/3dengfx/src/gfx/3dgeom.cpp b/src/3dengfx/src/gfx/3dgeom.cpp
new file mode 100644 (file)
index 0000000..bc0283f
--- /dev/null
@@ -0,0 +1,1044 @@
+/*
+This file is part of the 3dengfx, realtime visualization system.
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* fundamendal data structures for 3D graphics
+ *
+ * Author: John Tsiombikas 2004
+ * Modified: 
+ *             Mihalis Georgoulopoulos 2004, 2005
+ *             John Tsiombikas 2005
+ */
+
+#include "3dengfx_config.h"
+
+#include <iostream>
+#include <cstdlib>
+#include <cfloat>
+#include <algorithm>
+#include "3dgeom.hpp"
+#include "common/psort.hpp"
+
+#ifdef USING_3DENGFX
+#include "3dengfx/3denginefx.hpp"
+#endif // USING_3DENGFX
+
+using std::vector;
+using namespace glext;
+
+TexCoord::TexCoord(scalar_t u, scalar_t v, scalar_t w) {
+       this->u = u;
+       this->v = v;
+       this->w = w;
+}
+
+// Vertex class implementation
+
+Vertex::Vertex() {
+       //normal = Vector3(0, 1, 0);
+}
+
+Vertex::Vertex(const Vector3 &position, scalar_t tu, scalar_t tv, const Color &color) {
+       pos = position;
+       normal = Vector3(0, 1, 0);
+       tex[0].u = tex[1].u = tu;
+       tex[0].v = tex[1].v = tv;
+       this->color = color;
+}
+
+/////////// Edge class implementation ///////////
+
+Edge::Edge() {
+       vertices[0] = vertices[1] = 0;
+       adjfaces[0] = adjfaces[1] = NO_ADJFACE;
+}
+
+Edge::Edge(Index v1, Index v2, Index af1, Index af2) {
+       vertices[0] = v1;
+       vertices[1] = v2;
+       adjfaces[0] = af1;
+       adjfaces[1] = af2;
+}
+
+std::ostream &operator <<(std::ostream &o, const Edge &e) {
+       o << "v(" << e.vertices[0] << ", " << e.vertices[1] << ")";
+       o << " t(" << e.adjfaces[0] << ", " << e.adjfaces[1] << ")";
+       return o;
+}
+
+/////////// Triangle class implementation /////////////
+Triangle::Triangle(Index v1, Index v2, Index v3) {
+       vertices[0] = v1;
+       vertices[1] = v2;
+       vertices[2] = v3;
+
+       smoothing_group = 0;
+}
+
+void Triangle::calculate_normal(const Vertex *vbuffer, bool normalize) {
+       Vector3 v1 = vbuffer[vertices[1]].pos - vbuffer[vertices[0]].pos;
+       Vector3 v2 = vbuffer[vertices[2]].pos - vbuffer[vertices[0]].pos;
+       normal = cross_product(v1, v2);
+       if(normalize) normal.normalize();
+}
+
+void Triangle::calculate_tangent(const Vertex *vbuffer, bool normalize){
+       Vector3 a, b, c, d;
+       scalar_t au, bu, cu, du;
+       
+       a = vbuffer[vertices[0]].pos;
+       b = vbuffer[vertices[1]].pos;
+       c = vbuffer[vertices[2]].pos;
+
+       au = vbuffer[vertices[0]].tex[0].u;
+       bu = vbuffer[vertices[1]].tex[0].u;
+       cu = vbuffer[vertices[2]].tex[0].u;
+
+       int i=0;
+
+       // rotate a b and c until au!=bu and au != cu
+       while ( fabs(au - bu) < xsmall_number && 
+                       fabs(au - cu) < xsmall_number && i < 3)
+       {
+               du = cu; cu = bu; bu = au; au = du;
+               d = c; c = b; b = a; a = d;
+               i++;
+       }
+
+       if (i == 3)
+       {
+               // all u's are the same. cannot calculate tangent
+               tangent = Vector3(0, 0, 0);
+               return;
+       }
+
+       // find d using linear interpolation
+       d = a + (((bu - au) / (cu - au)) * (c - a));
+       
+       // find the projection of a to b->d
+       Vector3 bd = d - b;
+       bd.normalize();
+       Vector3 ab = b - a;
+       Vector3 a_proj = ab - (dot_product(ab, bd) * bd);
+
+       if (bu > au) tangent = a_proj - a;
+       else tangent = a - a_proj;
+       if (normalize) tangent.normalize();
+}
+
+std::ostream &operator <<(std::ostream &o, const Triangle &t) {
+       o << "[" << t.vertices[0] << ", " << t.vertices[1] << ", " << t.vertices[2] << "]";
+       return o;
+}
+
+Quad::Quad(Index v1, Index v2, Index v3, Index v4) {
+       vertices[0] = v1;
+       vertices[1] = v2;
+       vertices[2] = v3;
+       vertices[3] = v4;
+}
+
+void Quad::calculate_normal(const Vertex *vbuffer, bool normalize) {
+       Vector3 v1 = vbuffer[vertices[1]].pos - vbuffer[vertices[0]].pos;
+       Vector3 v2 = vbuffer[vertices[2]].pos - vbuffer[vertices[0]].pos;
+       normal = cross_product(v1, v2);
+       if(normalize) normal.normalize();
+}
+
+///////////////////////////////////////////
+// Index specialization of GeometryArray //
+///////////////////////////////////////////
+
+GeometryArray<Index>::GeometryArray(bool dynamic) {
+       data = 0;
+       count = 0;
+       buffer_object = INVALID_VBO;
+       vbo_in_sync = false;
+
+       set_dynamic(dynamic);
+}
+
+GeometryArray<Index>::GeometryArray(const Index *data, unsigned long count, bool dynamic) {
+       this->data = 0;
+       this->count = 0;
+       buffer_object = INVALID_VBO;
+       set_dynamic(dynamic);
+
+       set_data(data, count);
+}
+
+void tri_to_index_array(GeometryArray<Index> *ia, const GeometryArray<Triangle> &ta) {
+       ia->dynamic = ta.get_dynamic();
+
+       unsigned long tcount = ta.get_count();
+       Index *tmp_data = new Index[tcount * 3];
+
+       Index *ptr = tmp_data;
+       for(unsigned long i=0; i<tcount; i++) {
+               for(int j=0; j<3; j++) {
+                       *ptr++ = ta.get_data()[i].vertices[j];
+               }
+       }
+
+       ia->set_data(tmp_data, tcount * 3);
+       delete [] tmp_data;
+}
+
+GeometryArray<Index>::GeometryArray(const GeometryArray<Triangle> &tarray) {
+       tri_to_index_array(this, tarray);
+}
+
+GeometryArray<Index>::GeometryArray(const GeometryArray<Index> &ga) {
+       data = 0;
+       count = 0;
+       buffer_object = INVALID_VBO;
+       dynamic = ga.dynamic;
+
+       set_data(ga.data, ga.count);
+}
+
+GeometryArray<Index>::~GeometryArray() {
+       if(data) {
+               delete [] data;
+       }
+#ifdef USING_3DENGFX
+       if(buffer_object != INVALID_VBO) {
+               glDeleteBuffers(1, &buffer_object);
+       }
+#endif // USING_3DENGFX
+}
+
+GeometryArray<Index> &GeometryArray<Index>::operator =(const GeometryArray<Index> &ga) {
+       dynamic = ga.dynamic;
+       if(data) delete [] data;
+
+       set_data(ga.data, ga.count);
+
+       return *this;
+}
+
+void GeometryArray<Index>::sync_buffer_object() {
+#ifdef USING_3DENGFX
+       if(dynamic) return;
+
+       if(buffer_object == INVALID_VBO) {
+               glGenBuffers(1, &buffer_object);
+               glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, buffer_object);
+               glBufferData(GL_ELEMENT_ARRAY_BUFFER_ARB, count * sizeof(Index), data, GL_STATIC_DRAW_ARB);
+               glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
+       } else {
+
+               int glerr;
+               while((glerr = glGetError()) != GL_NO_ERROR) {
+                       std::cerr << get_glerror_string(glerr) << " ";
+               }
+               glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, buffer_object);
+               
+               glBufferData(GL_ELEMENT_ARRAY_BUFFER_ARB, count * sizeof(Index), data, GL_STATIC_DRAW_ARB);
+               glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
+       }
+#endif // USING_3DENGFX
+       vbo_in_sync = true;
+
+}
+
+void GeometryArray<Index>::set_data(const Index *data, unsigned long count) {
+       if(!data) return;
+       if(!this->data || count != this->count) {
+               if(this->data) {
+                       delete [] this->data;
+               }
+               this->data = new Index[count];
+       }
+
+       memcpy(this->data, data, count * sizeof(Index));
+
+#ifdef USING_3DENGFX
+       if(!dynamic) {
+               if(buffer_object != INVALID_VBO && count != this->count) {
+                       glDeleteBuffers(1, &buffer_object);
+               }
+               sync_buffer_object();
+               vbo_in_sync = true;
+       }
+#endif // USING_3DENGFX
+
+       this->count = count;
+}
+
+
+///////////// Triangle Mesh Implementation /////////////
+TriMesh::TriMesh() {
+       indices_valid = false;
+       vertex_stats_valid = false;
+       edges_valid = false;
+       index_graph_valid = false;
+       triangle_normals_valid = false;
+       triangle_normals_normalized = false;
+}
+
+TriMesh::TriMesh(const Vertex *vdata, unsigned long vcount, const Triangle *tdata, unsigned long tcount) {
+       indices_valid = false;
+       vertex_stats_valid = false;
+       edges_valid = false;
+       index_graph_valid = false;
+       triangle_normals_valid = false;
+       triangle_normals_normalized = false;
+       set_data(vdata, vcount, tdata, tcount);
+}
+
+void TriMesh::calculate_edges() {
+
+       if (!index_graph_valid)
+               calculate_index_graph();
+
+       unsigned int vcount = varray.get_count();
+       vector<Edge> *edge_table = new vector<Edge>[vcount];
+       const Triangle *tris = tarray.get_data();
+       const Index *igraph = index_graph.get_data();
+       unsigned int tcount = tarray.get_count();
+       unsigned int num_edges = 0;
+
+       // Triangle loop
+       for (unsigned int i=0; i<tcount; i++)
+       {
+               unsigned int a, b, temp;
+               for (unsigned int j=0; j<3; j++)
+               {
+                       a = igraph[tris[i].vertices[j]];
+                       b = igraph[tris[i].vertices[(j + 1) % 3]];
+
+                       if (a > b)
+                       {
+                               temp = b;
+                               b = a;
+                               a = temp;
+                       }
+
+                       int edge_found = -1;
+                       for (unsigned int edge = 0; edge < edge_table[a].size(); edge++)
+                       {
+                               if (edge_table[a][edge].vertices[1] == b)
+                               {
+                                       edge_found = edge;
+                                       break;
+                               }
+                       }
+
+                       if (edge_found != -1)
+                       {
+                               // edge was already in the list
+                               // add the second face to this edge
+                               edge_table[a][edge_found].adjfaces[1] = i;
+                       }
+                       else
+                       {
+                               // add a new edge to the list
+                               Edge new_edge(a, b, i);
+                               edge_table[a].push_back(new_edge);
+                               num_edges++;
+                       }
+               }
+       } // End triangle loop
+
+       // collect edges
+       Edge *edges = new Edge[num_edges];
+       int k = 0;
+       for (unsigned int i=0; i<vcount; i++)
+       {
+               for (unsigned int j=0; j<edge_table[i].size(); j++)
+               {
+                       edges[k] = edge_table[i][j];
+                       k++;
+               }
+       }
+
+       earray.set_data(edges, num_edges);
+       edges_valid = true;
+
+       // cleanup
+       delete [] edge_table;
+       delete [] edges;
+}
+
+void TriMesh::calculate_triangle_normals(bool normalize)
+{
+       // calculate the triangle normals
+       for(unsigned int i=0; i<tarray.get_count(); i++) {
+               tarray.get_mod_data()[i].calculate_normal(varray.get_data(), normalize);
+       }
+
+       triangle_normals_valid = true;
+       triangle_normals_normalized = normalize;
+}
+
+const IndexArray *TriMesh::get_index_array() {
+       if(!indices_valid) {
+               tri_to_index_array(&iarray, tarray);
+               indices_valid = true;
+       }
+       return &iarray;
+}
+
+const GeometryArray<Edge> *TriMesh::get_edge_array() const {
+       if(!edges_valid) {
+               const_cast<TriMesh*>(this)->calculate_edges();
+       }
+       return &earray;
+}
+
+void TriMesh::set_data(const Vertex *vdata, unsigned long vcount, const Triangle *tdata, unsigned long tcount) {
+       get_mod_vertex_array()->set_data(vdata, vcount);        // also invalidates vertex stats
+       get_mod_triangle_array()->set_data(tdata, tcount);      // also invalidates indices and edges
+}
+
+void TriMesh::calculate_normals_by_index() {
+       // precalculate which triangles index each vertex
+       std::vector<unsigned int> *tri_indices;
+       tri_indices = new std::vector<unsigned int>[varray.get_count()];
+
+       for(unsigned int i=0; i<tarray.get_count(); i++) {
+               for(int j=0; j<3; j++) {        
+                       tri_indices[tarray.get_data()[i].vertices[j]].push_back(i);
+               }
+       }
+
+       // calculate the triangle normals
+       if (!triangle_normals_valid)
+               calculate_triangle_normals(false);
+       
+       // now calculate the vertex normals
+       for(unsigned int i=0; i<varray.get_count(); i++) {
+               Vector3 normal;
+               for(unsigned int j=0; j<(unsigned int)tri_indices[i].size(); j++) {
+                       normal += tarray.get_data()[tri_indices[i][j]].normal;
+               }
+               
+               // avoid division by zero
+               if(tri_indices[i].size()) {
+                       normal.normalize();
+               }
+               varray.get_mod_data()[i].normal = normal;
+       }
+       
+       delete [] tri_indices;
+}
+
+/* TriMesh::calculate_normals() - (MG)
+ */
+void TriMesh::calculate_normals()
+{
+       if (!index_graph_valid)
+               calculate_index_graph();
+       
+       // calculate the triangle normals
+       if (!triangle_normals_valid)
+               calculate_triangle_normals(false);
+
+       // precalculate which triangles index each vertex
+       std::vector<unsigned int> *tri_indices;
+       tri_indices = new std::vector<unsigned int>[varray.get_count()];
+
+       for(unsigned int i=0; i<tarray.get_count(); i++) {
+               for(int j=0; j<3; j++) {        
+                       Index tri_index = index_graph.get_data()[tarray.get_data()[i].vertices[j]];
+                       tri_indices[tri_index].push_back(i);
+               }
+       }
+       
+       // now calculate the vertex normals
+       for(unsigned int i=0; i<varray.get_count(); i++) {
+               
+               if (index_graph.get_data()[i] != i)
+               {
+                       // normal already calculated. Just copy
+                       varray.get_mod_data()[i].normal = varray.get_mod_data()[index_graph.get_data()[i]].normal;
+                       continue;
+               }
+                       
+               Vector3 normal;
+               for(unsigned int j=0; j<(unsigned int)tri_indices[i].size(); j++) {
+                       normal += tarray.get_data()[tri_indices[i][j]].normal;
+               }
+               
+               // avoid division with zero
+               if (tri_indices[i].size())
+                       normal.normalize();
+               varray.get_mod_data()[i].normal = normal;
+       }
+       
+       delete [] tri_indices;
+}
+
+void TriMesh::normalize_normals() {
+       Vertex *vptr = varray.get_mod_data();
+       for(unsigned int i=0; i<varray.get_count(); i++) {
+               vptr[i].normal.normalize();
+       }
+}
+
+/* TriMesh::invert_winding() - (JT)
+ * inverts the order of vertices (cw/ccw) as well as the normals
+ */
+void TriMesh::invert_winding() {
+       Triangle *tptr = tarray.get_mod_data();
+       int tcount = tarray.get_count();
+
+       for(int i=0; i<tcount; i++) {
+               Index tmp = tptr->vertices[1];
+               tptr->vertices[1] = tptr->vertices[2];
+               tptr->vertices[2] = tmp;
+               tptr->normal = -tptr->normal;
+               tptr++;
+       }
+
+       Vertex *vptr = varray.get_mod_data();
+       int vcount = varray.get_count();
+
+       for(int i=0; i<vcount; i++) {
+               vptr->normal = -vptr->normal;
+               vptr++;
+       }
+}
+
+
+void TriMesh::calculate_tangents() {
+       // precalculate which triangles index each vertex
+       std::vector<unsigned int> *tri_indices;
+       tri_indices = new std::vector<unsigned int>[varray.get_count()];
+
+       for(unsigned int i=0; i<tarray.get_count(); i++) {
+               for(int j=0; j<3; j++) {        
+                       tri_indices[tarray.get_data()[i].vertices[j]].push_back(i);
+               }
+       }
+
+       // calculate the triangle tangents
+       for(unsigned int i=0; i<tarray.get_count(); i++) {
+               tarray.get_mod_data()[i].calculate_tangent(varray.get_data(), false);
+       }
+       
+       // now calculate the vertex tangents
+       for(unsigned int i=0; i<varray.get_count(); i++) {
+               Vector3 tangent;
+               for(unsigned int j=0; j<(unsigned int)tri_indices[i].size(); j++) {
+                       tangent += tarray.get_data()[tri_indices[i][j]].tangent;
+               }
+               
+               // avoid division by zero
+               if(tri_indices[i].size()) {
+                       tangent.normalize();
+               }
+               varray.get_mod_data()[i].tangent = tangent;
+       }
+       
+       delete [] tri_indices;
+}
+
+void TriMesh::apply_xform(const Matrix4x4 &xform) {
+       Vertex *vptr = varray.get_mod_data();
+       unsigned long count = varray.get_count();
+
+       for(unsigned long i=0; i<count; i++) {
+               vptr->pos.transform(xform);
+               (vptr++)->normal.transform((Matrix3x3)xform);
+       }
+}
+
+void TriMesh::operator +=(const TriMesh *m2) {
+       join_tri_mesh(this, this, m2);
+}
+
+/* TriMesh::sort_triangles - (MG)
+ * sorts triangles according to their distance from a
+ * given point (in model space).
+ */
+void TriMesh::sort_triangles(Vector3 point, bool hilo)
+{
+       const Vertex *verts = get_vertex_array()->get_data();
+       unsigned int vcount = get_vertex_array()->get_count();
+       Triangle *tris = get_mod_triangle_array()->get_mod_data();
+       unsigned int tcount = get_triangle_array()->get_count();
+
+       // store square distance for each vertex
+       scalar_t *sq_distances = new scalar_t[vcount];
+
+       for (unsigned int i=0; i<vcount; i++)
+       {
+               sq_distances[i] = (verts[i].pos - point).length_sq();
+       }
+
+       // store sum of sq distances for each triangle
+       scalar_t *tri_distances = new scalar_t[tcount];
+
+       for (unsigned int i=0; i<tcount; i++)
+       {
+               tri_distances[i] = 0;
+               for (unsigned int j=0; j<3; j++)
+               {
+                       tri_distances[i] += sq_distances[tris[i].vertices[j]];
+               }
+       }
+
+       // sort
+       sort(tris, tri_distances, tcount, hilo);
+       
+       // cleanup
+       delete [] sq_distances;
+       delete [] tri_distances;
+}
+
+VertexStatistics TriMesh::get_vertex_stats() const {
+       if(!vertex_stats_valid) {
+               vstats.xmin = vstats.ymin = vstats.zmin = FLT_MAX;
+               vstats.xmax = vstats.ymax = vstats.zmax = -FLT_MAX;
+               
+               const Vertex *varray = get_vertex_array()->get_data();
+               int count = get_vertex_array()->get_count();
+
+               const Vertex *vptr = varray;
+               vstats.centroid = Vector3(0, 0, 0);
+               for(int i=0; i<count; i++) {
+                       Vector3 pos = (vptr++)->pos;
+                       vstats.centroid += pos;
+
+                       if(pos.x < vstats.xmin) vstats.xmin = pos.x;
+                       if(pos.y < vstats.ymin) vstats.ymin = pos.y;
+                       if(pos.z < vstats.zmin) vstats.zmin = pos.z;
+                       if(pos.x > vstats.xmax) vstats.xmax = pos.x;
+                       if(pos.y > vstats.ymax) vstats.ymax = pos.y;
+                       if(pos.z > vstats.zmax) vstats.zmax = pos.z;
+               }
+               vstats.centroid /= count;
+
+               scalar_t min_len_sq = FLT_MAX;
+               scalar_t max_len_sq = 0.0;
+               scalar_t avg_len_sq = 0.0;
+               
+               vptr = varray;
+               for(int i=0; i<count; i++) {
+                       scalar_t len_sq = ((vptr++)->pos - vstats.centroid).length_sq();
+                       if(len_sq < min_len_sq) min_len_sq = len_sq;
+                       if(len_sq > max_len_sq) max_len_sq = len_sq;
+                       avg_len_sq += len_sq;
+               }
+
+               vstats.min_dist = sqrt(min_len_sq);
+               vstats.max_dist = sqrt(max_len_sq);
+               vstats.avg_dist = sqrt(avg_len_sq / (scalar_t)count);
+               vertex_stats_valid = true;
+       }
+       return vstats;
+}
+
+/* get_contour_edges - (MG, JT)
+ * returns the contour edges relative to the given point of view or direction
+ * The edges are in clockwise order, so they can be used to create a shadow volume
+ * mesh by extruding them...
+ * NOTE: pov_or_dir should be given in model space
+ */
+std::vector<Edge> *TriMesh::get_contour_edges(const Vector3 &pov_or_dir, bool dir)
+{
+       static std::vector<Edge> cont_edges;
+       
+       // calculate triangle normals
+       if(!triangle_normals_valid) {
+               calculate_triangle_normals(false);
+       }
+       
+       const Vertex *va = get_vertex_array()->get_data();
+       unsigned long vc = get_vertex_array()->get_count();
+       const Triangle *ta = get_triangle_array()->get_data();
+       unsigned long tc = get_triangle_array()->get_count();
+       
+       vector<Edge> *vert_edge = new vector<Edge>[vc];
+       
+       Vector3 direction = pov_or_dir;
+       for(unsigned long i=0; i<tc; i++) {
+               if(!dir) {
+                       direction = va[ta[i].vertices[0]].pos - pov_or_dir;
+               }
+               
+               if(dot_product(ta[i].normal, direction) > 0) {
+                       for(int j=0; j<3; j++) {
+                               int v0idx = j;
+                               int v1idx = (j + 1) % 3;
+
+                               Index v0 = ta[i].vertices[v0idx];
+                               Index v1 = ta[i].vertices[v1idx];
+                               
+                               Edge edge(v1, v0);
+                               std::vector<Edge>::iterator iter = vert_edge[v0].begin();
+                               
+                               bool found = false;
+                               for(unsigned int k=0; k<vert_edge[v0].size(); k++, iter++) {
+                                       if(vert_edge[v0][k].vertices[1] == v1) {
+                                               vert_edge[v0].erase(iter);
+                                               found = true;
+                                               break;
+                                       }
+                               }
+
+                               if(!found) {
+                                       iter = vert_edge[v1].begin();
+                                       for(unsigned int k=0; k<vert_edge[v1].size(); k++, iter++) {
+                                               if(vert_edge[v1][k].vertices[0] == v0) {
+                                                       vert_edge[v1].erase(iter);
+                                                       found = true;
+                                                       break;
+                                               }
+                                       }
+                               }
+
+                               if(!found) vert_edge[v0].push_back(edge);
+                               
+                       }
+                       
+               }
+       }
+
+       cont_edges.clear();
+       for(unsigned int i=0; i<vc; i++) {
+               for(unsigned int j=0; j<vert_edge[i].size(); j++) {
+                       cont_edges.push_back(vert_edge[i][j]);
+               }
+       }
+
+       return &cont_edges;
+}
+
+/* get_uncapped_shadow_volume() - (MG)
+ * specify pov_or_dir in model space
+ * delete the returned mesh after using it
+ */
+const scalar_t infinity = 100000;
+TriMesh *TriMesh::get_shadow_volume(const Vector3 &pov_or_dir, bool dir)
+{
+       TriMesh *ret = new TriMesh;
+       
+       const Vertex *va = get_vertex_array()->get_data();
+       std::vector<Edge> *contour_edges = get_contour_edges(pov_or_dir, dir);
+
+       // calculate number of vertices and indices for the mesh
+       unsigned long num_quads = contour_edges->size();
+       unsigned long num_verts = num_quads * 4;
+       unsigned long num_tris = num_quads * 2;
+
+       // allocate memory
+       Vertex *verts = new Vertex[num_verts];
+       Triangle *tris = new Triangle[num_tris];
+
+       // add contour vertices
+       for (unsigned long i=0; i<num_quads; i++)
+       {
+               for (unsigned long j=0; j<2; j++)
+               {
+                       verts[2 * i + j].pos = va[(*contour_edges)[i].vertices[j]].pos;
+               }
+       }
+
+       // add extruded vertices
+       for (unsigned long i=0; i<num_verts/2; i++)
+       {
+               verts[i + num_verts/2].pos = extrude(verts[i].pos, infinity, pov_or_dir, dir);
+       }
+
+       // make triangles
+       for (unsigned long i=0; i<num_quads; i++)
+       {
+               Index p1, p2, ep1, ep2;
+               p1 = 2 * i;
+               p2 = 2 * i + 1;
+               ep1 = p1 + num_verts / 2;
+               ep2 = p2 + num_verts / 2;
+               tris[2*i] = Triangle(p1, ep1, ep2);
+               tris[2*i + 1] = Triangle(p1, ep2, p2);
+       }
+       
+       ret->set_data(verts, num_verts, tris, num_tris);
+       
+       // cleanup
+       delete [] verts;
+       delete [] tris;
+
+       return ret;
+}
+
+/* get_shadow_volume - (MG)
+ * returns a capped shadow volume.
+ * Only the front side is capped.
+ * Delete the returned TriMesh* when finished using it.
+ * TODO: implement back cap
+ */
+/*TriMesh *TriMesh::get_shadow_volume(const Vector3 &pov_or_dir, bool dir)
+{
+       TriMesh *uncapped = get_uncapped_shadow_volume(pov_or_dir, dir);
+       TriMesh *capped = join_tri_mesh(this, uncapped);
+       delete uncapped;
+       return capped;
+}*/
+
+/* class VertexOrder - (MG)
+ * used by this module only
+ */
+class VertexOrder
+{
+public:
+       Index   order;
+       Vertex  vertex;
+
+       // Constructor
+       VertexOrder()
+       {
+               order = 0;
+               vertex = Vertex();
+       }
+
+       VertexOrder(Index order, const Vertex& vertex)
+       {
+               this->order = order;
+               this->vertex = vertex;
+       }
+};
+
+// fwd declaration
+static std::vector<unsigned int> process_vo_array(VertexOrder *array, unsigned int size, unsigned int crit);
+
+void TriMesh::calculate_index_graph()
+{
+       Index *igraph = new Index[varray.get_count()];
+       for (unsigned int i=0; i<varray.get_count(); i++)
+       {
+               igraph[i] = i;
+       }
+               
+       VertexOrder *vo = new VertexOrder[varray.get_count()];
+       for (unsigned int i=0; i<varray.get_count(); i++)
+       {
+               vo[i] = VertexOrder(i, varray.get_data()[i]);
+       }
+
+       // sort by x, then by y , then by z, and return constant-z parts
+       std::vector<unsigned int> parts;
+       parts = process_vo_array(vo, varray.get_count(), 0);
+       
+       for (unsigned int i=0; i<parts.size(); i += 2)
+       {
+               // find min index of this part
+               Index min_index = vo[parts[i]].order;
+               for (unsigned int j=0; j<parts[i + 1]; j++)
+               {
+                       if(min_index > vo[parts[i] + j].order) {
+                               min_index = vo[parts[i] + j].order;
+                       }
+               }
+               
+               // replace index
+               for (unsigned int j=0; j<parts[i + 1]; j++)
+                       igraph[vo[parts[i] + j].order] = min_index;
+       }
+
+       index_graph.set_data(igraph, varray.get_count());
+       index_graph_valid = true;
+       
+       delete [] vo;
+       delete [] igraph;
+}
+
+/* join_tri_mesh - (MG)
+ * Gets 2 trimeshes and returns a new one
+ * that contains both meshes
+ */
+void join_tri_mesh(TriMesh *ret, const TriMesh *m1, const TriMesh *m2)
+{
+       const Vertex *varr1 = m1->get_vertex_array()->get_data();
+       const Vertex *varr2 = m2->get_vertex_array()->get_data();
+       
+       unsigned long vcount1 = m1->get_vertex_array()->get_count();
+       unsigned long vcount2 = m2->get_vertex_array()->get_count();
+
+       const Triangle *tarr1 = m1->get_triangle_array()->get_data();
+       const Triangle *tarr2 = m2->get_triangle_array()->get_data();
+
+       unsigned long tcount1 = m1->get_triangle_array()->get_count();
+       unsigned long tcount2 = m2->get_triangle_array()->get_count();
+
+       // allocate memory
+       int vcount = vcount1 + vcount2;
+       int tcount = tcount1 + tcount2;
+       Vertex *varray = new Vertex[vcount];
+       Triangle *tarray = new Triangle[tcount];
+
+       // copy memory
+       memcpy(varray, varr1, vcount1 * sizeof(Vertex));
+       memcpy(varray + vcount1, varr2, vcount2 * sizeof(Vertex));
+       memcpy(tarray, tarr1, tcount1 * sizeof(Triangle));
+       memcpy(tarray + tcount1, tarr2, tcount2 * sizeof(Triangle));
+
+       // Fix indices
+       for (unsigned long i = 0; i < tcount2; i++)
+       {
+               for (int j=0; j<3; j++)
+               {
+                       tarray[tcount1 + i].vertices[j] += vcount1;
+               }
+       }
+       
+       ret->set_data(varray, vcount, tarray, tcount);
+       
+       // cleanup
+       delete [] varray;
+       delete [] tarray;
+}
+
+/* Nicer join_tri_mesh - (JT)
+ * This is a much better way to do things.
+ */
+TriMesh *join_tri_mesh(const TriMesh *m1, const TriMesh *m2) {
+       TriMesh *mesh = new TriMesh;
+       join_tri_mesh(mesh, m1, m2);
+       return mesh;
+}
+
+/* extrude() - (MG)
+ * extrude a vertex given a point of view (or direction) to the specified
+ * distance
+ */
+Vector3 extrude(const Vector3 &vec, scalar_t distance, const Vector3 &pov_or_dir, bool dir) {
+       Vector3 direction;
+
+       if (dir) {
+               direction = pov_or_dir;
+       }
+       else {
+               direction = vec - pov_or_dir;
+       }
+
+       direction.normalize();
+       direction *= distance;
+
+       return vec + direction;
+}
+
+/* utilities for finding duplicate vertices - (MG)
+ */
+extern const scalar_t xsmall_number;
+
+// Sort criteria for VertexOrder objects
+static bool vo_sort_crit_x(const VertexOrder& a, const VertexOrder& b)
+{
+       return (a.vertex.pos.x < b.vertex.pos.x);
+}
+
+static bool vo_sort_crit_y(const VertexOrder& a, const VertexOrder& b)
+{
+       return (a.vertex.pos.y < b.vertex.pos.y);
+}
+
+static bool vo_sort_crit_z(const VertexOrder& a, const VertexOrder& b)
+{
+       return (a.vertex.pos.z < b.vertex.pos.z);
+}
+
+// equality criteria for VertexOrder objects
+static bool vo_eq_crit_x(const VertexOrder& a, const VertexOrder& b)
+{
+       return (b.vertex.pos.x - a.vertex.pos.x < xsmall_number);
+}
+
+static bool vo_eq_crit_y(const VertexOrder& a, const VertexOrder& b)
+{
+       return (b.vertex.pos.y - a.vertex.pos.y < xsmall_number);
+}
+
+static bool vo_eq_crit_z(const VertexOrder& a, const VertexOrder& b)
+{
+       return (b.vertex.pos.z - a.vertex.pos.z < xsmall_number);
+}
+
+static bool (* vo_sort_crit[])(const VertexOrder& a, const VertexOrder& b) = {vo_sort_crit_x, vo_sort_crit_y, vo_sort_crit_z};
+
+static bool (* vo_eq_crit[])(const VertexOrder& a, const VertexOrder& b) = {vo_eq_crit_x, vo_eq_crit_y, vo_eq_crit_z};
+
+static std::vector<unsigned int> vo_find_constant_parts(VertexOrder *array, unsigned int size, unsigned int crit)
+{
+       std::vector<unsigned int> parts;
+       if (crit > 2) return parts;
+
+       bool (* eq_crit)(const VertexOrder& a, const VertexOrder& b);
+       eq_crit = vo_eq_crit[crit];
+
+       unsigned int start=0;
+       for (unsigned int i=0; i<size; i++)
+       {
+               if (!eq_crit(array[start], array[i]))
+               {
+                       if (i - start > 1)
+                       {
+                               parts.push_back(start);
+                               parts.push_back(i - start);
+                       }
+
+                       start = i;
+               }
+       }
+
+       if (size - start > 1)
+       {
+               parts.push_back(start);
+               parts.push_back(size - start);
+       }
+
+       return parts;
+}
+
+static std::vector<unsigned int> process_vo_array(VertexOrder *array, unsigned int size, unsigned int crit)
+{
+       std::vector<unsigned int> r_parts;
+       if (crit > 2) return r_parts;
+               
+       bool (* sort_crit)(const VertexOrder& a, const VertexOrder& b);
+       sort_crit = vo_sort_crit[crit];
+
+       // sort array
+       std::sort(array, array + size, sort_crit);
+
+       // find constant parts
+       std::vector<unsigned int> parts;
+       parts = vo_find_constant_parts(array, size, crit);
+       
+       if (crit < 2)
+       {
+               for (unsigned int i=0; i<parts.size(); i += 2)
+               {
+                       std::vector<unsigned int> new_parts;
+                       new_parts = process_vo_array(array + parts[i], parts[i + 1], crit + 1);
+                       for (unsigned int j=0; j<new_parts.size(); j+=2)
+                       {
+                               r_parts.push_back(new_parts[j] + parts[i]);
+                               r_parts.push_back(new_parts[j+1]);
+                       }
+               }
+               return r_parts;
+       }
+       else
+       {
+               // found constant z parts. just return them
+               return parts;
+       }
+}
diff --git a/src/3dengfx/src/gfx/3dgeom.hpp b/src/3dengfx/src/gfx/3dgeom.hpp
new file mode 100644 (file)
index 0000000..3e1a46a
--- /dev/null
@@ -0,0 +1,254 @@
+/*
+This file is part of the 3dengfx, realtime visualization system.
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* fundamendal data structures for 3D graphics
+ *
+ * Author: John Tsiombikas 2004
+ * Modified: 
+ *             Mihalis Georgoulopoulos 2004
+ *             John Tsiombikas 2005
+ */
+
+// JT: seperated animation classes and placed them in animation.hpp/cpp - 2/2005
+
+#ifndef _3DGEOM_HPP_
+#define _3DGEOM_HPP_
+
+#include "3dengfx_config.h"
+
+#include "n3dmath2/n3dmath2.hpp"
+#include "color.hpp"
+
+#include <iostream>
+#include <vector>
+
+typedef uint32_t Index;
+
+struct TexCoord {
+       scalar_t u, v, w;       // or s,t,v if you prefer... I like u,v,w more though.
+
+       TexCoord(scalar_t u = 0.0f, scalar_t v = 0.0f, scalar_t w = 0.0f);
+};
+
+class Triangle;        // fwd declaration
+
+class Vertex {
+public:
+       Vector3 pos;
+       Vector3 normal;
+       Vector3 tangent;
+       Color color;
+       TexCoord tex[2];
+
+       Vertex();
+       Vertex(const Vector3 &position, scalar_t tu = 0.0f, scalar_t tv = 0.0f, const Color &color = Color(1.0f, 1.0f, 1.0f));
+};
+
+#define NO_ADJFACE 0xFFFFFFFF
+
+class Edge {
+public:
+       Index vertices[2];
+       Index adjfaces[2];
+
+       Edge();
+       Edge(Index v1, Index v2, Index af1 = NO_ADJFACE, Index af2 = NO_ADJFACE);
+};
+
+std::ostream &operator <<(std::ostream &o, const Edge &e);
+
+
+class Triangle {
+public:
+       Index vertices[3];
+       Vector3 normal;
+       Vector3 tangent;
+       unsigned int smoothing_group;
+
+       Triangle(Index v1 = 0, Index v2 = 0, Index v3 = 0);
+
+       void calculate_normal(const Vertex *vbuffer, bool normalize=false);
+       void calculate_tangent(const Vertex *vbuffer, bool normalize=false);
+};
+
+std::ostream &operator <<(std::ostream &o, const Triangle &t);
+
+
+
+class Quad {
+public:
+       Index vertices[4];
+       Vector3 normal;
+       unsigned int smoothing_group;
+
+       Quad(Index v1 = 0, Index v2 = 0, Index v3 = 0, Index v4 = 0);
+
+       void calculate_normal(const Vertex *vbuffer, bool normalize=0);
+};
+
+
+//////////////// Geometry Arrays //////////////
+template <class DataType>
+class GeometryArray {
+private:
+       DataType *data;
+       unsigned long count;
+       bool dynamic;
+       unsigned int buffer_object;             // for OGL VBOs
+       bool vbo_in_sync;
+
+       void sync_buffer_object();
+
+public:
+       GeometryArray(bool dynamic = true);
+       GeometryArray(const DataType *data, unsigned long count, bool dynamic = true);
+       GeometryArray(const GeometryArray &ga);
+       ~GeometryArray();
+
+       GeometryArray &operator =(const GeometryArray &ga);
+
+       inline void set_data(const DataType *data, unsigned long count);
+       inline const DataType *get_data() const;
+       inline DataType *get_mod_data();
+
+       inline unsigned long get_count() const;
+
+       inline void set_dynamic(bool enable);
+       inline bool get_dynamic() const;
+       
+       inline unsigned int get_buffer_object() const;
+};
+
+
+// specialization of template class GeometryArray for type Index
+template <>
+class GeometryArray<Index> {
+private:
+       Index *data;
+       unsigned long count;
+       bool dynamic;
+       unsigned int buffer_object;
+       bool vbo_in_sync;
+
+       void sync_buffer_object();
+
+public:
+       GeometryArray(bool dynamic = true);
+       GeometryArray(const Index *data, unsigned long count, bool dynamic = true);
+       GeometryArray(const GeometryArray<Triangle> &tarray);   // conversion from triangle data
+       GeometryArray(const GeometryArray &ga);
+       ~GeometryArray();
+
+       GeometryArray &operator =(const GeometryArray &ga);
+
+       void set_data(const Index *data, unsigned long count);
+       inline const Index *get_data() const;
+       inline Index *get_mod_data();
+
+       inline unsigned long get_count() const;
+
+       inline void set_dynamic(bool enable);
+       inline bool get_dynamic() const;
+
+       inline unsigned int get_buffer_object() const;
+       
+       friend void tri_to_index_array(GeometryArray<Index> *ia, const GeometryArray<Triangle> &ta);
+};
+
+typedef GeometryArray<Vertex> VertexArray;
+typedef GeometryArray<Triangle> TriangleArray;
+typedef GeometryArray<Index> IndexArray;
+
+////////////// triangle mesh class ////////////
+struct VertexStatistics {
+       Vector3 centroid;
+       scalar_t min_dist;
+       scalar_t max_dist;
+       scalar_t avg_dist;
+       scalar_t xmin, xmax, ymin, ymax, zmin, zmax;
+};
+
+class TriMesh {
+private:
+       VertexArray varray;
+       TriangleArray tarray;
+       IndexArray iarray;
+       IndexArray index_graph;
+       
+       GeometryArray<Edge> earray;
+
+       mutable VertexStatistics vstats;
+       
+       mutable bool vertex_stats_valid;
+       bool indices_valid;
+       bool edges_valid;
+       bool index_graph_valid;
+       bool triangle_normals_valid;
+       bool triangle_normals_normalized;
+       
+       void calculate_edges();
+       void calculate_index_graph();
+       void calculate_triangle_normals(bool normalize);
+       
+public:
+       TriMesh();
+       TriMesh(const Vertex *vdata, unsigned long vcount, const Triangle *tdata, unsigned long tcount);
+       
+       inline const VertexArray *get_vertex_array() const;
+       inline VertexArray *get_mod_vertex_array();
+       
+       inline const TriangleArray *get_triangle_array() const;
+       inline TriangleArray *get_mod_triangle_array();
+       
+       const IndexArray *get_index_array();
+       const GeometryArray<Edge> *get_edge_array() const;
+       
+       void set_data(const Vertex *vdata, unsigned long vcount, const Triangle *tdata, unsigned long tcount);  
+
+       void calculate_normals_by_index();
+       void calculate_normals();
+       void normalize_normals();
+       void invert_winding();
+
+       void calculate_tangents();
+
+       void apply_xform(const Matrix4x4 &xform);
+
+       void operator +=(const TriMesh *m2);
+
+       void sort_triangles(Vector3 point, bool hilo=true);
+       
+       VertexStatistics get_vertex_stats() const;
+
+       // shadow volumes
+       std::vector<Edge> *get_contour_edges(const Vector3 &pov_or_dir, bool dir = false);
+       //TriMesh *get_uncapped_shadow_volume(const Vector3 &pov_or_dir, bool dir = false);
+       TriMesh *get_shadow_volume(const Vector3 &pov_or_dir, bool dir = false);
+};
+
+
+/* utility functions
+ */
+void join_tri_mesh(TriMesh *ret, const TriMesh *m1, const TriMesh *m2);
+TriMesh *join_tri_mesh(const TriMesh *m1, const TriMesh *m2);
+Vector3 extrude(const Vector3 &vec, scalar_t distance, const Vector3 &pov_or_dir, bool dir);
+
+#include "3dgeom.inl"
+
+#endif // _3DGEOM_HPP_
diff --git a/src/3dengfx/src/gfx/3dgeom.inl b/src/3dengfx/src/gfx/3dgeom.inl
new file mode 100644 (file)
index 0000000..fd55b62
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+This file is part of the graphics core library.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* fundamendal data structures for 3D graphics (inline definitions and templates)
+ *
+ * Author: John Tsiombikas 2004
+ * Modified: 
+ *             Mihalis Georgoulopoulos 2004
+ *             John Tsiombikas 2005
+ */
+
+#include <iostream>
+#include <cstring>
+
+#ifdef USING_3DENGFX
+#include "3dengfx/3denginefx_types.hpp"
+
+SysCaps get_system_capabilities();
+#endif // USING_3DENGFX
+
+#define INVALID_VBO            0
+
+template <class DataType>
+GeometryArray<DataType>::GeometryArray(bool dynamic) {
+       data = 0;
+       count = 0;
+       buffer_object = INVALID_VBO;
+       vbo_in_sync = false;
+
+       set_dynamic(dynamic);
+}
+
+template <class DataType>
+GeometryArray<DataType>::GeometryArray(const DataType *data, unsigned long count, bool dynamic) {
+       this->data = 0;
+       this->count = 0;
+       buffer_object = INVALID_VBO;
+       set_dynamic(dynamic);
+
+       set_data(data, count);
+}
+
+template <class DataType>
+GeometryArray<DataType>::GeometryArray(const GeometryArray<DataType> &ga) {
+       data = 0;
+       count = 0;
+       dynamic = ga.dynamic;
+       buffer_object = INVALID_VBO;
+
+       set_data(ga.data, ga.count);
+}
+
+template <class DataType>
+GeometryArray<DataType>::~GeometryArray() {
+       if(data) delete [] data;
+#ifdef USING_3DENGFX
+       if(buffer_object != INVALID_VBO) {
+               glext::glDeleteBuffers(1, &buffer_object);
+       }
+#endif // USING_3DENGFX
+}
+
+template <class DataType>
+GeometryArray<DataType> &GeometryArray<DataType>::operator =(const GeometryArray<DataType> &ga) {
+       dynamic = ga.dynamic;
+       if(data) delete [] data;
+
+       set_data(ga.data, ga.count);
+       
+       return *this;
+}
+
+template <class DataType>
+void GeometryArray<DataType>::sync_buffer_object() {
+#ifdef USING_3DENGFX
+       if(dynamic) return;
+
+       if(buffer_object == INVALID_VBO) {
+               glext::glGenBuffers(1, &buffer_object);
+               glext::glBindBuffer(GL_ARRAY_BUFFER_ARB, buffer_object);
+               glext::glBufferData(GL_ARRAY_BUFFER_ARB, count * sizeof(DataType), data, GL_STATIC_DRAW_ARB);
+               glext::glBindBuffer(GL_ARRAY_BUFFER_ARB, 0);
+       } else {
+
+               while(glGetError() != GL_NO_ERROR);
+               glext::glBindBuffer(GL_ARRAY_BUFFER_ARB, buffer_object);
+
+               glext::glBufferData(GL_ARRAY_BUFFER_ARB, count * sizeof(DataType), data, GL_STATIC_DRAW_ARB);
+               glext::glBindBuffer(GL_ARRAY_BUFFER_ARB, 0);
+       }
+#endif // USING_3DENGFX
+       vbo_in_sync = true;
+}
+
+
+template <class DataType>
+inline void GeometryArray<DataType>::set_data(const DataType *data, unsigned long count) {
+       if(!data) return;
+       if(!this->data || count != this->count) {
+               if(this->data) {
+                       delete [] this->data;
+               }
+               this->data = new DataType[count];
+       }
+       
+       memcpy(this->data, data, count * sizeof(DataType));
+       this->count = count;
+
+#ifdef USING_3DENGFX
+       if(!dynamic) {
+               if(buffer_object != INVALID_VBO && count != this->count) {
+                       glext::glDeleteBuffers(1, &buffer_object);
+               }
+               sync_buffer_object();
+               vbo_in_sync = true;
+       }
+#endif // USING_3DENGFX
+}
+
+template <class DataType>
+inline const DataType *GeometryArray<DataType>::get_data() const {
+       return data;
+}
+
+template <class DataType>
+inline DataType *GeometryArray<DataType>::get_mod_data() {
+       vbo_in_sync = false;
+       return data;
+}
+
+template <class DataType>
+inline unsigned long GeometryArray<DataType>::get_count() const {
+       return count;
+}
+
+template <class DataType>
+void GeometryArray<DataType>::set_dynamic(bool enable) {
+#ifdef USING_3DENGFX
+       SysCaps sys_caps = get_system_capabilities();
+       dynamic = enable;
+
+       if(!dynamic && !sys_caps.vertex_buffers) {
+               dynamic = true;
+       }
+#else
+       dynamic = false;
+#endif // USING_3DENGFX
+}
+
+template <class DataType>
+inline bool GeometryArray<DataType>::get_dynamic() const {
+       return dynamic;
+}
+
+template <class DataType>
+inline unsigned int GeometryArray<DataType>::get_buffer_object() const {
+       if(!dynamic && !vbo_in_sync) {
+               const_cast<GeometryArray<DataType>*>(this)->sync_buffer_object();
+       }
+               
+       return buffer_object;
+}
+
+// inline functions of <index> specialization of GeometryArray
+
+inline const Index *GeometryArray<Index>::get_data() const {
+       return data;
+}
+
+inline Index *GeometryArray<Index>::get_mod_data() {
+       vbo_in_sync = false;
+       return data;
+}
+
+inline unsigned long GeometryArray<Index>::get_count() const {
+       return count;
+}
+
+inline void GeometryArray<Index>::set_dynamic(bool enable) {
+#ifdef USING_3DENGFX
+       SysCaps sys_caps = get_system_capabilities();
+       dynamic = enable;
+
+       if(!dynamic && !sys_caps.vertex_buffers) {
+               dynamic = true;
+       }
+#else
+       dynamic = false;
+#endif // USING_3DENGFX
+}
+
+inline bool GeometryArray<Index>::get_dynamic() const {
+       return dynamic;
+}
+
+inline unsigned int GeometryArray<Index>::get_buffer_object() const {
+       if(!dynamic && !vbo_in_sync) {
+               const_cast<GeometryArray<Index>*>(this)->sync_buffer_object();
+       }
+
+       return buffer_object;
+}
+
+
+///////// Triangle Mesh Implementation (inline functions) //////////
+inline const VertexArray *TriMesh::get_vertex_array() const {
+       return &varray;
+}
+
+inline VertexArray *TriMesh::get_mod_vertex_array() {
+       vertex_stats_valid = false;
+       edges_valid = false;
+       index_graph_valid = false;
+       triangle_normals_valid = triangle_normals_normalized = false;
+       return &varray;
+}
+
+inline const TriangleArray *TriMesh::get_triangle_array() const {
+       return &tarray;
+}
+
+inline TriangleArray *TriMesh::get_mod_triangle_array() {
+       indices_valid = false;
+       edges_valid = false;
+       index_graph_valid = false;
+       triangle_normals_valid = triangle_normals_normalized = false;
+       return &tarray;
+}
diff --git a/src/3dengfx/src/gfx/animation.cpp b/src/3dengfx/src/gfx/animation.cpp
new file mode 100644 (file)
index 0000000..20d3a46
--- /dev/null
@@ -0,0 +1,480 @@
+/*
+This file is part of the graphics core library.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* fundamental animation system (initally part of 3dgeom.cpp)
+ *
+ * Author: John Tsiombikas 2004
+ * Modified:
+ *             John Tsiombikas 2005
+ */
+
+#include "3dengfx_config.h"
+
+#include <algorithm>
+#include "animation.hpp"
+
+using std::vector;
+
+
+///////////////// PRS /////////////////////
+
+PRS::PRS() {
+       scale = Vector3(1, 1, 1);
+}
+
+PRS::PRS(const Vector3 &pos, const Quaternion &rot, const Vector3 &scale, const Vector3 &pivot) {
+       position = pos;
+       rotation = rot;
+       this->scale = scale;
+       this->pivot = pivot;
+}
+
+Matrix4x4 PRS::get_xform_matrix() const {
+       Matrix4x4 trans_mat, rot_mat, scale_mat, pivot_mat, neg_pivot_mat;
+
+       pivot_mat.set_translation(pivot);
+       neg_pivot_mat.set_translation(-pivot);
+       
+       trans_mat.set_translation(position);
+       rot_mat = (Matrix4x4)rotation.get_rotation_matrix();
+       scale_mat.set_scaling(scale);
+       
+       return pivot_mat * trans_mat * rot_mat * scale_mat * neg_pivot_mat;
+}
+
+PRS combine_prs(const PRS &prs1, const PRS &prs2) {
+       PRS prs;
+
+       prs.position = prs1.position + prs2.position;
+       prs.rotation = prs2.rotation * prs1.rotation;
+       prs.scale.x = prs1.scale.x * prs2.scale.x;
+       prs.scale.y = prs1.scale.y * prs2.scale.y;
+       prs.scale.z = prs1.scale.z * prs2.scale.z;
+       prs.pivot = prs1.pivot;
+
+       return prs;
+}
+
+PRS inherit_prs(const PRS &child, const PRS &parent) {
+       PRS prs;
+       prs.pivot = child.pivot;
+       
+       prs.rotation = parent.rotation * child.rotation;
+
+       prs.position += child.position;
+       prs.position -= parent.position;
+       prs.position.transform(parent.rotation.conjugate());
+       prs.position += parent.position;
+
+       Vector3 ppos_trans = parent.position.transformed(parent.rotation.conjugate());
+       prs.position += ppos_trans;
+       
+       prs.position.x *= parent.scale.x;
+       prs.position.y *= parent.scale.y;
+       prs.position.z *= parent.scale.z;
+
+       prs.scale.x = child.scale.x * parent.scale.x;
+       prs.scale.y = child.scale.y * parent.scale.y;
+       prs.scale.z = child.scale.z * parent.scale.z;
+
+       return prs;
+}
+
+std::ostream &operator <<(std::ostream &out, const PRS &prs) {
+       out << "p: " << prs.position << " r: " << prs.rotation << " s: " << prs.scale;
+       return out;
+}
+
+//////////////// Keyframe /////////////////
+
+Keyframe::Keyframe(const PRS &prs, unsigned long time) {
+       this->prs = prs;
+       this->time = time;
+}
+
+
+////////////// XFormNode ///////////////
+XFormNode::XFormNode() {
+       key_count = 0;
+       use_ctrl = 0;
+       key_time_mode = TIME_CLAMP;
+       parent = 0;
+       cache.valid = false;
+}
+
+XFormNode::~XFormNode() {
+}
+
+Keyframe *XFormNode::get_nearest_key(int start, int end, unsigned long time) {
+       if(start == end) return &keys[start];
+       if(end - start == 1) {
+               return abs((int)(time - keys[start].time)) < abs((int)(keys[end].time - time)) ? &keys[start] : &keys[end];
+       }
+
+       int mid = (start + end) / 2;
+       if(time < keys[mid].time) return get_nearest_key(start, mid, time);
+       if(time > keys[mid].time) return get_nearest_key(mid + 1, end, time);
+       return &keys[mid];
+}
+
+void XFormNode::get_key_interval(unsigned long time, const Keyframe **start, const Keyframe **end) const {
+       const Keyframe *nearest = get_nearest_key(time);
+
+       *start = nearest;
+       *end = 0;
+       
+       if(time < nearest->time && nearest->time != keys[0].time) {
+               *start = nearest - 1;
+               *end = nearest;
+       } else if(time > nearest->time && nearest->time != keys[key_count - 1].time) {
+               *start = nearest;
+               *end = nearest + 1;
+       }
+}
+
+void XFormNode::add_controller(MotionController ctrl, ControllerType ctrl_type) {
+       switch(ctrl_type) {
+       case CTRL_TRANSLATION:
+               trans_ctrl.push_back(ctrl);
+               break;
+               
+       case CTRL_ROTATION:
+               rot_ctrl.push_back(ctrl);
+               break;
+               
+       case CTRL_SCALING:
+               scale_ctrl.push_back(ctrl);
+               break;
+       }
+       use_ctrl = true;
+       cache.valid = false;
+}
+
+vector<MotionController> *XFormNode::get_controllers(ControllerType ctrl_type) {
+       switch(ctrl_type) {
+       case CTRL_TRANSLATION:
+               return &trans_ctrl;
+               break;
+               
+       case CTRL_ROTATION:
+               return &rot_ctrl;
+               break;
+               
+       default:        // just to make sure at least one of them is returned
+       case CTRL_SCALING:
+               return &scale_ctrl;
+               break;
+       }
+       cache.valid = false;
+}
+
+void XFormNode::add_keyframe(const Keyframe &key) {
+       if(!keys.empty()) {
+               Keyframe *keyframe = get_nearest_key(key.time);
+       
+               if(keyframe->time == key.time) {
+                       keyframe->prs = key.prs;
+               } else {
+                       key_count++;
+                       keys.push_back(key);
+                       sort(keys.begin(), keys.end());
+               }
+       } else {
+               keys.push_back(key);
+               key_count++;
+       }
+       cache.valid = false;
+}
+
+Keyframe *XFormNode::get_keyframe(unsigned long time) {
+       cache.valid = false;
+       Keyframe *keyframe = get_nearest_key(time);
+       return (keyframe->time == time) ? keyframe : 0;
+}
+
+void XFormNode::delete_keyframe(unsigned long time) {
+       vector<Keyframe>::iterator iter = find(keys.begin(), keys.end(), Keyframe(PRS(), time));
+       if(iter != keys.end()) {
+               keys.erase(iter);
+       }
+       cache.valid = false;
+}
+
+std::vector<Keyframe> *XFormNode::get_keyframes() {
+       cache.valid = false;
+       return &keys;
+}
+
+void XFormNode::set_timeline_mode(TimelineMode time_mode) {
+       key_time_mode = time_mode;
+       cache.valid = false;
+}
+
+void XFormNode::set_position(const Vector3 &pos, unsigned long time) {
+       if(time == XFORM_LOCAL_PRS) {
+               local_prs.position = pos;
+       } else {
+               Keyframe *keyframe = get_nearest_key(time);
+               if(keyframe && keyframe->time == time) {
+                       keyframe->prs.position = pos;
+               }
+       }
+       cache.valid = false;
+}
+
+void XFormNode::set_rotation(const Quaternion &rot, unsigned long time) {
+       if(time == XFORM_LOCAL_PRS) {
+               local_prs.rotation = rot;
+       } else {
+               Keyframe *keyframe = get_nearest_key(time);
+               if(keyframe && keyframe->time == time) {
+                       keyframe->prs.rotation = rot;
+               }
+       }
+       cache.valid = false;
+}
+
+void XFormNode::set_rotation(const Vector3 &euler, unsigned long time) {
+       
+       Quaternion xrot, yrot, zrot;
+       xrot.set_rotation(Vector3(1, 0, 0), euler.x);
+       yrot.set_rotation(Vector3(0, 1, 0), euler.y);
+       zrot.set_rotation(Vector3(0, 0, 1), euler.z);
+       
+       if(time == XFORM_LOCAL_PRS) {           
+               local_prs.rotation = xrot * yrot * zrot;
+       } else {
+               Keyframe *keyframe = get_nearest_key(time);
+               if(keyframe && keyframe->time == time) {
+                       keyframe->prs.rotation = xrot * yrot * zrot;
+               }
+       }
+       cache.valid = false;
+}
+
+void XFormNode::set_scaling(const Vector3 &scale, unsigned long time) {
+       if(time == XFORM_LOCAL_PRS) {
+               local_prs.scale = scale;
+       } else {
+               Keyframe *keyframe = get_nearest_key(time);
+               if(keyframe && keyframe->time == time) {
+                       keyframe->prs.scale = scale;
+               }
+       }
+       cache.valid = false;
+}
+
+void XFormNode::set_pivot(const Vector3 &pivot) {
+       local_prs.pivot = pivot;
+       cache.valid = false;
+}
+
+
+Vector3 XFormNode::get_position(unsigned long time) const {
+       return get_prs(time).position;
+}
+
+Quaternion XFormNode::get_rotation(unsigned long time) const {
+       return get_prs(time).rotation;
+}
+
+Vector3 XFormNode::get_scaling(unsigned long time) const {
+       return get_prs(time).scale;
+}
+
+Vector3 XFormNode::get_pivot() const {
+       return local_prs.pivot;
+}
+
+
+void XFormNode::translate(const Vector3 &trans, unsigned long time) {
+       if(time == XFORM_LOCAL_PRS) {
+               local_prs.position += trans;
+       } else {
+               Keyframe *keyframe = get_nearest_key(time);
+               if(keyframe && keyframe->time == time) {
+                       keyframe->prs.position += trans;
+               }
+       }
+       cache.valid = false;
+}
+
+void XFormNode::rotate(const Quaternion &rot, unsigned long time) {
+       if(time == XFORM_LOCAL_PRS) {
+               local_prs.rotation = rot * local_prs.rotation;
+       } else {
+               Keyframe *keyframe = get_nearest_key(time);
+               if(keyframe && keyframe->time == time) {
+                       keyframe->prs.rotation = rot * keyframe->prs.rotation;
+               }
+       }
+       cache.valid = false;
+}
+
+void XFormNode::rotate(const Vector3 &euler, unsigned long time) {
+       
+       Quaternion xrot, yrot, zrot;
+       xrot.set_rotation(Vector3(1, 0, 0), euler.x);
+       yrot.set_rotation(Vector3(0, 1, 0), euler.y);
+       zrot.set_rotation(Vector3(0, 0, 1), euler.z);
+       
+       if(time == XFORM_LOCAL_PRS) {           
+               local_prs.rotation = xrot * yrot * zrot * local_prs.rotation;
+       } else {
+               Keyframe *keyframe = get_nearest_key(time);
+               if(keyframe && keyframe->time == time) {
+                       keyframe->prs.rotation = xrot * yrot * zrot * keyframe->prs.rotation;
+               }
+       }
+       cache.valid = false;
+}
+
+void XFormNode::rotate(const Matrix3x3 &rmat, unsigned long time) {
+       // hack a matrix to quat conversion (this should go into the math lib)
+       Quaternion q;
+       q.s = sqrt(rmat[0][0] + rmat[1][1] + rmat[2][2] + 1.0) / 2.0;
+       scalar_t ssq = q.s * q.s;
+       q.v.x = sqrt((rmat[0][0] + 1.0 - 2.0 * ssq) / 2.0);
+       q.v.y = sqrt((rmat[1][1] + 1.0 - 2.0 * ssq) / 2.0);
+       q.v.z = sqrt((rmat[2][2] + 1.0 - 2.0 * ssq) / 2.0);
+
+       rotate(q, time);
+       cache.valid = false;
+}
+
+void XFormNode::scale(const Vector3 &scale, unsigned long time) {
+       if(time == XFORM_LOCAL_PRS) {
+               local_prs.scale.x *= scale.x;
+               local_prs.scale.y *= scale.y;
+               local_prs.scale.z *= scale.z;
+       } else {
+               Keyframe *keyframe = get_nearest_key(time);
+               if(keyframe && keyframe->time == time) {
+                       keyframe->prs.scale.x *= scale.x;
+                       keyframe->prs.scale.y *= scale.y;
+                       keyframe->prs.scale.z *= scale.z;
+               }
+       }
+       cache.valid = false;
+}
+
+
+void XFormNode::reset_position(unsigned long time) {
+       set_position(Vector3(0, 0, 0), time);
+       cache.valid = false;
+}
+
+void XFormNode::reset_rotation(unsigned long time) {
+       set_rotation(Quaternion(), time);
+       cache.valid = false;
+}
+
+void XFormNode::reset_scaling(unsigned long time) {
+       set_scaling(Vector3(1, 1, 1), time);
+       cache.valid = false;
+}
+
+void XFormNode::reset_xform(unsigned long time) {
+       reset_position(time);
+       reset_rotation(time);
+       reset_scaling(time);
+}
+
+#define MIN(a, b)      ((a) < (b) ? (a) : (b))
+#define MAX(a, b)      ((a) > (b) ? (a) : (b))
+
+PRS XFormNode::get_prs(unsigned long time) const {
+       /*if(cache.valid && time == cache.time) {
+               return cache.prs;
+       }
+       */
+       cache.valid = true;
+       cache.time = time;
+
+       PRS parent_prs;
+       if(parent) {
+               parent_prs = parent->get_prs(time);
+       }
+       
+       if(time == XFORM_LOCAL_PRS) {
+               cache.prs = combine_prs(local_prs, parent_prs);
+               return cache.prs;
+       }
+       
+       PRS prs = local_prs;
+
+       // apply keyframes
+       if(key_count) {
+               unsigned long ktime = get_timeline_time(time, keys[0].time, keys[key_count-1].time, key_time_mode);
+               
+               const Keyframe *start, *end;
+               get_key_interval(ktime, &start, &end);
+
+               PRS key_prs;
+       
+               if(end) {
+                       // find the parametric location of the given keyframe in the range we have
+                       scalar_t t = (scalar_t)(ktime - start->time) / (scalar_t)(end->time - start->time);
+       
+                       key_prs.position = start->prs.position + (end->prs.position - start->prs.position) * t;
+                       key_prs.scale = start->prs.scale + (end->prs.scale - start->prs.scale) * t;
+                       key_prs.rotation = slerp(start->prs.rotation, end->prs.rotation, t);
+               } else {
+                       key_prs = start->prs;
+               }
+
+               prs = combine_prs(prs, key_prs);
+       }
+       
+       // now let's also apply the controllers, if any
+       if(use_ctrl) {
+               PRS ctrl_prs;
+               
+               int count = trans_ctrl.size();
+               for(int i=0; i<count; i++) {
+                       ctrl_prs.position += trans_ctrl[i](time);
+               }
+               
+               count = rot_ctrl.size();
+               for(int i=0; i<count; i++) {
+                       Quaternion xrot, yrot, zrot;
+                       Vector3 euler = rot_ctrl[i](time);
+                       
+                       xrot.set_rotation(Vector3(1, 0, 0), euler.x);
+                       yrot.set_rotation(Vector3(0, 1, 0), euler.y);
+                       zrot.set_rotation(Vector3(0, 0, 1), euler.z);
+                       
+                       ctrl_prs.rotation = xrot * yrot * zrot * ctrl_prs.rotation;
+               }
+               
+               count = scale_ctrl.size();
+               for(int i=0; i<count; i++) {
+                       Vector3 scale = scale_ctrl[i](time);
+                       ctrl_prs.scale.x *= scale.x;
+                       ctrl_prs.scale.y *= scale.y;
+                       ctrl_prs.scale.z *= scale.z;
+               }
+
+               prs = combine_prs(prs, ctrl_prs);
+       }
+       
+       cache.prs = inherit_prs(prs, parent_prs);
+       return cache.prs;
+}
diff --git a/src/3dengfx/src/gfx/animation.hpp b/src/3dengfx/src/gfx/animation.hpp
new file mode 100644 (file)
index 0000000..a7cdb39
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+This file is part of the graphics core library.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* fundamental animation system (initally part of 3dgeom.hpp)
+ *
+ * Author: John Tsiombikas 2004
+ * Modified:
+ *             John Tsiombikas 2005
+ */
+
+#ifndef _ANIMATION_HPP_
+#define _ANIMATION_HPP_
+
+#include "3dengfx_config.h"
+
+#include <iostream>
+#include <vector>
+#include "n3dmath2/n3dmath2.hpp"
+#include "controller.hpp"
+#include "timeline.hpp"
+
+class PRS {
+public:
+       Vector3 position;
+       Quaternion rotation;
+       Vector3 scale;
+       Vector3 pivot;
+       
+       PRS();
+       PRS(const Vector3 &pos, const Quaternion &rot, const Vector3 &scale = Vector3(1,1,1), const Vector3 &pivot = Vector3(0,0,0));
+       
+       Matrix4x4 get_xform_matrix() const;
+
+       friend PRS combine_prs(const PRS &prs1, const PRS &prs2);
+       friend std::ostream &operator <<(std::ostream &out, const PRS &prs);
+};
+
+PRS combine_prs(const PRS &prs1, const PRS &prs2);
+PRS inherit_prs(const PRS &child, const PRS &parent);
+std::ostream &operator <<(std::ostream &out, const PRS &prs);
+
+class Keyframe {
+public:
+       PRS prs;
+       unsigned long time;
+       
+       Keyframe(const PRS &prs, unsigned long time);
+       
+       inline bool operator ==(const Keyframe &key) const;
+       inline bool operator <(const Keyframe &key) const;
+};
+
+
+enum ControllerType {CTRL_TRANSLATION, CTRL_ROTATION, CTRL_SCALING};
+#define XFORM_LOCAL_PRS                0xffffffff
+
+//////////// Transformable Node Base class /////////////
+class XFormNode {
+protected:
+       PRS local_prs;
+
+       // PRS cache
+       mutable struct {
+               PRS prs;
+               unsigned long time;
+               bool valid;
+       } cache;
+
+       int key_count;
+       std::vector<Keyframe> keys;
+       std::vector<MotionController> trans_ctrl, rot_ctrl, scale_ctrl;
+
+       TimelineMode key_time_mode;
+       
+       bool use_ctrl;
+
+       inline Keyframe *get_nearest_key(unsigned long time);
+       inline const Keyframe *get_nearest_key(unsigned long time) const;
+       Keyframe *get_nearest_key(int start, int end, unsigned long time);
+       inline const Keyframe *get_nearest_key(int start, int end, unsigned long time) const;
+       void get_key_interval(unsigned long time, const Keyframe **start, const Keyframe **end) const;
+       
+public:
+       std::string name;
+       XFormNode *parent;
+       std::vector<XFormNode*> children;
+       
+       XFormNode();
+       virtual ~XFormNode();
+
+       virtual void add_controller(MotionController ctrl, ControllerType ctrl_type);
+       virtual std::vector<MotionController> *get_controllers(ControllerType ctrl_type);
+               
+       virtual void add_keyframe(const Keyframe &key);
+       virtual Keyframe *get_keyframe(unsigned long time);
+       virtual void delete_keyframe(unsigned long time);
+       virtual std::vector<Keyframe> *get_keyframes();
+
+       virtual void set_timeline_mode(TimelineMode time_mode);
+       
+       virtual void set_position(const Vector3 &pos, unsigned long time = XFORM_LOCAL_PRS);
+       virtual void set_rotation(const Quaternion &rot, unsigned long time = XFORM_LOCAL_PRS);
+       virtual void set_rotation(const Vector3 &euler, unsigned long time = XFORM_LOCAL_PRS);
+       virtual void set_scaling(const Vector3 &scale, unsigned long time = XFORM_LOCAL_PRS);
+       virtual void set_pivot(const Vector3 &pivot);
+       
+       virtual Vector3 get_position(unsigned long time = XFORM_LOCAL_PRS) const;
+       virtual Quaternion get_rotation(unsigned long time = XFORM_LOCAL_PRS) const;
+       virtual Vector3 get_scaling(unsigned long time = XFORM_LOCAL_PRS) const;
+       virtual Vector3 get_pivot() const;
+       
+       virtual void translate(const Vector3 &trans, unsigned long time = XFORM_LOCAL_PRS);
+       virtual void rotate(const Quaternion &rot, unsigned long time = XFORM_LOCAL_PRS);
+       virtual void rotate(const Vector3 &euler, unsigned long time = XFORM_LOCAL_PRS);
+       virtual void rotate(const Matrix3x3 &rmat, unsigned long time = XFORM_LOCAL_PRS);
+       virtual void scale(const Vector3 &scale, unsigned long time = XFORM_LOCAL_PRS); 
+
+       virtual void reset_position(unsigned long time = XFORM_LOCAL_PRS);
+       virtual void reset_rotation(unsigned long time = XFORM_LOCAL_PRS);
+       virtual void reset_scaling(unsigned long time = XFORM_LOCAL_PRS);
+       virtual void reset_xform(unsigned long time = XFORM_LOCAL_PRS);
+       
+       virtual PRS get_prs(unsigned long time = XFORM_LOCAL_PRS) const;
+};
+
+#include "animation.inl"
+
+
+#endif // _ANIMATION_HPP_
diff --git a/src/3dengfx/src/gfx/animation.inl b/src/3dengfx/src/gfx/animation.inl
new file mode 100644 (file)
index 0000000..4c2b1ec
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+This file is part of the graphics core library.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+///////////////// Keyframes ////////////////
+
+inline bool Keyframe::operator ==(const Keyframe &key) const {
+       return time == key.time ? true : false;
+}
+
+inline bool Keyframe::operator <(const Keyframe &key) const {
+       return time < key.time ? true : false;
+}
+
+
+// ------------- XFormNode -------------
+
+inline Keyframe *XFormNode::get_nearest_key(unsigned long time) {
+       return get_nearest_key(0, key_count > 0 ? key_count - 1 : 0, time);
+}
+inline const Keyframe *XFormNode::get_nearest_key(unsigned long time) const {
+       return get_nearest_key(0, key_count > 0 ? key_count - 1 : 0, time);
+}
+
+inline const Keyframe *XFormNode::get_nearest_key(int start, int end, unsigned long time) const {
+       return const_cast<XFormNode*>(this)->get_nearest_key(start, end, time);
+}
diff --git a/src/3dengfx/src/gfx/base_cam.cpp b/src/3dengfx/src/gfx/base_cam.cpp
new file mode 100644 (file)
index 0000000..2078529
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+This file is part of the graphics core library.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+the graphics core library is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+the graphics core library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with the graphics core library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "3dengfx_config.h"
+
+#include "base_cam.hpp"
+
+#ifdef USING_3DENGFX
+#include "3dengfx/3denginefx.hpp"
+#endif // USING_3DENGFX
+
+FrustumPlane::FrustumPlane() {
+       a = b = c = d = 0;
+}
+
+FrustumPlane::FrustumPlane(scalar_t a, scalar_t b, scalar_t c, scalar_t d) {
+       this->a = a;
+       this->b = b;
+       this->c = c;
+       this->d = d;
+}
+
+// frustum plane extraction from a projection (or mvp) matrix
+FrustumPlane::FrustumPlane(const Matrix4x4 &mat, int plane) {
+       int i = plane / 2;
+       int neg = plane % 2;
+
+       a = mat[3][0] + (neg ? -mat[i][0] : mat[i][0]);
+       b = mat[3][1] + (neg ? -mat[i][1] : mat[i][1]);
+       c = mat[3][2] + (neg ? -mat[i][2] : mat[i][2]);
+       d = mat[3][3] + (neg ? -mat[i][3] : mat[i][3]);
+
+       // normalize plane equation
+       scalar_t len = Vector3(a, b, c).length();
+       a /= len;
+       b /= len;
+       c /= len;
+       d /= len;
+}
+
+BaseCamera::BaseCamera(const Vector3 &trans, const Quaternion &rot) {
+       set_position(trans);
+       set_rotation(rot);
+       up = Vector3(0, 1, 0);
+       fov = quarter_pi;
+       near_clip = 1.0;
+       far_clip = 10000.0;
+       aspect = 1.33333;
+       flip_view.x = flip_view.y = flip_view.z = false;
+}
+
+BaseCamera::~BaseCamera() {}
+
+void BaseCamera::setup_frustum(const Matrix4x4 &m) {
+       for(int i=0; i<6; i++) {
+               frustum[i] = FrustumPlane(m, i);
+       }
+}
+
+void BaseCamera::set_up_vector(const Vector3 &up) {
+       this->up = up;
+}
+
+void BaseCamera::set_fov(scalar_t angle) {
+       fov = angle;
+}
+
+scalar_t BaseCamera::get_fov() const {
+       return fov;
+}
+
+void BaseCamera::set_aspect(scalar_t aspect) {
+       this->aspect = aspect;
+}
+
+scalar_t BaseCamera::get_aspect() const {
+       return aspect;
+}
+
+void BaseCamera::set_clipping_planes(scalar_t near_clip, scalar_t far_clip) {
+       this->near_clip = near_clip;
+       this->far_clip = far_clip;
+}
+
+void BaseCamera::set_clipping_plane(scalar_t val, ClipPlane which) {
+       if(which == CLIP_NEAR) {
+               near_clip = val;
+       } else {
+               far_clip = val;
+       }
+}
+
+scalar_t BaseCamera::get_clipping_plane(ClipPlane which) const {
+       return which == CLIP_NEAR ? near_clip : far_clip;
+}
+
+
+void BaseCamera::zoom(scalar_t zoom_factor, unsigned long msec) {
+       Vector3 zoom_dir(0, 0, zoom_factor);
+       PRS prs = get_prs(msec);
+
+       zoom_dir.transform(prs.rotation.inverse());
+       translate(zoom_dir, msec);
+}
+
+void BaseCamera::pan(const Vector2 &dir, unsigned long msec) {
+       Vector3 i(1, 0, 0), j(0, 1, 0);
+       
+       PRS prs = get_prs(msec);
+       
+       i.transform(prs.rotation.inverse());
+       j.transform(prs.rotation.inverse());
+       
+       translate(i * dir.x);
+       translate(j * dir.y);
+}
+
+void BaseCamera::roll(scalar_t angle, unsigned long msec) {
+       Vector3 dir(0, 0, 1);
+       dir.transform(get_prs(msec).rotation);
+
+       Quaternion q(dir, angle);
+       up = Vector3(0, 1, 0);
+       up.transform(q);
+}
+
+void BaseCamera::flip(bool x, bool y, bool z) {
+       flip_view.x = x;
+       flip_view.y = y;
+       flip_view.z = z;
+}
+
+const FrustumPlane *BaseCamera::get_frustum() const {
+       return frustum;
+}
+
+Matrix4x4 BaseCamera::get_projection_matrix() const {
+#ifdef USING_3DENGFX
+       return create_projection_matrix(fov, aspect, near_clip, far_clip);
+#else
+       return Matrix4x4::identity_matrix;
+#endif // USING_3DENGFX
+}
+
+void BaseCamera::activate(unsigned long msec) const {
+#ifdef USING_3DENGFX
+       set_matrix(XFORM_VIEW, get_camera_matrix(msec));
+
+       Matrix4x4 proj = get_projection_matrix();
+       set_matrix(XFORM_PROJECTION, proj);
+
+       engfx_state::view_mat_camera = (const Camera*)this;
+       const_cast<BaseCamera*>(this)->setup_frustum(proj * engfx_state::view_matrix);
+#endif // USING_3DENGFX
+}
diff --git a/src/3dengfx/src/gfx/base_cam.hpp b/src/3dengfx/src/gfx/base_cam.hpp
new file mode 100644 (file)
index 0000000..254fccc
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+This file is part of the graphics core library.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+the graphics core library is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+the graphics core library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with the graphics core library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#ifndef _BASE_CAM_HPP_
+#define _BASE_CAM_HPP_
+
+#include "3dgeom.hpp"
+#include "animation.hpp"
+#include "n3dmath2/n3dmath2.hpp"
+
+enum ClipPlane {CLIP_NEAR, CLIP_FAR};
+
+/* DON'T change the order of these enums!
+ * The frustum plane extraction algorithm depends on it.
+ */
+enum {FRUSTUM_LEFT, FRUSTUM_RIGHT, FRUSTUM_BOTTOM, FRUSTUM_TOP, FRUSTUM_NEAR, FRUSTUM_FAR};
+
+class FrustumPlane {
+public:
+       scalar_t a, b, c, d;    // the plane equation coefficients
+
+       FrustumPlane();
+       FrustumPlane(scalar_t a, scalar_t b, scalar_t c, scalar_t d);
+       FrustumPlane(const Matrix4x4 &mat, int plane);
+};
+       
+
+class BaseCamera : public XFormNode {
+protected:
+       scalar_t fov;
+       scalar_t near_clip, far_clip;
+       Vector3 up;
+       scalar_t aspect;
+
+       mutable FrustumPlane frustum[6];
+
+       struct {bool x, y, z;} flip_view;
+
+       virtual void setup_frustum(const Matrix4x4 &m);
+       
+public:
+       BaseCamera(const Vector3 &trans = Vector3(0,0,0), const Quaternion &rot = Quaternion());
+       virtual ~BaseCamera();
+       
+       virtual void set_up_vector(const Vector3 &up);
+       
+       virtual void set_fov(scalar_t angle);
+       virtual scalar_t get_fov() const;
+
+       virtual void set_aspect(scalar_t aspect);
+       virtual scalar_t get_aspect() const;
+       
+       virtual void set_clipping_planes(scalar_t near_clip, scalar_t far_clip);
+       virtual void set_clipping_plane(scalar_t val, ClipPlane which);
+       virtual scalar_t get_clipping_plane(ClipPlane which) const;
+
+       virtual void zoom(scalar_t zoom_factor, unsigned long msec = XFORM_LOCAL_PRS);
+       virtual void pan(const Vector2 &dir, unsigned long msec = XFORM_LOCAL_PRS);
+       virtual void roll(scalar_t angle, unsigned long msec = XFORM_LOCAL_PRS);
+
+       virtual void flip(bool x, bool y, bool z);
+
+       virtual const FrustumPlane *get_frustum() const;
+
+       virtual Matrix4x4 get_camera_matrix(unsigned long msec = XFORM_LOCAL_PRS) const = 0;
+       virtual Matrix4x4 get_projection_matrix() const;
+
+       virtual void activate(unsigned long msec = XFORM_LOCAL_PRS) const;
+};
+
+#endif // _BASE_CAM_HPP_
diff --git a/src/3dengfx/src/gfx/bvol.cpp b/src/3dengfx/src/gfx/bvol.cpp
new file mode 100644 (file)
index 0000000..0ae67b8
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+This file is part of the graphics core library.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+the graphics core library is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+the graphics core library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with the graphics core library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* Bounding volumes
+ *
+ * Author: John Tsiombikas 2005
+ */
+
+#include "bvol.hpp"
+
+BoundingVolume::BoundingVolume() {
+       parent = 0;
+}
+
+BoundingVolume::~BoundingVolume() {}
+
+void BoundingVolume::set_transform(const Matrix4x4 &transform) {
+       this->transform = transform;
+}
+
+BoundingSphere::BoundingSphere(const Vector3 &pos, scalar_t rad) {
+       set_position(pos);
+       set_radius(rad);
+}
+
+bool BoundingSphere::ray_hit(const Ray &ray) const {
+       Sphere sph = *this;
+       Vector3 new_pos = sph.get_position();
+       sph.set_position(new_pos.transformed(transform));
+       
+       if(!sph.check_intersection(ray)) return false;
+       if(!children.size()) return true;
+       
+       for(size_t i=0; i<children.size(); i++) {
+               if(children[i]->ray_hit(ray)) return true;
+       }
+
+       return false;
+}
+
+bool BoundingSphere::visible(const FrustumPlane *frustum) const {
+       Vector3 new_pos = pos.transformed(transform);
+       
+       for(int i=0; i<6; i++) {
+               Vector3 normal(frustum[i].a, frustum[i].b, frustum[i].c);
+               scalar_t dist = dot_product(new_pos, normal) + frustum[i].d;
+
+               if(fabs(dist) < radius) break;
+               if(dist < -radius) return false;
+       }
+
+       // the sphere is at least partially inside the frustum, check any children
+       if(!children.size()) return true;
+
+       for(size_t i=0; i<children.size(); i++) {
+               if(children[i]->visible(frustum)) return true;
+       }
+       return false;
+}
diff --git a/src/3dengfx/src/gfx/bvol.hpp b/src/3dengfx/src/gfx/bvol.hpp
new file mode 100644 (file)
index 0000000..9a36720
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+This file is part of the graphics core library.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+the graphics core library is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+the graphics core library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with the graphics core library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* Bounding volumes
+ *
+ * Author: John Tsiombikas 2005
+ */
+
+#ifndef _BVOL_HPP_
+#define _BVOL_HPP_
+
+#include <vector>
+#include "n3dmath2/n3dmath2.hpp"
+#include "gfx/base_cam.hpp"
+
+class BoundingVolume {
+protected:
+       BoundingVolume *parent;
+       std::vector<BoundingVolume*> children;
+       Matrix4x4 transform;
+
+public:
+       BoundingVolume();
+       virtual ~BoundingVolume();
+
+       virtual void set_transform(const Matrix4x4 &transform);
+
+       virtual bool ray_hit(const Ray &ray) const = 0;
+       virtual bool visible(const FrustumPlane *frustum) const = 0;
+};
+
+class BoundingSphere : public BoundingVolume, public Sphere {
+public:
+       BoundingSphere(const Vector3 &pos = Vector3(0,0,0), scalar_t rad = 1.0);
+
+       virtual bool ray_hit(const Ray &ray) const;
+       virtual bool visible(const FrustumPlane *frustum) const;
+};
+
+#endif // _BVOL_HPP_
diff --git a/src/3dengfx/src/gfx/color.cpp b/src/3dengfx/src/gfx/color.cpp
new file mode 100644 (file)
index 0000000..c7b93be
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+Copyright 2004 John Tsiombikas <nuclear@siggraph.org>
+
+This file is part of the graphics core library.
+
+the graphics core library is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+the graphics core library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with the graphics core library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* colors
+ * author: John Tsiombikas 2004
+ */
+
+#include "3dengfx_config.h"
+
+#include <cmath>
+#include "color.hpp"
+
+template <class T>
+const T &clamp(const T &val, const T &low, const T &high) {
+       if(val > high) return high;
+       if(val < low) return low;
+       return val;
+}
+
+Color::Color(scalar_t intensity) {
+       r = g = b = clamp<scalar_t>(intensity, 0.0f, 1.0f);
+       a = 1.0f;
+}
+
+Color::Color(scalar_t r, scalar_t g, scalar_t b, scalar_t a) {
+       this->r = clamp<scalar_t>(r, 0.0f, 1.0f);
+       this->g = clamp<scalar_t>(g, 0.0f, 1.0f);
+       this->b = clamp<scalar_t>(b, 0.0f, 1.0f);
+       this->a = clamp<scalar_t>(a, 0.0f, 1.0f);
+}
+
+unsigned long Color::get_packed32() const {
+       return pack_color32(*this);
+}
+
+unsigned short Color::get_packed16() const {
+       return pack_color16(*this);
+}
+
+unsigned short Color::get_packed15() const {
+       return pack_color15(*this);
+}
+
+unsigned char Color::get_nearest8(const unsigned char **pal) const {
+       return match_nearest8(*this, pal);
+}
+
+Color Color::operator +(const Color &col) const {
+       return Color(r + col.r, g + col.g, b + col.b, a + col.a);
+}
+
+Color Color::operator -(const Color &col) const {
+       return Color(r - col.r, g - col.g, b - col.b, a - col.a);
+}
+
+Color Color::operator *(const Color &col) const {
+       return Color(r * col.r, g * col.g, b * col.b, a * col.a);
+}
+       
+Color Color::operator *(scalar_t scalar) const {
+       return Color(r * scalar, g * scalar, b * scalar, a);
+}
+
+
+void Color::operator +=(const Color &col) {
+       *this = Color(r + col.r, g + col.g, b + col.b, a + col.a);
+}
+
+void Color::operator -=(const Color &col) {
+       *this = Color(r - col.r, g - col.g, b - col.b, a - col.a);
+}
+
+void Color::operator *=(const Color &col) {
+       *this = Color(r * col.r, g * col.g, b * col.b, a * col.a);
+}
+
+void Color::operator *=(scalar_t scalar) {
+       *this = Color(r * scalar, g * scalar, b * scalar, a);
+}
+
+unsigned char match_nearest8(const Color &col, const unsigned char **pal) {
+       static const scalar_t half_pi = 1.5707963268;
+
+       scalar_t score[256];
+       for(int i=0; i<256; i++) {
+               Color palcol = lookup_color8(i, pal);
+               scalar_t near_r = (scalar_t)cos(fabs(col.r - palcol.r) * half_pi);
+               scalar_t near_g = (scalar_t)cos(fabs(col.g - palcol.g) * half_pi);
+               scalar_t near_b = (scalar_t)cos(fabs(col.b - palcol.b) * half_pi);
+               score[i] = near_r + near_g + near_b;
+       }
+
+       int nearest = 0;
+       for(int i=0; i<256; i++) {
+               if(score[i] > score[nearest]) nearest = i;
+       }
+       return nearest;
+}
diff --git a/src/3dengfx/src/gfx/color.hpp b/src/3dengfx/src/gfx/color.hpp
new file mode 100644 (file)
index 0000000..4f2c286
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+Copyright 2004 John Tsiombikas <nuclear@siggraph.org>
+
+This file is part of the graphics core library.
+
+The graphics core library is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+The graphics core library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with the graphics core library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* colors
+ * author: John Tsiombikas 2004
+ */
+
+#ifndef _COLOR2_H_
+#define _COLOR2_H_
+
+#include "3dengfx_config.h"
+#include "color_bits.h"
+
+#ifdef SINGLE_PRECISION_MATH
+typedef float scalar_t;
+#else
+typedef double scalar_t;
+#endif // DOUBLE_PRECISION_MATH
+
+class Color {
+public:
+       scalar_t r, g, b, a;
+
+       Color(scalar_t intensity = 1.0f);
+       Color(scalar_t r, scalar_t g, scalar_t b, scalar_t a = 1.0f);
+
+       Color operator +(const Color &col) const;
+       Color operator -(const Color &col) const;
+       Color operator *(const Color &col) const;
+       Color operator *(scalar_t scalar) const;
+
+       void operator +=(const Color &col);
+       void operator -=(const Color &col);
+       void operator *=(const Color &col);
+       void operator *=(scalar_t scalar);
+
+       unsigned long get_packed32() const;
+       unsigned short get_packed16() const;
+       unsigned short get_packed15() const;
+       unsigned char get_nearest8(const unsigned char **pal) const;
+};
+
+inline Color int_color(int r, int g, int b, int a = 255);
+
+inline unsigned long pack_color32(const Color &col);
+inline unsigned short pack_color16(const Color &col);
+inline unsigned short pack_color15(const Color &col);
+unsigned char match_nearest8(const Color &col, const unsigned char **pal);
+
+inline Color unpack_color32(unsigned long pcol);
+inline Color unpack_color16(unsigned short pcol);
+inline Color unpack_color15(unsigned short pcol);
+inline Color lookup_color8(int index, const unsigned char **pal);
+
+Color blend_colors(const Color &c1, const Color &c2, scalar_t t);
+
+#include "color.inl"
+
+#endif // _COLOR2_H_
diff --git a/src/3dengfx/src/gfx/color.inl b/src/3dengfx/src/gfx/color.inl
new file mode 100644 (file)
index 0000000..7d82b95
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+Copyright 2004 John Tsiombikas <nuclear@siggraph.org>
+
+This file is part of the graphics core library.
+
+The graphics core library is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+The graphics core library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with the graphics core library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* colors
+ * author: John Tsiombikas 2004
+ */
+
+inline Color int_color(int r, int g, int b, int a) {
+       return Color((scalar_t)r / 255.0, (scalar_t)g / 255.0, (scalar_t)b / 255.0, (scalar_t)a / 255.0);
+}
+
+inline unsigned long pack_color32(const Color &col) {
+       unsigned long r = (unsigned long)(col.r * 255.0);
+       unsigned long g = (unsigned long)(col.g * 255.0);
+       unsigned long b = (unsigned long)(col.b * 255.0);
+       unsigned long a = (unsigned long)(col.a * 255.0);
+       return (a << ALPHA_SHIFT32) | (r << RED_SHIFT32) | (g << GREEN_SHIFT32) | (b << BLUE_SHIFT32);
+}
+
+inline unsigned short pack_color16(const Color &col) {
+       unsigned long r = (unsigned long)(col.r * 31.0);
+       unsigned long g = (unsigned long)(col.g * 63.0);
+       unsigned long b = (unsigned long)(col.b * 31.0);
+       return (r << RED_SHIFT16) | (g << GREEN_SHIFT16) | (b << BLUE_SHIFT16);
+}
+
+inline unsigned short pack_color15(const Color &col) {
+       unsigned long r = (unsigned long)(col.r * 31.0);
+       unsigned long g = (unsigned long)(col.g * 31.0);
+       unsigned long b = (unsigned long)(col.b * 31.0);
+       return (r << RED_SHIFT15) | (g << GREEN_SHIFT15) | (b << BLUE_SHIFT15);
+}
+
+inline Color unpack_color32(unsigned long pcol) {
+       scalar_t a = (scalar_t)((pcol >> ALPHA_SHIFT32) & ALPHA_MASK32) / 255.0;
+       scalar_t r = (scalar_t)((pcol >> RED_SHIFT32) & RED_MASK32) / 255.0;
+       scalar_t g = (scalar_t)((pcol >> GREEN_SHIFT32) & GREEN_MASK32) / 255.0;
+       scalar_t b = (scalar_t)((pcol >> BLUE_SHIFT32) & BLUE_MASK32) / 255.0;
+       return Color(r, g, b, a);
+}
+
+inline Color unpack_color16(unsigned short pcol) {
+       scalar_t r = (scalar_t)((pcol >> RED_SHIFT16) & RED_MASK16) / 31.0;
+       scalar_t g = (scalar_t)((pcol >> GREEN_SHIFT16) & GREEN_MASK16) / 63.0;
+       scalar_t b = (scalar_t)((pcol >> BLUE_SHIFT16) & BLUE_MASK16) / 31.0;
+       return Color(r, g, b, 1.0);
+}
+
+inline Color unpack_color15(unsigned short pcol) {
+       scalar_t r = (scalar_t)((pcol >> RED_SHIFT15) & RED_MASK15) / 31.0;
+       scalar_t g = (scalar_t)((pcol >> GREEN_SHIFT15) & GREEN_MASK15) / 31.0;
+       scalar_t b = (scalar_t)((pcol >> BLUE_SHIFT15) & BLUE_MASK15) / 31.0;
+       return Color(r, g, b, 1.0);
+}
+
+inline Color lookup_color8(int index, const unsigned char **pal) {
+       scalar_t r = (scalar_t)pal[index][0] / 255.0;
+       scalar_t g = (scalar_t)pal[index][1] / 255.0;
+       scalar_t b = (scalar_t)pal[index][2] / 255.0;
+       return Color(r, g, b, 1.0);
+}
+
+inline Color blend_colors(const Color &c1, const Color &c2, scalar_t t) {
+       scalar_t r = c1.r + (c2.r - c1.r) * t;
+       scalar_t g = c1.g + (c2.g - c1.g) * t;
+       scalar_t b = c1.b + (c2.b - c1.b) * t;
+       scalar_t a = c1.a + (c2.a - c1.a) * t;
+       return Color(r, g, b, a);
+}
diff --git a/src/3dengfx/src/gfx/color_bits.h b/src/3dengfx/src/gfx/color_bits.h
new file mode 100644 (file)
index 0000000..ec15999
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+Copyright 2004 John Tsiombikas <nuclear@siggraph.org>
+
+This file is part of the graphics core library.
+
+The graphics core library is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+The graphics core library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with the graphics core library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* color bit shift and mask values for color packing/unpacking
+ * in a cross-endianess manner.
+ *
+ * author: John Tsiombikas 2004
+ */
+#ifndef _COLOR_BITS_H_
+#define _COLOR_BITS_H_
+
+#include "common/types.h"
+#include "common/byteorder.h"
+
+/* 32bit color shift values */
+#ifdef LITTLE_ENDIAN
+#define ALPHA_SHIFT32  24
+#define RED_SHIFT32            16
+#define GREEN_SHIFT32  8
+#define BLUE_SHIFT32   0
+#else  /* BIG_ENDIAN */
+#define ALPHA_SHIFT32  0
+#define RED_SHIFT32            8
+#define GREEN_SHIFT32  16
+#define BLUE_SHIFT32   24
+#endif /* LITTLE_ENDIAN */
+
+/* 32bit color mask values */
+#define ALPHA_MASK32   0xff
+#define RED_MASK32             0xff
+#define GREEN_MASK32   0xff
+#define BLUE_MASK32            0xff
+
+/* 16bit color shift values */
+#ifdef LITTLE_ENDIAN
+#define RED_SHIFT16            11
+#define GREEN_SHIFT16  5
+#define BLUE_SHIFT16   0
+#else  /* BIG_ENDIAN */
+#define RED_SHIFT16            0
+#define GREEN_SHIFT16  5
+#define BLUE_SHIFT16   11
+#endif /* LITTLE_ENDIAN */
+
+/* 16bit color mask values */
+#define RED_MASK16             0x1f
+#define GREEN_MASK16   0x3f
+#define BLUE_MASK16            0x1f
+
+/* 15bit color shift values */
+#ifdef LITTLE_ENDIAN
+#define RED_SHIFT15            10
+#define GREEN_SHIFT15  5
+#define BLUE_SHIFT15   0
+#else  /* BIG_ENDIAN */
+#define RED_SHIFT15            0
+#define GREEN_SHIFT15  5
+#define BLUE_SHIFT15   10
+#endif /* LITTLE_ENDIAN */
+
+/* 15bit color mask values */
+#define RED_MASK15             0x1f
+#define GREEN_MASK15   0x1f
+#define BLUE_MASK15            0x1f
+
+
+/* color packing macros */
+#define PACK_COLOR32(a,r,g,b) \
+       ((((unsigned long)(a) & ALPHA_MASK32) << ALPHA_SHIFT32) | \
+       (((unsigned long)(r) & RED_MASK32) << RED_SHIFT32) | \
+       (((unsigned long)(g) & GREEN_MASK32) << GREEN_SHIFT32) | \
+       (((unsigned long)(b) & BLUE_MASK32) << BLUE_SHIFT32))
+
+#define PACK_COLOR24(r,g,b)            PACK_COLOR32(0xff,r,g,b)
+
+#define PACK_COLOR16(r,g,b) \
+       ((((unsigned short)(r) & RED_MASK16) << RED_SHIFT16) | \
+       (((unsigned short)(g) & GREEN_MASK16) << GREEN_SHIFT16) | \
+       (((unsigned short)(b) & BLUE_MASK16) << BLUE_SHIFT16))
+
+#define PACK_COLOR15(r,g,b) \
+       ((((unsigned short)(r) & RED_MASK15) << RED_SHIFT15) | \
+       (((unsigned short)(g) & GREEN_MASK15) << GREEN_SHIFT15) | \
+       (((unsigned short)(b) & BLUE_MASK15) << BLUE_SHIFT15))
+
+#endif /* _COLOR_BITS_H_ */
diff --git a/src/3dengfx/src/gfx/controller.cpp b/src/3dengfx/src/gfx/controller.cpp
new file mode 100644 (file)
index 0000000..8efc843
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+This file is part of the graphics core library.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* motion controllers (part of the animation system)
+ *
+ * Author: John Tsiombikas 2004
+ */
+
+#include "3dengfx_config.h"
+
+#include "controller.hpp"
+
+MotionController::MotionController(ControllerClass ctype, TimelineMode mode) {
+       start_time = end_time = 0;
+       curve = 0;
+       time_mode = mode;
+       ctrl_type = ctype;
+
+       freq = ampl = 1.0f;
+       freq_func = ampl_func = 0;
+
+       slope = Vector3(1, 1, 1);
+
+       axis_flags = CTRL_XYZ;
+}
+
+MotionController::MotionController(Curve *curve, unsigned long start, unsigned long end, TimelineMode mode) {
+       this->curve = curve;
+       start_time = start;
+       end_time = end;
+       time_mode = mode;
+
+       ctrl_type = CTRL_CURVE;
+       freq = ampl = 1.0f;
+       freq_func = ampl_func = 0;
+
+       slope = Vector3(1, 1, 1);
+
+       axis_flags = CTRL_XYZ;
+}
+
+void MotionController::set_curve(Curve *curve) {
+       this->curve = curve;
+}
+
+void MotionController::set_sin_func(scalar_t freq, scalar_t ampl, scalar_t phase) {
+       this->freq = freq;
+       this->ampl = ampl;
+       this->phase = phase;
+}
+
+void MotionController::set_sin_func(scalar_t (*freq_func)(scalar_t), scalar_t (*ampl_func)(scalar_t)) {
+       this->freq_func = freq_func;
+       this->ampl_func = ampl_func;
+}
+
+void MotionController::set_origin(scalar_t orig) {
+       this->orig = Vector3(orig, orig, orig);
+}
+
+void MotionController::set_origin(const Vector3 &orig_vec) {
+       orig = orig_vec;
+}
+
+void MotionController::set_slope(scalar_t slope) {
+       this->slope = Vector3(slope, slope, slope);
+}
+
+void MotionController::set_slope(const Vector3 &slope_vec) {
+       slope = slope_vec;
+}
+
+void MotionController::set_timing(unsigned long start, unsigned long end) {
+       start_time = start;
+       end_time = end;
+}
+
+void MotionController::set_timeline_mode(TimelineMode tmode) {
+       time_mode = tmode;
+}
+
+void MotionController::set_controller_type(ControllerClass ctype) {
+       ctrl_type = ctype;
+}
+
+void MotionController::set_control_axis(unsigned int axis_flags) {
+       this->axis_flags = axis_flags;
+}
+
+Curve *MotionController::get_curve() {
+       return curve;
+}
+
+unsigned long MotionController::get_start_time() const {
+       return start_time;
+}
+
+unsigned long MotionController::get_end_time() const {
+       return end_time;
+}
+
+TimelineMode MotionController::get_timeline_mode() const {
+       return time_mode;
+}
+
+unsigned int MotionController::get_control_axis() const {
+       return axis_flags;
+}
+
+
+Vector3 MotionController::operator ()(unsigned long time) const {
+       time = get_timeline_time(time, start_time, end_time, time_mode);
+
+       double (*sinusoidal)(double);
+       sinusoidal = sin;
+       
+       switch(ctrl_type) {
+       case CTRL_CURVE:
+               {
+                       scalar_t t = (scalar_t)(time - start_time) / (scalar_t)(end_time - start_time);
+                       Vector3 vec = (*curve)(t);
+                       if(!(axis_flags & CTRL_X)) vec.x = 0;
+                       if(!(axis_flags & CTRL_Y)) vec.y = 0;
+                       if(!(axis_flags & CTRL_Z)) vec.z = 0;
+                       return vec;
+               }
+
+       case CTRL_COS:
+               sinusoidal = cos;
+       case CTRL_SIN:
+               {
+                       scalar_t t = (scalar_t)time / 1000.0f;
+                       scalar_t frequency = freq_func ? freq_func(t) : freq;
+                       scalar_t amplitude = ampl_func ? ampl_func(t) : ampl;
+                       scalar_t result = sinusoidal((phase + t) * frequency) * amplitude;
+
+                       Vector3 vec(0, 0, 0);
+                       if(axis_flags & CTRL_X) vec.x = result;
+                       if(axis_flags & CTRL_Y) vec.y = result;
+                       if(axis_flags & CTRL_Z) vec.z = result;
+                       return vec;
+               }
+
+       case CTRL_LIN:
+               {
+                       scalar_t t = (scalar_t)time / 1000.0f;
+                       Vector3 result = orig + slope * t;
+                       
+                       Vector3 vec(0, 0, 0);
+                       if(axis_flags & CTRL_X) vec.x = result.x;
+                       if(axis_flags & CTRL_Y) vec.y = result.y;
+                       if(axis_flags & CTRL_Z) vec.z = result.z;
+                       return vec;
+               }
+       }
+       return Vector3();       // Should not happen
+}
diff --git a/src/3dengfx/src/gfx/controller.hpp b/src/3dengfx/src/gfx/controller.hpp
new file mode 100644 (file)
index 0000000..541d876
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+This file is part of the graphics core library.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* motion controllers (part of the animation system)
+ *
+ * Author: John Tsiombikas 2004
+ */
+
+#ifndef _CONTROLLER_HPP_
+#define _CONTROLLER_HPP_
+
+#include "curves.hpp"
+#include "timeline.hpp"
+
+enum ControllerClass {CTRL_CURVE, CTRL_SIN, CTRL_COS, CTRL_LIN};
+
+enum {
+       CTRL_X          = 1,    // 0001
+       CTRL_Y          = 2,    // 0010
+       CTRL_Z          = 4,    // 0100
+       CTRL_XY         = 3,    // 0011
+       CTRL_YZ         = 6,    // 0110
+       CTRL_XZ         = 5,    // 0101
+       CTRL_XYZ        = 7             // 0111
+};
+       
+
+class MotionController {
+private:
+       Curve *curve;
+
+       // parameters for the sinusoidal controller
+       scalar_t freq, ampl, phase;
+       scalar_t (*freq_func)(scalar_t);
+       scalar_t (*ampl_func)(scalar_t);
+
+       // parameters for the linear controller
+       Vector3 orig, slope;
+       
+       unsigned long start_time, end_time;
+       
+       TimelineMode time_mode;
+       ControllerClass ctrl_type;
+       unsigned int axis_flags;
+       
+public:
+       MotionController(ControllerClass ctype = CTRL_CURVE, TimelineMode mode = TIME_CLAMP);
+       MotionController(Curve *curve, unsigned long start, unsigned long end, TimelineMode mode = TIME_CLAMP);
+       
+       void set_curve(Curve *curve);
+       void set_sin_func(scalar_t freq, scalar_t ampl, scalar_t phase = 0.0f);
+       void set_sin_func(scalar_t (*freq_func)(scalar_t), scalar_t(*ampl_func)(scalar_t));
+       
+       void set_origin(scalar_t orig);
+       void set_origin(const Vector3 &orig_vec);
+       void set_slope(scalar_t slope);
+       void set_slope(const Vector3 &slope_vec);
+       
+       void set_timing(unsigned long start, unsigned long end);
+       void set_timeline_mode(TimelineMode tmode);
+       void set_controller_type(ControllerClass ctype);
+       void set_control_axis(unsigned int axis_flags);
+       
+       Curve *get_curve();
+       unsigned long get_start_time() const;
+       unsigned long get_end_time() const;
+       TimelineMode get_timeline_mode() const;
+       unsigned int get_control_axis() const;
+       
+       Vector3 operator ()(unsigned long time) const;
+};
+       
+
+#endif // _CONTROLLER_HPP_
diff --git a/src/3dengfx/src/gfx/curves.cpp b/src/3dengfx/src/gfx/curves.cpp
new file mode 100644 (file)
index 0000000..a71194f
--- /dev/null
@@ -0,0 +1,533 @@
+/*
+This file is part of the 3dengfx, realtime visualization system.
+Copyright (C) 2004, 2006 John Tsiombikas <nuclear@siggraph.org>
+
+the 3dengfx library is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+the 3dengfx library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with the 3dengfx library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* 3D Curves
+ * 
+ * author: John Tsiombikas 2003
+ * modified:
+ *             John Tsiombikas 2004, 2006
+ *             Mihalis Georgoulopoulos 2004
+ */
+
+#include <cstdio>
+#include <cstring>
+#include <cmath>
+#include <cctype>
+#include <cassert>
+#include "curves.hpp"
+#include "common/err_msg.h"
+
+Curve::Curve() {
+       arc_parametrize = false;
+       ease_curve = 0;
+       samples = 0;
+       xform_cv = 0;
+
+       set_ease_sample_count(100);
+}
+
+Curve::~Curve() {
+       delete [] samples;
+       
+}
+
+void Curve::set_arc_parametrization(bool state) {
+       arc_parametrize = state;
+}
+
+#define Param  0
+#define ArcLen 1
+
+void Curve::sample_arc_lengths() {
+       const int samplesPerSegment = 30;
+       sample_count = get_segment_count() * samplesPerSegment;
+
+       arc_parametrize = false;        // to be able to interpolate with the original values
+
+       samples = new Vector2[sample_count];
+       Vector3 prevpos;
+       scalar_t step = 1.0f / (scalar_t)(sample_count-1);
+       for(int i=0; i<sample_count; i++) {
+               scalar_t t = step * (scalar_t)i;
+               Vector3 pos = interpolate(t);
+               samples[i][Param] = t;
+               if(!i) {
+                       samples[i][ArcLen] = 0.0f;
+               } else {
+                       samples[i][ArcLen] = (pos - prevpos).length() + samples[i-1][ArcLen];
+               }
+               prevpos = pos;
+       }
+
+       // normalize arc lenghts
+       scalar_t maxlen = samples[sample_count-1][ArcLen];
+       for(int i=0; i<sample_count; i++) {
+               samples[i][ArcLen] /= maxlen;
+       }
+
+       arc_parametrize = true;
+}
+
+static int binary_search(Vector2 *array, scalar_t key, int begin, int end) {
+       int middle = begin + ((end - begin)>>1);
+
+       if(array[middle][ArcLen] == key) return middle;
+       if(end == begin) return middle;
+
+       if(key < array[middle][ArcLen]) return binary_search(array, key, begin, middle);
+       if(key > array[middle][ArcLen]) return binary_search(array, key, middle+1, end);
+       return -1;      // just to make the compiler shut the fuck up
+}
+
+scalar_t Curve::parametrize(scalar_t t) const {
+       if(!samples) const_cast<Curve*>(this)->sample_arc_lengths();
+
+       int samplepos = binary_search(samples, t, 0, sample_count);
+       scalar_t par = samples[samplepos][Param];
+       scalar_t len = samples[samplepos][ArcLen];
+
+       // XXX: I can't remember the significance of this condition, I had xsmall_number here
+       // previously and if t was 0.9999 it broke. I just changed the number blindly which fixed
+       // the breakage but I should investigate further at some point.
+       if((len - t) < 0.0005) return par;
+
+       if(len < t) {
+               if(!samplepos) return par;
+               scalar_t prevlen = samples[samplepos-1][ArcLen];
+               scalar_t prevpar = samples[samplepos-1][Param];
+               scalar_t p = (t - prevlen) / (len - prevlen);
+               return prevpar + (par - prevpar) * p;
+       } else {
+               if(samplepos >= sample_count) return par;
+               scalar_t nextlen = samples[samplepos+1][ArcLen];
+               scalar_t nextpar = samples[samplepos+1][Param];
+               scalar_t p = (t - len) / (nextlen - len);
+               return par + (nextpar - par) * p;
+       }
+
+       return par;     // not gonna happen
+}
+
+
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+
+scalar_t Curve::ease(scalar_t t) const {
+       if(!ease_curve) return t;
+
+       const_cast<Curve*>(this)->ease_curve->set_arc_parametrization(true);
+       scalar_t et = ease_curve->interpolate(t).y;
+
+       return MIN(MAX(et, 0.0f), 1.0f);
+}
+
+
+void Curve::add_control_point(const Vector3 &cp) {
+       control_points.push_back(cp);
+       delete [] samples;
+       samples = 0;
+}
+
+void Curve::remove_control_point(int index) {
+       if(index < 0 || index >= control_points.size()) return;
+
+       ListNode<Vector3> *node = control_points.begin();
+       for(int i=0; i<index; i++) {
+               node = node->next;
+       }
+
+       control_points.erase(node);
+}
+
+#define MIN(a, b)      ((a) < (b) ? (a) : (b))
+#define MAX(a, b)      ((a) > (b) ? (a) : (b))
+
+Vector3 *Curve::get_control_point(int index) {
+       index = MAX(0, MIN(index, control_points.size() - 1));
+
+       ListNode<Vector3> *node = control_points.begin();
+       for(int i=0; i<index; i++) {
+               assert(node);
+               node = node->next;
+       }
+       
+       assert(node);
+       return &node->data;
+}
+
+int Curve::get_point_count() const {
+       return control_points.size();
+}
+
+void Curve::set_ease_curve(Curve *curve) {
+       ease_curve = curve;
+}
+
+void Curve::set_ease_sample_count(int count) {
+       ease_sample_count = count;
+       ease_step = (int)(1.0f / (scalar_t)ease_sample_count);
+}
+
+Vector3 Curve::operator ()(scalar_t t) const {
+       return xform_cv ? xform_cv(interpolate(t)) : interpolate(t);
+}
+
+void Curve::set_xform_func(Vector3 (*func)(const Vector3&)) {
+       xform_cv = func;
+}
+
+///////////////// B-Spline implementation ////////////////////
+
+int BSpline::get_segment_count() const {
+       return control_points.size() - 3;
+}
+
+Vector3 BSpline::interpolate(scalar_t t) const {
+       if(t > 1.0) t = 1.0;
+       if(t < 0.0) t = 0.0;
+
+       if(control_points.size() < 4) return Vector3(0, 0, 0);
+
+       if(arc_parametrize) {
+               t = ease(parametrize(t));
+       }
+
+       // find the appropriate segment of the spline that t lies and calculate the piecewise parameter
+       t = (scalar_t)(control_points.size() - 3) * t;
+       int seg = (int)t;
+       t -= (scalar_t)floor(t);
+       if(seg >= get_segment_count()) {
+               seg = get_segment_count() - 1;
+               t = 1.0f;
+       }
+       
+       ListNode<Vector3> *iter = const_cast<BSpline*>(this)->control_points.begin();
+       for(int i=0; i<seg; i++) iter = iter->next;
+
+       Vector3 Cp[4];
+       for(int i=0; i<4; i++) {
+        Cp[i] = iter->data;
+               iter = iter->next;
+       }
+
+       Vector3 res;
+       res.x = bspline(Cp[0].x, Cp[1].x, Cp[2].x, Cp[3].x, t);
+       res.y = bspline(Cp[0].y, Cp[1].y, Cp[2].y, Cp[3].y, t);
+       res.z = bspline(Cp[0].z, Cp[1].z, Cp[2].z, Cp[3].z, t);
+
+       return res;
+}
+
+//////////////// Catmull-Rom Spline implementation //////////////////
+
+int CatmullRomSpline::get_segment_count() const {
+       return control_points.size() - 1;
+}
+
+Vector3 CatmullRomSpline::interpolate(scalar_t t) const {
+       if(t > 1.0) t = 1.0;
+       if(t < 0.0) t = 0.0;
+
+       if(control_points.size() < 2) return Vector3(0, 0, 0);
+
+       if(arc_parametrize) {
+               t = ease(parametrize(t));
+       }
+
+       // find the appropriate segment of the spline that t lies and calculate the piecewise parameter
+       t = (scalar_t)(control_points.size() - 1) * t;
+       int seg = (int)t;
+       t -= (scalar_t)floor(t);
+       if(seg >= get_segment_count()) {
+               seg = get_segment_count() - 1;
+               t = 1.0f;
+       }
+
+       Vector3 cp[4];
+       ListNode<Vector3> *iter = const_cast<CatmullRomSpline*>(this)->control_points.begin();
+       for(int i=0; i<seg; i++) {
+               iter = iter->next;
+       }
+
+       cp[1] = iter->data;
+       cp[2] = iter->next->data;
+       
+       if(!seg) {
+               cp[0] = cp[1];
+       } else {
+               cp[0] = iter->prev->data;
+       }
+       
+       if(seg == control_points.size() - 2) {
+               cp[3] = cp[2];
+       } else {
+               cp[3] = iter->next->next->data;
+       }
+
+       Vector3 res;
+       res.x = catmull_rom_spline(cp[0].x, cp[1].x, cp[2].x, cp[3].x, t);
+       res.y = catmull_rom_spline(cp[0].y, cp[1].y, cp[2].y, cp[3].y, t);
+       res.z = catmull_rom_spline(cp[0].z, cp[1].z, cp[2].z, cp[3].z, t);
+
+       return res;
+}
+
+
+
+/* BezierSpline implementation - (MG) */
+int BezierSpline::get_segment_count() const
+{
+       return control_points.size() / 4;
+}
+
+Vector3 BezierSpline::interpolate(scalar_t t) const
+{
+       if (!get_segment_count()) return Vector3(0, 0, 0);
+
+       if (arc_parametrize)
+       {
+               t = ease(parametrize(t));
+       }
+       t = (t * get_segment_count());
+       int seg = (int) t;
+       t -= (scalar_t) floor(t);
+       if (seg >= get_segment_count())
+       {
+               seg = get_segment_count() - 1;
+               t = 1.0f;
+       }
+
+       seg *= 4;
+       ListNode<Vector3> *iter = const_cast<BezierSpline*>(this)->control_points.begin();
+       for (int i = 0; i < seg; i++) iter = iter->next;
+       
+       Vector3 Cp[4];
+       for (int i = 0; i < 4; i++)
+       {
+               Cp[i] = iter->data;
+               iter = iter->next;
+       }
+       
+       // interpolate
+       return bezier(Cp[seg], Cp[seg + 1], Cp[seg + 2], Cp[seg + 3], t);
+}
+
+Vector3 BezierSpline::get_tangent(scalar_t t)
+{      
+       if (!get_segment_count()) return Vector3(0, 0, 0);
+
+       if (arc_parametrize)
+       {
+               t = ease(parametrize(t));
+       }
+       t = (t * get_segment_count());
+       int seg = (int) t;
+       t -= (scalar_t) floor(t);
+       if (seg >= get_segment_count())
+       {
+               seg = get_segment_count() - 1;
+               t = 1.0f;
+       }
+
+       seg *= 4;
+       ListNode<Vector3> *iter = const_cast<BezierSpline*>(this)->control_points.begin();
+       for (int i = 0; i < seg; i++) iter = iter->next;
+       
+       Vector3 Cp[4];
+       for (int i = 0; i < 4; i++)
+       {
+               Cp[i] = iter->data;
+               iter = iter->next;
+       }
+       
+       // interpolate
+       return bezier_tangent(Cp[0], Cp[1], Cp[2], Cp[3], t);
+}
+
+Vector3 BezierSpline::get_control_point(int i) const
+{      
+       
+       ListNode<Vector3> *iter = const_cast<BezierSpline*>(this)->control_points.begin();
+       for (int j = 0; j < i; j++) 
+       {
+               if (!iter->next)
+               {
+                       return Vector3(0, 0, 0);
+               }
+               iter = iter->next;
+       }
+       
+       return iter->data;
+}
+
+
+/* ------ polylines (JT) ------ */
+int PolyLine::get_segment_count() const {
+       return control_points.size() - 1;
+}
+
+Vector3 PolyLine::interpolate(scalar_t t) const {
+       if(t > 1.0) t = 1.0;
+       if(t < 0.0) t = 0.0;
+
+       if(control_points.size() < 2) return Vector3(0, 0, 0);
+
+       // TODO: check if this is reasonable for polylines.
+       if(arc_parametrize) {
+               t = ease(parametrize(t));
+       }
+
+       // find the appropriate segment of the spline that t lies and calculate the piecewise parameter
+       t = (scalar_t)(control_points.size() - 1) * t;
+       int seg = (int)t;
+       t -= (scalar_t)floor(t);
+       if(seg >= get_segment_count()) {
+               seg = get_segment_count() - 1;
+               t = 1.0f;
+       }
+
+       Vector3 cp[2];
+       ListNode<Vector3> *iter = const_cast<PolyLine*>(this)->control_points.begin();
+       for(int i=0; i<seg; i++) {
+               iter = iter->next;
+       }
+
+       cp[0] = iter->data;
+       cp[1] = iter->next->data;
+
+       return cp[0] + (cp[1] - cp[0]) * t;
+}
+
+
+bool save_curve(const char *fname, const Curve *curve) {
+       FILE *fp = fopen(fname, "w");
+       if(!fp) {
+               error("failed to save the curve %s", curve->name.c_str());
+               return false;
+       }
+
+       fputs("curve_3dengfx\n", fp);
+       fputs(curve->name.c_str(), fp);
+       fputs("\n", fp);
+
+       if(dynamic_cast<const BSpline*>(curve)) {
+               fputs("bspline\n", fp);
+       } else if(dynamic_cast<const CatmullRomSpline*>(curve)) {
+               fputs("catmullrom\n", fp);
+       } else if(dynamic_cast<const BezierSpline*>(curve)) {
+               fputs("bezier\n", fp);
+       } else if(dynamic_cast<const PolyLine*>(curve)) {
+               fputs("polyline\n", fp);
+       } else {
+               error("unknown spline type, save failed %s", curve->name.c_str());
+               fclose(fp);
+               remove(fname);
+               return false;
+       }
+
+       fprintf(fp, "%d\n", curve->control_points.size());
+
+       const ListNode<Vector3> *node = curve->control_points.begin();
+       while(node) {
+               fprintf(fp, "%f %f %f\n", node->data.x, node->data.y, node->data.z);
+               node = node->next;
+       }
+
+       fclose(fp);
+       return true;
+}
+
+Curve *load_curve(const char *fname) {
+       FILE *fp = fopen(fname, "r");
+       if(!fp) {
+               error("failed to open file %s", fname);
+               return 0;
+       }
+
+       char buffer[256];
+
+       fgets(buffer, 256, fp);
+       if(strcmp(buffer, "curve_3dengfx\n") != 0) {
+               error("load_curve failed, %s is not a curve file", fname);
+               fclose(fp);
+               return 0;
+       }
+
+       Curve *curve;
+
+       fgets(buffer, 256, fp);
+       std::string name = buffer;
+
+       fgets(buffer, 256, fp);
+       if(!strcmp(buffer, "bspline\n")) {
+               curve = new BSpline;
+       } else if(!strcmp(buffer, "catmullrom\n")) {
+               curve = new CatmullRomSpline;
+       } else /*if(!strcmp(buffer, "bezier"))*/ {
+               error("unsupported curve type (%s) or not a curve file", buffer);
+               fclose(fp);
+               return 0;
+       }
+
+       curve->name = name;
+
+       fgets(buffer, 256, fp);
+       if(!isdigit(buffer[0])) {
+               error("load_curve failed, %s is not a valid curve file (count: %s)", fname, buffer);
+               delete curve;
+               fclose(fp);
+               return 0;
+       }
+       int count = atoi(buffer);
+
+       int failed = count;
+       for(int i=0; i<count; i++, failed--) {
+               fgets(buffer, 256, fp);
+               if(!isdigit(buffer[0]) && buffer[0] != '.' && buffer[0] != '-') {
+                       break;
+               }
+               float x = atof(buffer);
+
+               char *ptr = strchr(buffer, ' ');
+               if(!ptr || (!isdigit(ptr[1]) && ptr[1] != '.' && ptr[1] != '-')) {
+                       break;
+               }
+               float y = atof(++ptr);
+               
+               ptr = strchr(ptr, ' ');
+               if(!ptr || (!isdigit(ptr[1]) && ptr[1] != '.' && ptr[1] != '-')) {
+                       break;
+               }
+               float z = atof(++ptr);
+
+               curve->add_control_point(Vector3(x, y, z));
+       }
+
+       fclose(fp);
+
+       if(failed) {
+               error("load_curve failed to read the data, %s is not a valid curve file", fname);
+               delete curve;
+               return 0;
+       }
+
+       return curve;
+}
diff --git a/src/3dengfx/src/gfx/curves.hpp b/src/3dengfx/src/gfx/curves.hpp
new file mode 100644 (file)
index 0000000..0d0887a
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+This file is part of the 3dengfx, realtime visualization system.
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+the 3dengfx library is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+the 3dengfx library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with the 3dengfx library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* 3D Curves
+ * 
+ * author: John Tsiombikas 2003
+ * modified:
+ *             John Tsiombikas 2004, 2005, 2006
+ *             Mihalis Georgoulopoulos 2004
+ */
+
+#ifndef _CURVES_HPP_
+#define _CURVES_HPP_
+
+#include "3dengfx_config.h"
+
+#include <string>
+#include "n3dmath2/n3dmath2.hpp"
+#include "common/linkedlist.hpp"
+
+
+class Curve {
+protected:
+       LinkedList<Vector3> control_points;
+       Vector2 *samples;       // used for parametrizing by arc length
+       int sample_count;
+       bool arc_parametrize;
+
+       Curve *ease_curve;      // ease in/out curve (1D, x&z discarded)
+       int ease_sample_count, ease_step;
+       
+       void sample_arc_lengths();
+       scalar_t parametrize(scalar_t t) const;
+       scalar_t ease(scalar_t t) const;
+
+       Vector3 (*xform_cv)(const Vector3 &pt);
+       
+       virtual Vector3 interpolate(scalar_t t) const = 0;
+
+public:
+       std::string name;
+
+       Curve();
+       virtual ~Curve();
+       virtual void add_control_point(const Vector3 &cp);
+       virtual void remove_control_point(int index);
+       virtual Vector3 *get_control_point(int index);
+
+       virtual int get_point_count() const;
+       virtual int get_segment_count() const = 0;
+       virtual void set_arc_parametrization(bool state);
+       virtual void set_ease_curve(Curve *curve);
+       virtual void set_ease_sample_count(int count);
+
+       virtual Vector3 operator ()(scalar_t t) const;
+
+       virtual void set_xform_func(Vector3 (*func)(const Vector3&));
+
+       friend bool save_curve(const char *fname, const Curve *curve);
+};
+
+class BSpline : public Curve {
+protected:
+       virtual Vector3 interpolate(scalar_t t) const;
+
+public:
+       virtual int get_segment_count() const;
+};
+
+typedef BSpline        BSplineCurve;
+
+
+class CatmullRomSpline : public Curve {
+protected:
+       virtual Vector3 interpolate(scalar_t t) const;
+
+public:
+       virtual int get_segment_count() const;
+};
+
+typedef CatmullRomSpline CatmullRomSplineCurve;
+
+
+class BezierSpline : public Curve {
+protected:
+       virtual Vector3 interpolate(scalar_t t) const;
+
+public:
+       virtual int get_segment_count() const;
+
+       Vector3 get_control_point(int i) const;
+       Vector3 get_tangent(scalar_t t);
+};
+
+class PolyLine : public Curve {
+protected:
+       virtual Vector3 interpolate(scalar_t t) const;
+
+public:
+       virtual int get_segment_count() const;
+};
+
+bool save_curve(const char *fname, const Curve *curve);
+Curve *load_curve(const char *fname);
+
+#endif // _CURVES_HPP_
diff --git a/src/3dengfx/src/gfx/image.c b/src/3dengfx/src/gfx/image.c
new file mode 100644 (file)
index 0000000..bec0b6c
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+This is a small image library.
+Copyright (C) 2004 John Tsiombikas <nuclear@siggraph.org>
+
+This library is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* image file library
+ *
+ * author: John Tsiombikas 2003
+ * modified: John Tsiombikas 2004
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "image.h"
+
+#ifdef IMGLIB_USE_PNG
+int check_png(FILE *fp);
+void *load_png(FILE *fp, unsigned long *xsz, unsigned long *ysz);
+int save_png(FILE *fp, void *pixels, unsigned long xsz, unsigned long ysz);
+#endif /* IMGLIB_USE_PNG */
+
+#ifdef IMGLIB_USE_JPEG
+int check_jpeg(FILE *fp);
+void *load_jpeg(FILE *fp, unsigned long *xsz, unsigned long *ysz);
+int save_jpeg(FILE *fp, void *pixels, unsigned long xsz, unsigned long ysz);
+#endif /* IMGLIB_USE_JPEG */
+
+#ifdef IMGLIB_USE_TGA
+int check_tga(FILE *fp);
+void *load_tga(FILE *fp, unsigned long *xsz, unsigned long *ysz);
+int save_tga(FILE *fp, void *pixels, unsigned long xsz, unsigned long ysz);
+#endif /* IMGLIB_USE_TGA */
+
+#ifdef IMGLIB_USE_PPM
+int check_ppm(FILE *fp);
+void *load_ppm(FILE *fp, unsigned long *xsz, unsigned long *ysz);
+int save_ppm(FILE *fp, void *pixels, unsigned long xsz, unsigned long ysz);
+#endif /* IMGLIB_USE_PPM */
+
+
+static unsigned long save_flags;
+
+
+void *load_image(const char *fname, unsigned long *xsz, unsigned long *ysz) {
+       FILE *file;
+
+       if(!(file = fopen(fname, "rb"))) {
+               fprintf(stderr, "Image loading error: could not open file %s\n", fname);
+               return 0;
+       }
+       
+#ifdef IMGLIB_USE_PNG
+       if(check_png(file)) {
+               return load_png(file, xsz, ysz);
+       }
+#endif /* IMGLIB_USE_PNG */
+       
+#ifdef IMGLIB_USE_JPEG
+       if(check_jpeg(file)) {
+               return load_jpeg(file, xsz, ysz);
+       }
+#endif /* IMGLIB_USE_JPEG */
+       
+#ifdef IMGLIB_USE_TGA
+       if(check_tga(file)) {
+               return load_tga(file, xsz, ysz);
+       }
+#endif /* IMGLIB_USE_TGA */
+
+#ifdef IMGLIB_USE_PPM
+       if(check_ppm(file)) {
+               return load_ppm(file, xsz, ysz);
+       }
+#endif /* IMGLIB_USE_PPM */
+
+       fclose(file);
+       return 0;
+}
+
+void free_image(void *img) {
+       free(img);
+}
+
+int save_image(const char *fname, void *pixels, unsigned long xsz, unsigned long ysz, enum image_file_format fmt) {
+       FILE *fp;
+
+       if(!(fp = fopen(fname, "wb"))) {
+               fprintf(stderr, "Image saving error: could not open file %s for writing\n", fname);
+               return -1;
+       }
+
+       switch(fmt) {
+       case IMG_FMT_PNG:
+#ifdef IMGLIB_USE_PNG
+               save_png(fp, pixels, xsz, ysz);
+               break;
+#endif /* IMGLIB_USE_PNG */
+
+       case IMG_FMT_JPEG:
+#ifdef IMGLIB_USE_JPEG
+               save_jpeg(fp, pixels, xsz, ysz);
+#endif /* IMGLIB_USE_JPEG */
+               break;
+               
+       case IMG_FMT_TGA:
+#ifdef IMGLIB_USE_TGA
+               save_tga(fp, pixels, xsz, ysz);
+#endif /* IMGLIB_USE_TGA */
+               break;
+
+       case IMG_FMT_PPM:
+#ifdef IMGLIB_USE_PPM
+               save_ppm(fp, pixels, xsz, ysz);
+#endif /* IMGLIB_USE_PPM */
+               break;
+
+       default:
+               fprintf(stderr, "Image saving error: error saving %s, invalid format specification", fname);
+               break;
+       }
+
+       fclose(fp);
+       
+       return 0;
+}
+
+
+void set_image_save_flags(unsigned int flags) {
+       save_flags = flags;
+}
+
+unsigned int get_image_save_flags(void) {
+       return save_flags;
+}
diff --git a/src/3dengfx/src/gfx/image.h b/src/3dengfx/src/gfx/image.h
new file mode 100644 (file)
index 0000000..e4b178b
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+Copyright 2004 John Tsiombikas <nuclear@siggraph.org>
+
+This is a small image library.
+
+This library is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* image file handling library
+ *
+ * author: John Tsiombikas 2003
+ * modified: John Tsiombikas 2004
+ */
+
+#ifndef IMAGE_H_
+#define IMAGE_H_
+
+#include "3dengfx_config.h"
+
+/* always compile support for image formats that
+ * don't create any library dependencies.
+ */
+#define IMGLIB_USE_TGA
+#define IMGLIB_USE_PPM
+
+/* for jpeg and png, make the default be to compile them in,
+ * unless explicitly disabled.
+ */
+#ifndef IMGLIB_NO_JPEG
+#define IMGLIB_USE_JPEG
+#endif /* IMGLIB_NO_JPEG */
+
+#ifndef IMGLIB_NO_PNG
+#define IMGLIB_USE_PNG
+#endif /* IMGLIB_NO_PNG */
+
+
+enum image_file_format {
+       IMG_FMT_PNG,
+       IMG_FMT_JPEG,
+       IMG_FMT_TGA,
+       IMG_FMT_PPM
+};
+
+enum {
+       IMG_SAVE_ALPHA          = 1,
+       IMG_SAVE_COMPRESS       = 2,
+       IMG_SAVE_INVERT         = 4
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* load_image() loads the specified image from file, returns the pixel data
+ * in 32bit mode, and changes xsz and ysz to the size of the image
+ */
+void *load_image(const char *fname, unsigned long *xsz, unsigned long *ysz);
+
+/* deallocate the image data with this function
+ * note: provided for consistency, simply calls free()
+ */
+void free_image(void *img);
+
+/* save the supplied image data in a file of the specified format */
+int save_image(const char *fname, void *pixels, unsigned long xsz, unsigned long ysz, enum image_file_format fmt);
+
+/* set/get save image options */
+void set_image_save_flags(unsigned int flags);
+unsigned int get_image_save_flags(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+       
+#endif /* IMAGE_H_ */
diff --git a/src/3dengfx/src/gfx/image_jpg.c b/src/3dengfx/src/gfx/image_jpg.c
new file mode 100644 (file)
index 0000000..02e7ab2
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+Copyright 2004 John Tsiombikas <nuclear@siggraph.org>
+
+This is a small image library.
+
+This library is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* jpeg support
+ * 
+ * author: Mihalis Georgoulopoulos 2004
+ * modified: John Tsiombikas 2004
+ */
+
+#include "3dengfx_config.h"
+#include "image.h"
+#include <stdio.h>
+
+#ifdef IMGLIB_USE_JPEG
+
+#include <stdlib.h>
+
+#ifdef WIN32
+#include <windows.h>
+#define HAVE_BOOLEAN
+#endif
+
+#include <jpeglib.h>
+#include "color_bits.h"
+
+typedef struct
+{
+       unsigned char r,g,b;
+} RGBTriplet;
+
+/*jpeg signature*/
+int check_jpeg(FILE *fp){
+       unsigned char sig[10];
+
+       fseek(fp, 0, SEEK_SET);
+       fread(sig, 1, 10, fp);
+       
+    if(sig[0]!=0xff || sig[1]!=0xd8 || sig[2]!=0xff || sig[3]!=0xe0) {
+               return 0;
+       }
+
+       if(/*sig[6]!='J' ||*/sig[7]!='F' || sig[8]!='I' || sig[9]!='F') {
+               return 0;
+       }
+       
+    return 1;
+}
+
+void *load_jpeg(FILE *fp, unsigned long *xsz, unsigned long *ysz) {
+       int i;
+       RGBTriplet *buffer;
+       uint32_t *image;
+       
+       JSAMPLE *tmp;
+    
+       struct jpeg_decompress_struct cinfo;
+       struct jpeg_error_mgr jerr;
+       cinfo.err = jpeg_std_error(&jerr);
+       
+       fseek(fp, 0, SEEK_SET);
+
+       jpeg_create_decompress(&cinfo);
+       jpeg_stdio_src(&cinfo, fp);
+       
+       jpeg_read_header(&cinfo, TRUE);
+       
+       /* force output to rgb */
+       cinfo.out_color_space = JCS_RGB;
+       
+    /* allocate space */
+    buffer = malloc(cinfo.image_width * sizeof(RGBTriplet));
+    if (!buffer) return 0;
+    image = malloc(cinfo.image_width * (cinfo.image_height) * sizeof(uint32_t));
+    if (!image) return 0;
+    
+    tmp = (JSAMPLE*) buffer;
+
+       /* return w and h */
+       *xsz = cinfo.image_width;
+       *ysz = cinfo.image_height;
+    
+       /* Decompress, pack and store */
+    jpeg_start_decompress(&cinfo);
+    {
+        while (cinfo.output_scanline < cinfo.output_height) 
+        {
+            jpeg_read_scanlines(&cinfo, &tmp, 1);
+                       if (cinfo.output_scanline == 0) continue;
+            
+            for (i=0;i<cinfo.image_width;i++)
+            {
+                               int offs = i + (cinfo.output_scanline-1) * cinfo.output_width;
+                image[offs] = PACK_COLOR24(buffer[i].r, buffer[i].g, buffer[i].b);
+            }
+        }
+    }
+    jpeg_finish_decompress(&cinfo);
+       
+       /*Done - cleanup*/
+       jpeg_destroy_decompress(&cinfo);
+       free(buffer);
+       fclose(fp);
+
+       return (void*) image;
+}
+
+/* TODO: implement this */
+int save_jpeg(FILE *fp, void *pixels, unsigned long xsz, unsigned long ysz) {
+       fprintf(stderr, "saving jpeg files is not implemented yet\n");
+       return -1;
+}
+
+#endif /* IMGLIB_USE_JPEG */
diff --git a/src/3dengfx/src/gfx/image_png.c b/src/3dengfx/src/gfx/image_png.c
new file mode 100644 (file)
index 0000000..1b0f759
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+Copyright 2004 John Tsiombikas <nuclear@siggraph.org>
+
+This is a small image library.
+
+This library is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* png support
+ * 
+ * author: John Tsiombikas 2003
+ * modified: John Tsiombikas 2004
+ */
+
+#include "3dengfx_config.h"
+#include "image.h"
+#include <stdio.h>
+#include <string.h>
+
+#ifdef IMGLIB_USE_PNG
+
+#include <stdlib.h>
+#include <png.h>
+#include "color_bits.h"
+#include "common/types.h"
+
+#define FILE_SIG_BYTES 8
+
+int check_png(FILE *fp) {
+       unsigned char sig[FILE_SIG_BYTES];
+
+       fread(sig, 1, FILE_SIG_BYTES, fp);
+
+       return png_sig_cmp(sig, 0, FILE_SIG_BYTES) == 0 ? 1 : 0;
+}
+
+void *load_png(FILE *fp, unsigned long *xsz, unsigned long *ysz) {
+       png_struct *png_ptr;
+       png_info *info_ptr;
+       int i;
+       uint32_t **lineptr, *pixels;
+       int channel_bits, color_type, ilace_type, compression, filtering;
+       
+       if(!(png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0))) {
+               fclose(fp);
+               return 0;
+       }
+       
+       if(!(info_ptr = png_create_info_struct(png_ptr))) {
+               png_destroy_read_struct(&png_ptr, 0, 0);
+               fclose(fp);
+               return 0;
+       }
+       
+       if(setjmp(png_jmpbuf(png_ptr))) {               
+               png_destroy_read_struct(&png_ptr, &info_ptr, 0);
+               fclose(fp);
+               return 0;
+       }
+       
+       png_init_io(png_ptr, fp);       
+       png_set_sig_bytes(png_ptr, FILE_SIG_BYTES);
+       
+       png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_BGR, 0);
+               
+       png_get_IHDR(png_ptr, info_ptr, xsz, ysz, &channel_bits, &color_type, &ilace_type, &compression, &filtering);
+       pixels = malloc(*xsz * *ysz * sizeof(uint32_t));
+       
+       lineptr = (uint32_t**)png_get_rows(png_ptr, info_ptr);
+       
+       for(i=0; i<*ysz; i++) {
+               
+               switch(color_type) {
+               case PNG_COLOR_TYPE_RGB:
+                       {
+                               int j;
+                               unsigned char *ptr = (unsigned char*)lineptr[i];
+                               for(j=0; j<*xsz; j++) {
+                       
+                                       uint32_t pixel;
+                                       pixel = PACK_COLOR24(*(ptr+2), *(ptr+1), *ptr);
+                                       ptr+=3;
+                                       pixels[i * *xsz + j] = pixel;                   
+                               }
+                       }
+                       break;
+                       
+               case PNG_COLOR_TYPE_RGB_ALPHA:
+                       memcpy(&pixels[i * *xsz], lineptr[i], *xsz * sizeof(uint32_t));
+                       break;
+                       
+               default:
+                       png_destroy_read_struct(&png_ptr, &info_ptr, 0);
+                       fclose(fp);
+                       return 0;
+               }
+                               
+       }
+       
+       png_destroy_read_struct(&png_ptr, &info_ptr, 0);
+       fclose(fp);
+       
+       return pixels;
+}
+
+/* TODO: implement this */
+int save_png(FILE *fp, void *pixels, unsigned long xsz, unsigned long ysz) {
+       fprintf(stderr, "saving png files is not implemented yet");
+       return -1;
+}
+
+#endif /* IMGLIB_USE_PNG */
diff --git a/src/3dengfx/src/gfx/image_ppm.c b/src/3dengfx/src/gfx/image_ppm.c
new file mode 100644 (file)
index 0000000..5809078
--- /dev/null
@@ -0,0 +1,131 @@
+#include "image.h"
+#include <stdio.h>
+
+#ifdef IMGLIB_USE_PPM
+
+#include <stdlib.h>
+#include <ctype.h>
+#include "color_bits.h"
+
+
+int check_ppm(FILE *fp) {
+       fseek(fp, 0, SEEK_SET);
+       if(fgetc(fp) == 'P' && fgetc(fp) == '6') {
+               return 1;
+       }
+       return 0;
+}
+
+static int read_to_wspace(FILE *fp, char *buf, int bsize) {
+       int c, count = 0;
+       
+       while((c = fgetc(fp)) != -1 && !isspace(c) && count < bsize - 1) {
+               if(c == '#') {
+                       while((c = fgetc(fp)) != -1 && c != '\n' && c != '\r');
+                       c = fgetc(fp);
+                       if(c == '\n' || c == '\r') continue;
+               }
+               *buf++ = c;
+               count++;
+       }
+       *buf = 0;
+       
+       while((c = fgetc(fp)) != -1 && isspace(c));
+       ungetc(c, fp);
+       return count;
+}
+
+void *load_ppm(FILE *fp, unsigned long *xsz, unsigned long *ysz) {
+       char buf[64];
+       int bytes, raw;
+       unsigned int w, h, i, sz;
+       uint32_t *pixels;
+       
+       fseek(fp, 0, SEEK_SET);
+       
+       bytes = read_to_wspace(fp, buf, 64);
+       raw = buf[1] == '6';
+
+       if((bytes = read_to_wspace(fp, buf, 64)) == 0) {
+               fclose(fp);
+               return 0;
+       }
+       if(!isdigit(*buf)) {
+               fprintf(fp, "load_ppm: invalid width: %s", buf);
+               fclose(fp);
+               return 0;
+       }
+       w = atoi(buf);
+
+       if((bytes = read_to_wspace(fp, buf, 64)) == 0) {
+               fclose(fp);
+               return 0;
+       }
+       if(!isdigit(*buf)) {
+               fprintf(fp, "load_ppm: invalid height: %s", buf);
+               fclose(fp);
+               return 0;
+       }
+       h = atoi(buf);
+
+       if((bytes = read_to_wspace(fp, buf, 64)) == 0) {
+               fclose(fp);
+               return 0;
+       }
+       if(!isdigit(*buf) || atoi(buf) != 255) {
+               fprintf(fp, "load_ppm: invalid or unsupported max value: %s", buf);
+               fclose(fp);
+               return 0;
+       }
+
+       if(!(pixels = malloc(w * h * sizeof *pixels))) {
+               fputs("malloc failed", fp);
+               fclose(fp);
+               return 0;
+       }
+
+       sz = h * w;
+       for(i=0; i<sz; i++) {
+               int r = fgetc(fp);
+               int g = fgetc(fp);
+               int b = fgetc(fp);
+
+               if(r == -1 || g == -1 || b == -1) {
+                       free(pixels);
+                       fclose(fp);
+                       fputs("load_ppm: EOF while reading pixel data", fp);
+                       return 0;
+               }
+               pixels[i] = PACK_COLOR24(r, g, b);
+       }
+
+       fclose(fp);
+
+       if(xsz) *xsz = w;
+       if(ysz) *ysz = h;
+       return pixels;
+}
+
+int save_ppm(FILE *fp, void *pixels, unsigned long xsz, unsigned long ysz) {
+       int i, sz = xsz * ysz;
+       uint32_t *ptr = pixels;
+       
+       fprintf(fp, "P6\n%lu %lu\n255\n# 3dengfx PPM file writer\n", xsz, ysz);
+
+       for(i=0; i<sz; i++) {
+               int r = (*ptr & RED_MASK32) >> RED_SHIFT32;
+               int g = (*ptr & GREEN_MASK32) >> GREEN_SHIFT32;
+               int b = (*ptr++ & BLUE_MASK32) >> BLUE_SHIFT32;
+
+               if(fputc(r, fp) == EOF || fputc(g, fp) == EOF || fputc(b, fp) == EOF) {
+                       fputs("save_ppm: failed to write to file", stderr);
+                       fclose(fp);
+                       return -1;
+               }
+       }
+
+       fclose(fp);
+       return 0;
+}
+
+#endif /* IMGLIB_USE_PPM */
diff --git a/src/3dengfx/src/gfx/image_tga.c b/src/3dengfx/src/gfx/image_tga.c
new file mode 100644 (file)
index 0000000..81b27ab
--- /dev/null
@@ -0,0 +1,248 @@
+/*
+This is a small image library.
+
+Copyright (C) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This library is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* targa support
+ * 
+ * author: John Tsiombikas 2004
+ * modified: John Tsiombikas 2005
+ */
+
+#include "3dengfx_config.h"
+#include "image.h"
+#include <stdio.h>
+
+#ifdef IMGLIB_USE_TGA
+
+#include <stdlib.h>
+#include <string.h>
+#include "color_bits.h"
+#include "common/byteorder.h"
+
+struct tga_header {
+       uint8_t idlen;                  /* id field length */
+       uint8_t cmap_type;              /* color map type (0:no color map, 1:color map present) */
+       uint8_t img_type;               /* image type: 
+                                                        * 0: no image data
+                                                        *      1: uncomp. color-mapped          9: RLE color-mapped
+                                                        *      2: uncomp. true color           10: RLE true color
+                                                        *      3: uncomp. black/white          11: RLE black/white */  
+       uint16_t cmap_first;    /* color map first entry index */
+       uint16_t cmap_len;              /* color map length */
+       uint8_t cmap_entry_sz;  /* color map entry size */
+       uint16_t img_x;                 /* X-origin of the image */
+       uint16_t img_y;                 /* Y-origin of the image */
+       uint16_t img_width;             /* image width */
+       uint16_t img_height;    /* image height */
+       uint8_t img_bpp;                /* bits per pixel */
+       uint8_t img_desc;               /* descriptor: 
+                                                        * bits 0 - 3: alpha or overlay bits
+                                                        * bits 5 & 4: origin (0 = bottom/left, 1 = top/right)
+                                                        * bits 7 & 6: data interleaving */     
+};
+
+struct tga_footer {
+       uint32_t ext_off;               /* extension area offset */
+       uint32_t devdir_off;    /* developer directory offset */
+       char sig[18];                           /* signature with . and \0 */
+};
+
+/*static void print_tga_info(struct tga_header *hdr);*/
+
+int check_tga(FILE *fp) {
+       struct tga_footer foot;
+       
+       fseek(fp, -18, SEEK_END);
+       fread(foot.sig, 1, 18, fp);
+
+       foot.sig[17] = 0;
+       return strcmp(foot.sig, "TRUEVISION-XFILE.") == 0 ? 1 : 0;
+}
+
+void *load_tga(FILE *fp, unsigned long *xsz, unsigned long *ysz) {
+       struct tga_header hdr;
+       unsigned long x, y, sz;
+       int i;
+       uint32_t *pix;
+
+       /* read header */
+       fseek(fp, 0, SEEK_SET);
+       hdr.idlen = fgetc(fp);
+       hdr.cmap_type = fgetc(fp);
+       hdr.img_type = fgetc(fp);
+       hdr.cmap_first = read_int16_le(fp);
+       hdr.cmap_len = read_int16_le(fp);
+       hdr.cmap_entry_sz = fgetc(fp);
+       hdr.img_x = read_int16_le(fp);
+       hdr.img_y = read_int16_le(fp);
+       hdr.img_width = read_int16_le(fp);
+       hdr.img_height = read_int16_le(fp);
+       hdr.img_bpp = fgetc(fp);
+       hdr.img_desc = fgetc(fp);
+
+       if(feof(fp)) {
+               fclose(fp);
+               return 0;
+       }
+       
+       /* only read true color images */
+       if(hdr.img_type != 2) {
+               fclose(fp);
+               fprintf(stderr, "only true color tga images supported\n");
+               return 0;
+       }
+
+       fseek(fp, hdr.idlen, SEEK_CUR); /* skip the image ID */
+
+       /* skip the color map if it exists */
+       if(hdr.cmap_type == 1) {
+               fseek(fp, hdr.cmap_len * hdr.cmap_entry_sz / 8, SEEK_CUR);
+       }
+
+       x = hdr.img_width;
+       y = hdr.img_height;
+       sz = x * y;
+       if(!(pix = malloc(sz * 4))) {
+               fclose(fp);
+               return 0;
+       }
+
+       for(i=0; i<y; i++) {
+               uint32_t *ptr;
+               int j;
+
+               ptr = pix + ((hdr.img_desc & 0x20) ? i : y-(i+1)) * x;
+
+               for(j=0; j<x; j++) {
+                       unsigned char r, g, b, a;
+                       r = fgetc(fp);
+                       g = fgetc(fp);
+                       b = fgetc(fp);
+                       a = (hdr.img_desc & 0xf) ? fgetc(fp) : 255;
+               
+                       *ptr++ = PACK_COLOR32(a, r, g, b);
+                       
+                       if(feof(fp)) break;
+               }
+       }
+
+       fclose(fp);
+       *xsz = x;
+       *ysz = y;
+       return pix;
+}
+
+int save_tga(FILE *fp, void *pixels, unsigned long xsz, unsigned long ysz) {
+       struct tga_header hdr;
+       struct tga_footer ftr;
+       unsigned long pix_count = xsz * ysz;
+       uint32_t *pptr = pixels;
+       unsigned long save_flags;
+       int i;
+
+       save_flags = get_image_save_flags();
+
+       memset(&hdr, 0, sizeof hdr);
+       hdr.img_type = 2;
+       hdr.img_width = xsz;
+       hdr.img_height = ysz;
+
+       if(save_flags & IMG_SAVE_ALPHA) {
+               hdr.img_bpp = 32;
+               hdr.img_desc = 8 | 0x20;        /* 8 alpha bits, origin top-left */
+       } else {
+               hdr.img_bpp = 24;
+               hdr.img_desc = 0x20;            /* no alpha bits, origin top-left */
+       }
+
+       if(save_flags & IMG_SAVE_INVERT) {
+               hdr.img_desc ^= 0x20;
+       }
+
+       ftr.ext_off = 0;
+       ftr.devdir_off = 0;
+       strcpy(ftr.sig, "TRUEVISION-XFILE.");
+
+       /* write the header */
+       
+       fwrite(&hdr.idlen, 1, 1, fp);
+       fwrite(&hdr.cmap_type, 1, 1, fp);
+       fwrite(&hdr.img_type, 1, 1, fp);
+       write_int16_le(fp, hdr.cmap_first);
+       write_int16_le(fp, hdr.cmap_len);
+       fwrite(&hdr.cmap_entry_sz, 1, 1, fp);
+       write_int16_le(fp, hdr.img_x);
+       write_int16_le(fp, hdr.img_y);
+       write_int16_le(fp, hdr.img_width);
+       write_int16_le(fp, hdr.img_height);
+       fwrite(&hdr.img_bpp, 1, 1, fp);
+       fwrite(&hdr.img_desc, 1, 1, fp);
+
+       /* write the pixels */
+       for(i=0; i<pix_count; i++) {
+               fputc((*pptr >> BLUE_SHIFT32) & 0xff, fp);
+               fputc((*pptr >> GREEN_SHIFT32) & 0xff, fp);
+               fputc((*pptr >> RED_SHIFT32) & 0xff, fp);
+               
+               if(save_flags & IMG_SAVE_ALPHA) {
+                       fputc((*pptr >> ALPHA_SHIFT32) & 0xff, fp);
+               }
+               
+               pptr++;
+       }
+
+       /* write the footer */
+       write_int32_le(fp, ftr.ext_off);
+       write_int32_le(fp, ftr.devdir_off);
+       fputs(ftr.sig, fp);
+       fputc(0, fp);
+
+       fclose(fp);
+       return 0;
+}
+
+/*
+static void print_tga_info(struct tga_header *hdr) {
+       static const char *img_type_str[] = {
+               "no image data",
+               "uncompressed color-mapped",
+               "uncompressed true color",
+               "uncompressed black & white",
+               "", "", "", "", "",
+               "RLE color-mapped",
+               "RLE true color",
+               "RLE black & white"
+       };
+       
+       printf("id field length: %d\n", (int)hdr->idlen);
+       printf("color map present: %s\n", hdr->cmap_type ? "yes" : "no");
+       printf("image type: %s\n", img_type_str[hdr->img_type]);
+       printf("color-map start: %d\n", (int)hdr->cmap_first);
+       printf("color-map length: %d\n", (int)hdr->cmap_len);
+       printf("color-map entry size: %d\n", (int)hdr->cmap_entry_sz);
+       printf("image origin: %d, %d\n", (int)hdr->img_x, (int)hdr->img_y);
+       printf("image size: %d, %d\n", (int)hdr->img_width, (int)hdr->img_height);
+       printf("bpp: %d\n", (int)hdr->img_bpp);
+       printf("attribute bits (alpha/overlay): %d\n", (int)(hdr->img_desc & 0xf));
+       printf("origin: %s-", (hdr->img_desc & 0x20) ? "top" : "bottom");
+       printf("%s\n", (hdr->img_desc & 0x10) ? "right" : "left");
+}
+*/
+
+#endif /* IMGLIB_USE_TGA */
diff --git a/src/3dengfx/src/gfx/img_manip.cpp b/src/3dengfx/src/gfx/img_manip.cpp
new file mode 100644 (file)
index 0000000..9a9e7cc
--- /dev/null
@@ -0,0 +1,579 @@
+/*
+Copyright 2004 John Tsiombikas <nuclear@siggraph.org>
+
+This file is part of the 3dengfx, realtime visualization system.
+
+3dengfx is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+3dengfx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with 3dengfx; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* image manipulation
+ * author: Mihalis Georgoulopoulos 2004
+ * modified: John Tsiombikas 2004
+ */
+
+#include <cstdio>
+#include <cstdlib>
+#include <cmath>
+#include <cstring>
+#include <cctype>
+#include "img_manip.hpp"
+#include "color.hpp"
+#include "common/err_msg.h"
+
+// Macros
+#define PACK_ARGB32(a,r,g,b)   PACK_COLOR32(a,r,g,b)
+
+#define GETA(c)                (((c) >> ALPHA_SHIFT32) & ALPHA_MASK32)
+#define GETR(c)                (((c) >> RED_SHIFT32) & RED_MASK32)
+#define GETG(c)                (((c) >> GREEN_SHIFT32) & GREEN_MASK32)
+#define GETB(c)                (((c) >> BLUE_SHIFT32) & BLUE_MASK32)
+
+static inline scalar_t cerp(scalar_t x0, scalar_t x1, scalar_t x2, scalar_t x3, scalar_t t);
+static inline int clamp_integer(int i, int from, int to);
+
+// ------------ simple operations ----------------
+void clear_pixel_buffer(PixelBuffer *pb, const Color &col) {
+       int sz = pb->width * pb->height;
+       Pixel pcol = pack_color32(col);
+       Pixel *ptr = pb->buffer;
+       
+       for(int i=0; i<sz; i++) {
+               *ptr++ = pcol;
+       }
+}
+
+// ------------ resampling ------------------
+
+static bool resample_line(scalar_t *dst, int dst_width, int dst_pitch, scalar_t *src, int src_width, int src_pitch)
+{
+       if (!dst || !src) return false;
+
+       scalar_t x0,x1,x2,x3,t;
+       int i0,i1,i2,i3;
+       for (int i=0;i<dst_width;i++)
+       {
+               i1 = (i*src_width)/dst_width;
+               i0 = i1 - 1; if(i0 < 0) i0 = 0;
+               i2 = i1 + 1; if(i2 >= src_width) i2 = src_width - 1;
+               i3 = i1 + 2; if(i3 >= src_width) i3 = src_width - 1;
+
+               x0 = src[i0 * src_pitch];
+               x1 = src[i1 * src_pitch];
+               x2 = src[i2 * src_pitch];
+               x3 = src[i3 * src_pitch];
+
+               t = ((scalar_t)i * (scalar_t)src_width) / (scalar_t)dst_width;
+               t -= i1;
+
+               // write the destination element
+               dst[i * dst_pitch] = cerp(x0, x1, x2, x3, t);
+       }
+
+       return true;
+}
+
+static bool resample2d(scalar_t *dst, int dst_w, int dst_h, scalar_t *src, int src_w, int src_h)
+{
+       if (!src || !dst) return false;
+
+       if (dst_w == src_w && dst_h == src_h)
+       {
+               memcpy(dst, src, dst_w * dst_h * sizeof(scalar_t));
+               return true;
+       }
+
+       // first resample along x
+       scalar_t *temp = (scalar_t*)malloc(dst_w * src_h * sizeof(scalar_t));
+
+       if (dst_w == src_w)
+       {
+               memcpy(temp, src, src_w * src_h * sizeof(scalar_t));
+       }
+       else
+       {
+               // horizontal resample
+               for (int i=0;i<src_h;i++)
+               {
+                       resample_line(temp + i*dst_w, dst_w, 1, src + i * src_w, src_w, 1);
+               }
+       }
+
+       // Now temp is stretched horizontally
+       // stretch vertically
+       if (dst_h == src_h)
+       {
+               memcpy(dst, temp, dst_w * dst_h * sizeof(scalar_t));
+       }
+       else
+       {
+               // vertical resample
+               for (int i=0; i<dst_w; i++)
+               {
+                       resample_line(dst+i, dst_h, dst_w, temp + i, src_h, dst_w);
+               }
+       }
+
+       // cleanup
+       free(temp);
+
+       return true;
+}
+
+static bool pack_scalar_rgb2dw(Pixel *dst, scalar_t *ac, scalar_t *rc, scalar_t *gc, scalar_t *bc, int samples)
+{
+       if (!dst || !ac || !rc || !gc || !bc) return false;
+
+       int a, r, g, b;
+
+       for (int i=0;i<samples;i++)
+       {
+               a = (int)(ac[i] + 0.5f);
+               r = (int)(rc[i] + 0.5f);
+               g = (int)(gc[i] + 0.5f);
+               b = (int)(bc[i] + 0.5f);
+
+               a = clamp_integer(a, 0, 255);
+               r = clamp_integer(r, 0, 255);
+               g = clamp_integer(g, 0, 255);
+               b = clamp_integer(b, 0, 255);
+
+               dst[i] = PACK_ARGB32(a, r, g, b);
+       }
+
+       return true;
+}
+
+bool resample_pixel_buffer(PixelBuffer *pb, int w, int h)
+{
+       if (!pb || !pb->buffer || pb->width < 0 || pb->height < 0) return false;
+
+       if ((int)pb->width == w && (int)pb->height == h) return true;
+
+       // split channels
+       scalar_t *a, *newa, *r, *newr, *g, *newg, *b, *newb;
+
+       a = (scalar_t*)malloc(pb->width * pb->height * sizeof(scalar_t));       
+       r = (scalar_t*)malloc(pb->width * pb->height * sizeof(scalar_t));
+       g = (scalar_t*)malloc(pb->width * pb->height * sizeof(scalar_t));
+       b = (scalar_t*)malloc(pb->width * pb->height * sizeof(scalar_t));
+
+       newa = (scalar_t*)malloc(w * h * sizeof(scalar_t));
+       newr = (scalar_t*)malloc(w * h * sizeof(scalar_t));
+       newg = (scalar_t*)malloc(w * h * sizeof(scalar_t));
+       newb = (scalar_t*)malloc(w * h * sizeof(scalar_t));
+
+       for(int i=0; i<(int)(pb->width * pb->height); i++)
+       {
+               a[i] = GETA(pb->buffer[i]);
+               r[i] = GETR(pb->buffer[i]);
+               g[i] = GETG(pb->buffer[i]);
+               b[i] = GETB(pb->buffer[i]);
+       }
+
+       // resample
+       resample2d(newa, w, h, a, pb->width, pb->height);
+       resample2d(newr, w, h, r, pb->width, pb->height);
+       resample2d(newg, w, h, g, pb->width, pb->height);
+       resample2d(newb, w, h, b, pb->width, pb->height);
+
+       // pack
+       Pixel *temp = (Pixel*)malloc(w * h * sizeof(Pixel));
+       pack_scalar_rgb2dw(temp, newa, newr, newg, newb, w * h);
+       free(pb->buffer);
+       pb->buffer = temp;
+       temp = 0;
+       pb->width = w;
+       pb->height = h;
+
+       // cleanup
+       free(a); free(r); free(g); free(b);
+       free(newa); free(newr); free(newg); free(newb);
+
+       return true;
+}
+
+
+// --- static inline functions ---
+
+static inline scalar_t cerp(scalar_t x0, scalar_t x1, scalar_t x2, scalar_t x3, scalar_t t)
+{
+       scalar_t a0, a1, a2, a3, t2;
+
+       t2 = t * t;
+       a0 = x3 - x2 - x0 + x1;
+       a1 = x0 - x1 - a0;
+       a2 = x2 - x0;
+       a3 = x1;
+
+       return(a0 * t * t2 + a1 * t2 + a2 * t + a3);
+}
+
+
+#define MIN(a, b)      ((a) < (b) ? (a) : (b))
+#define MAX(a, b)      ((a) > (b) ? (a) : (b))
+#define CLAMP(n, l, h) MIN(MAX((n), (l)), (h))
+
+static inline int clamp_integer(int i, int from, int to)
+{
+       return CLAMP(i, from, to);
+}
+
+// Kernels
+//----------------------------------------------------------------
+
+static ImgSamplingMode samp_mode = SAMPLE_CLAMP;
+
+static inline int map_index(int c, int dim)
+{
+
+       switch (samp_mode)
+       {
+               case SAMPLE_WRAP:
+               {
+                       if (c < 0) 
+                       {
+                               while(c < 0) c += dim;
+                               return c;
+                       }
+                       if (c >= dim) return c % dim;
+                       break;
+               }
+               case SAMPLE_MIRROR:
+               {
+                       if (c < 0) return -c;
+                       if (c >= dim) return dim - c - 1;
+                       break;
+               }
+
+               case SAMPLE_CLAMP:
+               default:
+               {
+                       if (c < 0) return 0;
+                       if (c >= dim) return dim - 1;
+                       break;
+               }
+       }
+
+       return c;
+}
+
+static void split_channels(Pixel *img, Pixel *a, Pixel *r, Pixel *g, Pixel *b, unsigned int pixel_count)
+{
+       for(unsigned int i=0; i<pixel_count; i++)
+       {
+               *a++ = GETA(*img);
+               *r++ = GETR(*img);
+               *g++ = GETG(*img);
+               *b++ = GETB(*img);
+               img++;
+       }
+}
+
+static void join_channels(Pixel *img, Pixel *a, Pixel *r, Pixel *g, Pixel *b, unsigned int pixel_count)
+{
+       for(unsigned int i=0; i<pixel_count; i++)
+       {
+               *img++ = PACK_ARGB32(*a++, *r++, *g++, *b++);
+       }
+}
+
+static inline Pixel fetch_pixel(int x, int y, Pixel *img, int w, int h)
+{
+       x = map_index(x,w);
+       y = map_index(y,h);
+
+       return img[x+w*y];
+}
+
+static Pixel* apply_kernel_to_channel(int *kernel, int kernel_dim, Pixel *img, int w, int h)
+{
+       // only odd kernels
+       if (!(kernel_dim % 2))  return 0;
+       if (!kernel || !img)  return 0;
+       if ((w <= 0) || (h <= 0)) return 0; 
+
+       int kernel_l = kernel_dim * kernel_dim;
+       int kernel_center = kernel_dim / 2;
+       int kernel_sum = 0;
+       for (int i=0; i<kernel_l; i++)
+       {
+               kernel_sum += kernel[i];
+       }
+
+       // allocate memory
+       Pixel *temp = (Pixel*)malloc(w * h * sizeof(Pixel));
+
+       // pain loop
+       for(int j=0; j<h; j++)
+       {
+               for(int i=0; i<w; i++)
+               {
+                       int sum=0;
+
+                       // kernel loop
+                       for(int kj=0; kj<kernel_dim; kj++)
+                       {
+                               for(int ki=0; ki<kernel_dim; ki++)
+                               {
+                                       int pixel = (int)fetch_pixel(i + ki - kernel_center, j + kj - kernel_center, img, w, h);
+                                       sum += pixel * kernel[ki + kernel_dim * kj];
+                               }
+                       }// end kernel loop
+
+                       if(kernel_sum) {
+                               sum /= kernel_sum;
+                       }
+                       temp[i + j * w] = CLAMP(sum, 0, 255);
+               }
+       } // end pain loop
+
+       return temp;
+}
+
+bool apply_kernel(PixelBuffer *pb, int *kernel, int kernel_dim, ImgSamplingMode sampling)
+{
+       if(!pb || !pb->buffer) return false;
+       if(pb->width <= 0 || pb->height <= 0) return false;
+       if(!(kernel_dim / 2)) return false;
+       
+       unsigned int sz = pb->width * pb->height;
+
+       // set sampling mode
+       samp_mode = sampling;
+
+       // allocate memory
+       Pixel *tempa = (Pixel*)malloc(sz * sizeof(Pixel));
+       Pixel *tempr = (Pixel*)malloc(sz * sizeof(Pixel));
+       Pixel *tempg = (Pixel*)malloc(sz * sizeof(Pixel));
+       Pixel *tempb = (Pixel*)malloc(sz * sizeof(Pixel));
+
+       // split channels
+       split_channels(pb->buffer, tempa, tempr, tempg, tempb, sz);
+
+       // apply kernel
+       Pixel *a = apply_kernel_to_channel(kernel, kernel_dim, tempa, pb->width, pb->height);
+       free(tempa);
+
+       Pixel *r = apply_kernel_to_channel(kernel, kernel_dim, tempr, pb->width, pb->height);
+       free(tempr);
+
+       Pixel *g = apply_kernel_to_channel(kernel, kernel_dim, tempg, pb->width, pb->height);
+       free(tempg);
+
+       Pixel *b = apply_kernel_to_channel(kernel, kernel_dim, tempb, pb->width, pb->height);
+       free(tempb);
+
+       // join channels
+       join_channels(pb->buffer, a, r, g, b, sz);
+
+       free(a);
+       free(r);
+       free(g);
+       free(b);
+
+       return true;
+}
+
+int* load_kernel(const char* filename, int *dim)
+{
+       // try to open the file
+       FILE *input = fopen(filename, "r");
+
+       if (!input) return 0;
+
+       fseek(input , 0 , SEEK_END);
+       int size = ftell(input);
+       fseek(input , 0 , SEEK_SET);
+
+       // allocate memory
+       //char *s = (char*) malloc(size+1);
+
+       char s[2048];
+
+       int i;
+       
+       for(i=0; i<size; i++)
+               s[i] = getc(input);
+
+       s[i] = 0;
+
+       // clear comments and commas
+       int j=0;
+       while (j<size)
+       {
+               if (s[j] == '/')
+               {
+                       while(s[j] != '\n' && s[j] != 0)
+                       {
+                               s[j] = ' ';
+                               j++;
+                       }
+               }
+               else 
+               {
+                       if (s[j]==',') s[j]= ' ';
+                       j++;
+               }
+       }
+
+       // remove everything indeed
+       for(j=0; j<size; j++) {
+               if (s[j] == '\n' || s[j] == '\t') s[j] = ' ';
+       }
+
+       int num;
+       int index = 0;
+       char temp[24];
+
+       int i2=0;
+
+       while(s[index] == ' ') index++;
+       while(s[index] != ' ')
+       {
+               temp[i2] = s[index];
+               index++; i2++;
+       }
+       temp[i2] = 0;
+
+       if(!isdigit(temp[0])) {
+               fclose(input);
+               error("load_kernel() failed, invalid kernel file format: %s\n", filename);
+               return 0;
+       }
+       num = atoi(temp);
+
+       int *kernel = (int*)malloc(num * num * sizeof(int));
+
+       for (int n=0; n<num*num; n++)
+       {
+               i2 = 0;
+
+               while (s[index] == ' ') index++;
+               while (s[index] != ' ')
+               {
+                       temp[i2] = s[index];
+                       index++; i2++;
+               }
+               temp[i2] = 0;
+
+               if(!isdigit(temp[0]) && temp[0] != '-' && temp[0] != '+') {
+                       fclose(input);
+                       free(kernel);
+                       error("load_kernel() failed, invalid kernel file format: %s\n", filename);
+                       return 0;
+               }
+               kernel[n] = atoi(temp);
+       }
+
+       //cleanup
+       fclose(input);
+
+       *dim = num;
+       return kernel;
+}
+
+/* SobelEdge - (JT)
+ * Applies the sobel edge detection algorithm to the pixel buffer
+ */
+bool sobel_edge(PixelBuffer *pb, ImgSamplingMode sampling) {
+       int sobel_horiz[] = {-1, 0, 1, -2, 0, 2, -1, 0, 1};
+       int sobel_vert[] = {-1, -2, -1, 0, 0, 0, 1, 2, 1};
+
+       PixelBuffer horiz = *pb;
+       PixelBuffer vert = *pb;
+
+       if(!apply_kernel(&horiz, sobel_horiz, 3, sampling)) return false;
+       if(!apply_kernel(&vert, sobel_vert, 3, sampling)) return false;
+
+       Pixel *vptr = vert.buffer;
+       Pixel *hptr = horiz.buffer;
+       Pixel *dest = pb->buffer;
+       int sz = pb->width * pb->height;
+
+       for(int i=0; i<sz; i++) {
+               Color vcol = unpack_color32(*vptr++);
+               Color hcol = unpack_color32(*hptr++);
+
+               scalar_t r = sqrt(hcol.r * hcol.r + vcol.r * vcol.r);
+               scalar_t g = sqrt(hcol.g * hcol.g + vcol.g * vcol.g);
+               scalar_t b = sqrt(hcol.b * hcol.b + vcol.b * vcol.b);
+
+               *dest++ = pack_color32(Color(r, g, b));
+       }
+
+       return true;
+}
+
+
+static inline Pixel blur_pixels(Pixel p1, Pixel p2)
+{
+       // static temp colors
+       static Pixel tempc1, tempc2, tempc3, tempc4;
+       
+       // blur all channels in a SIMD-like manner
+       tempc1 = tempc2 = p1;
+       tempc3 = tempc4 = p2;
+
+       // divide by 2
+       // dividing 2 channels with a single operation
+       tempc1 &= 0xff00ff00; tempc1 >>= 1;
+       tempc2 &= 0x00ff00ff; tempc2 >>= 1;
+       tempc3 &= 0xff00ff00; tempc3 >>= 1;
+       tempc4 &= 0x00ff00ff; tempc4 >>= 1;
+
+       tempc1 = (tempc1 + tempc3) & 0xff00ff00;
+       tempc2 = (tempc2 + tempc4) & 0x00ff00ff;
+
+       return tempc1 | tempc2;
+}
+
+
+bool blur(PixelBuffer *pb, ImgSamplingMode sampling)
+{
+       if(!pb) return false;
+       if(pb->width <= 0 || pb->height <= 0) return false;
+
+       samp_mode = sampling;
+
+       Pixel *temp = (Pixel*)malloc(pb->width * pb->height * sizeof(Pixel));
+
+       Pixel *scanline = pb->buffer;
+       Pixel *dst_scanline = temp;
+
+       // blur horizontally
+       for(unsigned int j=0; j<pb->height; j++)
+       {
+               for(unsigned int i=0; i<pb->width; i++)
+               {
+                       dst_scanline[i] = blur_pixels(scanline[map_index(i-1 , pb->width)], scanline[map_index(i+1 , pb->width)]);
+               }       
+               scanline += pb->width;
+               dst_scanline += pb->width;
+       }
+
+       // blur vertically
+       for(unsigned int i=0; i<pb->width; i++)
+       {
+               for(unsigned int j=0;j<pb->height;j++)
+               {
+                       pb->buffer[i+j*pb->width] = blur_pixels(temp[i+map_index(j-1,pb->height)*pb->width], temp[i+map_index(j+1,pb->height)*pb->width]);
+               }
+       }
+
+       // cleanup
+       free(temp);     
+
+       return true;
+}
diff --git a/src/3dengfx/src/gfx/img_manip.hpp b/src/3dengfx/src/gfx/img_manip.hpp
new file mode 100644 (file)
index 0000000..26f7290
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+Copyright 2004 John Tsiombikas <nuclear@siggraph.org>
+
+This file is part of the 3dengfx, realtime visualization system.
+
+3dengfx is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+3dengfx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with 3dengfx; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#ifndef _IMG_MANIP_HPP_
+#define _IMG_MANIP_HPP_
+
+/* image manipulation
+ * author: Mihalis Georgoulopoulos 2004
+ * modified: John Tsiombikas 2004
+ */
+
+#include "pbuffer.hpp"
+#include "color.hpp"
+#include "3dengfx/3denginefx_types.hpp"
+#include "n3dmath2/n3dmath2_types.hpp"
+
+enum ImgSamplingMode {SAMPLE_CLAMP, SAMPLE_WRAP, SAMPLE_MIRROR};
+
+void clear_pixel_buffer(PixelBuffer *pb, const Color &col);
+
+bool resample_pixel_buffer(PixelBuffer *pb, int w, int h);
+bool apply_kernel(PixelBuffer *pb, int *kernel, int kernel_dim, ImgSamplingMode sampling = SAMPLE_CLAMP);
+int* load_kernel(const char* filename, int *dim);
+
+// filters
+bool sobel_edge(PixelBuffer *pb, ImgSamplingMode sampling = SAMPLE_CLAMP);
+bool blur(PixelBuffer *pb, ImgSamplingMode sampling = SAMPLE_CLAMP);
+
+#endif // _IMG_MANIP_HPP_
diff --git a/src/3dengfx/src/gfx/makefile.part b/src/3dengfx/src/gfx/makefile.part
new file mode 100644 (file)
index 0000000..6e0cb08
--- /dev/null
@@ -0,0 +1,15 @@
+gfx_obj = \
+       src/gfx/3dgeom.o\
+       src/gfx/animation.o\
+       src/gfx/controller.o\
+       src/gfx/timeline.o\
+       src/gfx/base_cam.o\
+       src/gfx/curves.o\
+       src/gfx/color.o\
+       src/gfx/image.o\
+       src/gfx/image_png.o\
+       src/gfx/image_jpg.o\
+       src/gfx/image_tga.o\
+       src/gfx/image_ppm.o\
+       src/gfx/img_manip.o\
+       src/gfx/bvol.o
diff --git a/src/3dengfx/src/gfx/pbuffer.hpp b/src/3dengfx/src/gfx/pbuffer.hpp
new file mode 100644 (file)
index 0000000..e7db8e5
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+Copyright 2004 John Tsiombikas <nuclear@siggraph.org>
+
+This file is part of the graphics core library.
+
+the graphics core library is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+the graphics core library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with the graphics core library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#ifndef _PBUFFER_HPP_
+#define _PBUFFER_HPP_
+
+#include "common/byteorder.h"
+
+template <class T>
+class Buffer {
+public:
+       T *buffer;
+       unsigned long width, height, pitch;
+       
+       Buffer();
+       Buffer(unsigned long x, unsigned long y);
+       Buffer(const Buffer &b);
+       ~Buffer();
+};
+
+typedef uint32_t Pixel;
+typedef Buffer<Pixel> PixelBuffer;
+
+// implementation
+
+template <class T>
+Buffer<T>::Buffer() {
+       buffer = 0;
+}
+
+template <class T>
+Buffer<T>::Buffer(unsigned long x, unsigned long y) {
+       width = x;
+       height = y;
+       pitch = width * sizeof(T);
+       
+       buffer = new T[width * height];
+}
+
+template <class T>
+Buffer<T>::Buffer(const Buffer<T> &b) {
+       *this = b;
+       buffer = new T[width * height];
+       memcpy(buffer, b.buffer, pitch * height);
+}
+
+template <class T>
+Buffer<T>::~Buffer() {
+       if(buffer) delete [] buffer;
+}
+
+#endif // _PBUFFER_HPP_
diff --git a/src/3dengfx/src/gfx/timeline.cpp b/src/3dengfx/src/gfx/timeline.cpp
new file mode 100644 (file)
index 0000000..fbce4f3
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+This file is part of the graphics core library.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "timeline.hpp"
+
+template <class T>
+static inline T wrap(T n, T low, T high) {
+       n -= low;
+       
+       while(n < 0) {
+               n += high;
+       }
+       if(high) n %= high;
+       
+       return n + low;
+}
+
+template <class T>
+static inline T bounce(T n, T low, T high) {
+       T interval = high - low;
+       T offs = n % interval;
+       
+       if((n / interval) % 2) {
+               // descent
+               return high - offs;
+       } else {
+               return low + offs;
+       }
+}
+
+
+unsigned long get_timeline_time(unsigned long time, unsigned long start, unsigned long end, TimelineMode mode) {
+       switch(mode) {
+       case TIME_WRAP:
+               time = wrap(time, start, end);
+               break;
+
+       case TIME_BOUNCE:
+               time = bounce(time, start, end);
+               break;
+
+       case TIME_CLAMP:
+               if(time < start) time = start;
+               if(time > end) time = end;
+               break;
+
+       case TIME_FREE:
+       default:
+               break;
+       }
+
+       return time;
+}
+
diff --git a/src/3dengfx/src/gfx/timeline.hpp b/src/3dengfx/src/gfx/timeline.hpp
new file mode 100644 (file)
index 0000000..586f32c
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+This file is part of the graphics core library.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef _TIMELINE_HPP_
+#define _TIMELINE_HPP_
+
+enum TimelineMode {TIME_WRAP, TIME_CLAMP, TIME_FREE, TIME_BOUNCE};
+
+unsigned long get_timeline_time(unsigned long time, unsigned long start, unsigned long end, TimelineMode mode);
+
+#endif // _TIMELINE_HPP_
diff --git a/src/3dengfx/src/n3dmath2/makefile.part b/src/3dengfx/src/n3dmath2/makefile.part
new file mode 100644 (file)
index 0000000..d676ae4
--- /dev/null
@@ -0,0 +1,8 @@
+n3dmath2_obj =\
+       src/n3dmath2/n3dmath2.o\
+       src/n3dmath2/n3dmath2_mat.o\
+       src/n3dmath2/n3dmath2_vec.o\
+       src/n3dmath2/n3dmath2_qua.o\
+       src/n3dmath2/n3dmath2_ray.o\
+       src/n3dmath2/n3dmath2_qdr.o\
+       src/n3dmath2/n3dmath2_sph.o
diff --git a/src/3dengfx/src/n3dmath2/n3dmath2.cpp b/src/3dengfx/src/n3dmath2/n3dmath2.cpp
new file mode 100644 (file)
index 0000000..791df24
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+This file is part of the n3dmath2 library.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+The n3dmath2 library is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+The n3dmath2 library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with the n3dmath2 library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "n3dmath2.hpp"
+
+const scalar_t e = 2.7182818;
+
+const scalar_t pi = 3.1415926535897932;
+const scalar_t half_pi = pi / 2.0;
+const scalar_t quarter_pi = pi / 4.0;
+const scalar_t two_pi = pi * 2.0;
+const scalar_t three_half_pi = 3.0 * pi / 2.0;
+
+const scalar_t xsmall_number = 1.e-8;
+const scalar_t small_number = 1.e-4;
+
+const scalar_t error_margin = 1.e-6;
+
+
+scalar_t frand(scalar_t range) {
+       return range * (float)rand() / (float)RAND_MAX;
+}
+
+scalar_t integral(scalar_t (*f)(scalar_t), scalar_t low, scalar_t high, int samples)  {
+       scalar_t h = (high - low) / (scalar_t)samples;
+       scalar_t sum = 0.0;
+       
+       for(int i=0; i<samples+1; i++) {
+               scalar_t y = f((scalar_t)i * h + low);
+               sum += ((!i || i == samples) ? y : ((i%2) ? 4.0 * y : 2.0 * y)) * (h / 3.0);
+       }
+       return sum;
+}
+
+scalar_t gaussian(scalar_t x, scalar_t mean, scalar_t sdev) {
+       scalar_t exponent = -SQ(x - mean) / (2.0 * SQ(sdev));
+       
+       return 1.0 - -pow(e, exponent) / (sdev * sqrt(two_pi));
+}
+
+
+// -- b-spline approximation --
+scalar_t bspline(const Vector4 &cpvec, scalar_t t) {
+       Matrix4x4 bspline_mat(  -1,  3, -3,  1,
+                                                        3, -6,  3,  0,
+                                                       -3,  0,  3,  0,
+                                                        1,  4,  1,  0);
+       
+       scalar_t t_square = t * t;
+       scalar_t t_cube = t_square * t;
+       Vector4 params(t_cube, t_square, t, 1.0);
+
+       return dot_product(params, cpvec.transformed(bspline_mat) / 6.0);
+}
+
+// -- catmull rom spline interpolation --
+scalar_t catmull_rom_spline(const Vector4 &cpvec, scalar_t t) {
+       Matrix4x4 crspline_mat( -1,  3, -3,  1,
+                                                        2, -5,  4, -1,
+                                                       -1,  0,  1,  0,
+                                                        0,  2,  0,  0);
+
+       scalar_t t_square = t * t;
+       scalar_t t_cube = t_square * t;
+       Vector4 params(t_cube, t_square, t, 1.0);
+
+       return dot_product(params, cpvec.transformed(crspline_mat) / 2.0);
+}
+
+/* Bezier - (MG)
+ * returns a interpolated scalar value
+ * given 4 control values 
+ */
+scalar_t bezier(const Vector4 &cp, scalar_t t)
+{
+       static scalar_t omt, omt3, t3, f;
+       t3 = t * t * t;
+       omt = 1.0f - t;
+       omt3 = omt * omt * omt;
+       f = 3 * t * omt;
+
+       return (cp.x * omt3) + (cp.y * f * omt) + (cp.z * f * t) + (cp.w * t3);
+}
+
+/* Bezier - (MG)
+ * Vector3 overloaded bezier function
+ */
+Vector3 bezier(const Vector3 &p0, const Vector3 &p1, const Vector3 &p2, const Vector3 &p3, scalar_t t)
+{
+       static scalar_t omt, omt3, t3, f;
+       t3 = t * t * t;
+       omt = 1.0f - t;
+       omt3 = omt * omt * omt;
+       f = 3 * t * omt;
+
+       return (p0 * omt3) + (p1 * f * omt) + (p2 * f * t) + (p3 * t3);
+}
+
+/* BezierTangent
+ * returns a vector tangent to the 
+ * Bezier curve at the specified point
+ */
+Vector3 bezier_tangent(const Vector3 &p0, const Vector3 &p1, const Vector3 &p2, const Vector3 &p3, scalar_t t)
+{
+       static scalar_t omt;
+       omt = 1.0f - t;
+       static Vector3 p4, p5, p6, p7, p8;
+       p4 = p0 * omt + p1 * t;
+       p5 = p1 * omt + p2 * t;
+       p6 = p2 * omt + p3 * t;
+
+       p7 = p4 * omt + p5 * t;
+       p8 = p5 * omt + p6 * t;
+
+       return p8 - p7;
+}
+
+
+// -- point / line distance in 2D --
+scalar_t dist_line(const Vector2 &p1, const Vector2 &p2, const Vector2 &p) {
+       if(p1.x == p2.x && p1.y == p2.y) return 0;      // avoid div/zero
+       scalar_t t = dot_product(p - p1, p2 - p1) / (p2 - p1).length_sq();
+
+       Vector2 pt = p1 + (p2 - p1) * t;
+       return (p - pt).length();
+}
+
+
+Basis::Basis() {
+       i = Vector3(1, 0, 0);
+       j = Vector3(0, 1, 0);
+       k = Vector3(0, 0, 1);
+}
+
+Basis::Basis(const Vector3 &i, const Vector3 &j, const Vector3 &k) {
+       this->i = i;
+       this->j = j;
+       this->k = k;
+}
+
+Basis::Basis(const Vector3 &dir, bool LeftHanded) {
+       k = dir;
+       j = VECTOR3_J;
+       i = cross_product(j, k);
+       j = cross_product(k, i);
+}
+
+
+void Basis::rotate(scalar_t x, scalar_t y, scalar_t z) {
+       Matrix4x4 RotMat;
+       RotMat.set_rotation(Vector3(x, y, z));
+       i.transform(RotMat);
+       j.transform(RotMat);
+       k.transform(RotMat);
+}
+
+void Basis::rotate(const Vector3 &axis, scalar_t angle) {
+       Quaternion q;
+       q.set_rotation(axis, angle);
+       i.transform(q);
+       j.transform(q);
+       k.transform(q);
+}
+
+void Basis::rotate(const Matrix4x4 &mat) {
+       i.transform(mat);
+       j.transform(mat);
+       k.transform(mat);
+}
+
+void Basis::rotate(const Quaternion &quat) {
+       i.transform(quat);
+       j.transform(quat);
+       k.transform(quat);
+}
+
+Matrix3x3 Basis::create_rotation_matrix() const {
+       return Matrix3x3(       i.x, j.x, k.x,
+                                               i.y, j.y, k.y,
+                                               i.z, j.z, k.z);
+}
+
+
+//////////////
+
+size_t size_of_scalar_type() {
+       static const scalar_t temp = 0.0;
+       return sizeof(temp);
+}
+
+
diff --git a/src/3dengfx/src/n3dmath2/n3dmath2.hpp b/src/3dengfx/src/n3dmath2/n3dmath2.hpp
new file mode 100644 (file)
index 0000000..59f59d3
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+Copyright 2004 John Tsiombikas <nuclear@siggraph.org>
+
+This file is part of the n3dmath2 library.
+
+The n3dmath2 library is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+The n3dmath2 library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with the n3dmath2 library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef _N3DMATH2_HPP_
+#define _N3DMATH2_HPP_
+
+#include <math.h>
+#include "n3dmath2_types.hpp"
+
+extern const scalar_t e;
+
+extern const scalar_t pi;
+extern const scalar_t half_pi;
+extern const scalar_t quarter_pi;
+extern const scalar_t two_pi;
+extern const scalar_t three_half_pi;
+
+extern const scalar_t xsmall_number;
+extern const scalar_t small_number;
+
+extern const scalar_t error_margin;
+
+
+// basis vectors
+#define VECTOR3_I      (Vector3(1.0, 0.0, 0.0))
+#define VECTOR3_J      (Vector3(0.0, 1.0, 0.0))
+#define VECTOR3_K      (Vector3(0.0, 0.0, 1.0))
+
+#define VECTOR2_I      (Vector2(1.0, 0.0))
+#define VECTOR2_J      (Vector2(0.0, 1.0))
+
+// angle conversion
+#define RAD_TO_DEG(a) ((((scalar_t)a) * 360.0) / two_pi)
+//#define DEG_TO_RAD(a) ((((scalar_t)a) * two_pi) / 360.0)
+#define DEG_TO_RAD(a) (((scalar_t)a) * (pi / 180.0))
+
+#define SQ(x) ((x) * (x))
+
+#ifndef __GLIBC__
+#define round(x)       ((x) >= 0 ? (x) + 0.5 : (x) - 0.5)
+#endif // __GLIBC__
+
+// -- mathematical & helper functions --
+scalar_t frand(scalar_t range);
+scalar_t integral(scalar_t (*f)(scalar_t), scalar_t low, scalar_t high, int samples);
+scalar_t gaussian(scalar_t x, scalar_t mean, scalar_t sdev);
+
+// -- interpolation and approximation --
+inline scalar_t lerp(scalar_t a, scalar_t b, scalar_t t);
+
+scalar_t bspline(const Vector4 &cpvec, scalar_t t);
+inline scalar_t bspline(scalar_t a, scalar_t b, scalar_t c, scalar_t d, scalar_t t);
+
+scalar_t catmull_rom_spline(const Vector4 &cpvec, scalar_t t);
+inline scalar_t catmull_rom_spline(scalar_t a, scalar_t b, scalar_t c, scalar_t d, scalar_t t);
+
+scalar_t bezier(const Vector4 &cp, scalar_t t);
+Vector3 bezier(const Vector3 &p0, const Vector3 &p1, const Vector3 &p2, const Vector3 &p3, scalar_t t);
+Vector3 bezier_tangent(const Vector3 &p0, const Vector3 &p1, const Vector3 &p2, const Vector3 &p3, scalar_t t);
+
+// -- point / line distance in 2D --
+scalar_t dist_line(const Vector2 &p1, const Vector2 &p2, const Vector2 &p);
+
+// -- actual class definitions --
+#include "n3dmath2_vec.hpp"
+#include "n3dmath2_mat.hpp"
+#include "n3dmath2_qua.hpp"
+#include "n3dmath2_sph.hpp"
+#include "n3dmath2_ray.hpp"
+#include "n3dmath2_qdr.hpp"
+
+class Basis {
+public:
+       Vector3 i, j, k;
+
+       Basis();
+       Basis(const Vector3 &i, const Vector3 &j, const Vector3 &k);
+       Basis(const Vector3 &dir, bool LeftHanded=true);
+
+       void rotate(scalar_t x, scalar_t y, scalar_t z);
+       void rotate(const Vector3 &axis, scalar_t angle);
+       void rotate(const Matrix4x4 &mat);
+       void rotate(const Quaternion &quat);
+
+       Matrix3x3 create_rotation_matrix() const;
+};
+
+
+// bad ugly hack
+size_t size_of_scalar_type();
+
+#include "n3dmath2.inl"
+
+#endif // _N3DMATH2_HPP_
diff --git a/src/3dengfx/src/n3dmath2/n3dmath2.inl b/src/3dengfx/src/n3dmath2/n3dmath2.inl
new file mode 100644 (file)
index 0000000..9a1a298
--- /dev/null
@@ -0,0 +1,12 @@
+
+inline scalar_t lerp(scalar_t a, scalar_t b, scalar_t t) {
+       return a + (b - a) * t;
+}
+
+inline scalar_t bspline(scalar_t a, scalar_t b, scalar_t c, scalar_t d, scalar_t t) {
+       return bspline(Vector4(a, b, c, d), t);
+}
+
+inline scalar_t catmull_rom_spline(scalar_t a, scalar_t b, scalar_t c, scalar_t d, scalar_t t) {
+       return catmull_rom_spline(Vector4(a, b, c, d), t);
+}
diff --git a/src/3dengfx/src/n3dmath2/n3dmath2_mat.cpp b/src/3dengfx/src/n3dmath2/n3dmath2_mat.cpp
new file mode 100644 (file)
index 0000000..640f33b
--- /dev/null
@@ -0,0 +1,699 @@
+/*
+This file is part of the n3dmath2 library.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+The n3dmath2 library is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+The n3dmath2 library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with the n3dmath2 library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <cstdio>
+#include <cmath>
+#include "n3dmath2_mat.hpp"
+
+using namespace std;
+
+// ----------- Matrix3x3 --------------
+
+Matrix3x3 Matrix3x3::identity_matrix = Matrix3x3(1, 0, 0, 0, 1, 0, 0, 0, 1);
+
+Matrix3x3::Matrix3x3() {
+       *this = identity_matrix;
+}
+
+Matrix3x3::Matrix3x3(  scalar_t m11, scalar_t m12, scalar_t m13,
+                                               scalar_t m21, scalar_t m22, scalar_t m23,
+                                               scalar_t m31, scalar_t m32, scalar_t m33) {
+       m[0][0] = m11; m[0][1] = m12; m[0][2] = m13;
+       m[1][0] = m21; m[1][1] = m22; m[1][2] = m23;
+       m[2][0] = m31; m[2][1] = m32; m[2][2] = m33;
+       //memcpy(m, &m11, 9 * sizeof(scalar_t));        // args are adjacent in the stack
+}
+
+Matrix3x3::Matrix3x3(const Matrix4x4 &mat4x4) {
+       for(int i=0; i<3; i++) {
+               for(int j=0; j<3; j++) {
+                       m[i][j] = mat4x4[i][j];
+               }
+       }
+}
+
+Matrix3x3 operator +(const Matrix3x3 &m1, const Matrix3x3 &m2) {
+       Matrix3x3 res;
+       const scalar_t *op1 = m1.m[0], *op2 = m2.m[0];
+       scalar_t *dest = res.m[0];
+       
+       for(int i=0; i<9; i++) {
+               *dest++ = *op1++ + *op2++;
+       }
+       return res;
+}
+
+Matrix3x3 operator -(const Matrix3x3 &m1, const Matrix3x3 &m2) {
+       Matrix3x3 res;
+       const scalar_t *op1 = m1.m[0], *op2 = m2.m[0];
+       scalar_t *dest = res.m[0];
+       
+       for(int i=0; i<9; i++) {
+               *dest++ = *op1++ - *op2++;
+       }
+       return res;
+}
+
+Matrix3x3 operator *(const Matrix3x3 &m1, const Matrix3x3 &m2) {
+       Matrix3x3 res;
+       for(int i=0; i<3; i++) {
+               for(int j=0; j<3; j++) {
+                       res.m[i][j] = m1.m[i][0] * m2.m[0][j] + m1.m[i][1] * m2.m[1][j] + m1.m[i][2] * m2.m[2][j];
+               }
+       }
+       return res;
+}
+
+void operator +=(Matrix3x3 &m1, const Matrix3x3 &m2) {
+       scalar_t *op1 = m1.m[0];
+       const scalar_t *op2 = m2.m[0];
+       
+       for(int i=0; i<9; i++) {
+               *op1++ += *op2++;
+       }
+}
+
+void operator -=(Matrix3x3 &m1, const Matrix3x3 &m2) {
+       scalar_t *op1 = m1.m[0];
+       const scalar_t *op2 = m2.m[0];
+       
+       for(int i=0; i<9; i++) {
+               *op1++ -= *op2++;
+       }
+}
+
+void operator *=(Matrix3x3 &m1, const Matrix3x3 &m2) {
+       Matrix3x3 res;
+       for(int i=0; i<3; i++) {
+               for(int j=0; j<3; j++) {
+                       res.m[i][j] = m1.m[i][0] * m2.m[0][j] + m1.m[i][1] * m2.m[1][j] + m1.m[i][2] * m2.m[2][j];
+               }
+       }
+       memcpy(m1.m, res.m, 9 * sizeof(scalar_t));
+}
+
+Matrix3x3 operator *(const Matrix3x3 &mat, scalar_t scalar) {
+       Matrix3x3 res;
+       const scalar_t *mptr = mat.m[0];
+       scalar_t *dptr = res.m[0];
+       
+       for(int i=0; i<9; i++) {
+               *dptr++ = *mptr++ * scalar;
+       }
+       return res;
+}
+
+Matrix3x3 operator *(scalar_t scalar, const Matrix3x3 &mat) {
+       Matrix3x3 res;
+       const scalar_t *mptr = mat.m[0];
+       scalar_t *dptr = res.m[0];
+       
+       for(int i=0; i<9; i++) {
+               *dptr++ = *mptr++ * scalar;
+       }
+       return res;
+}
+
+void operator *=(Matrix3x3 &mat, scalar_t scalar) {
+       scalar_t *mptr = mat.m[0];
+       
+       for(int i=0; i<9; i++) {
+               *mptr++ *= scalar;
+       }
+}
+
+void Matrix3x3::translate(const Vector2 &trans) {
+       Matrix3x3 tmat(1, 0, trans.x, 0, 1, trans.y, 0, 0, 1);
+       *this *= tmat;
+}
+
+void Matrix3x3::set_translation(const Vector2 &trans) {
+       *this = Matrix3x3(1, 0, trans.x, 0, 1, trans.y, 0, 0, 1);
+}
+
+void Matrix3x3::rotate(scalar_t angle) {
+       scalar_t cos_a = cos(angle);
+       scalar_t sin_a = sin(angle);
+       Matrix3x3 rmat( cos_a,  -sin_a,         0,
+                                       sin_a,  cos_a,          0,
+                                       0,              0,                      1);
+       *this *= rmat;
+}
+
+void Matrix3x3::set_rotation(scalar_t angle) {
+       scalar_t cos_a = cos(angle);
+       scalar_t sin_a = sin(angle);
+       *this = Matrix3x3(cos_a, -sin_a, 0, sin_a, cos_a, 0, 0, 0, 1);
+}
+
+void Matrix3x3::rotate(const Vector3 &euler_angles) {
+       Matrix3x3 xrot, yrot, zrot;
+       
+       xrot = Matrix3x3(       1,                      0,                                      0,
+                                               0,      cos(euler_angles.x),    -sin(euler_angles.x),
+                                               0,      sin(euler_angles.x),    cos(euler_angles.x));
+       
+       yrot = Matrix3x3(       cos(euler_angles.y),    0,      sin(euler_angles.y),
+                                                               0,                              1,                              0,
+                                               -sin(euler_angles.y),   0,      cos(euler_angles.y));
+       
+       zrot = Matrix3x3(       cos(euler_angles.z),    -sin(euler_angles.z),   0,
+                                               sin(euler_angles.z),    cos(euler_angles.z),    0,
+                                                               0,                                              0,                              1);
+       
+       *this *= xrot * yrot * zrot;
+}
+
+void Matrix3x3::set_rotation(const Vector3 &euler_angles) {
+       Matrix3x3 xrot, yrot, zrot;
+       
+       xrot = Matrix3x3(       1,                      0,                                      0,
+                                               0,      cos(euler_angles.x),    -sin(euler_angles.x),
+                                               0,      sin(euler_angles.x),    cos(euler_angles.x));
+       
+       yrot = Matrix3x3(       cos(euler_angles.y),    0,      sin(euler_angles.y),
+                                                               0,                              1,                              0,
+                                               -sin(euler_angles.y),   0,      cos(euler_angles.y));
+       
+       zrot = Matrix3x3(       cos(euler_angles.z),    -sin(euler_angles.z),   0,
+                                               sin(euler_angles.z),    cos(euler_angles.z),    0,
+                                                               0,                                              0,                              1);
+       
+       *this = xrot * yrot * zrot;
+}
+
+void Matrix3x3::rotate(const Vector3 &axis, scalar_t angle) {
+       scalar_t sina = (scalar_t)sin(angle);
+       scalar_t cosa = (scalar_t)cos(angle);
+       scalar_t invcosa = 1-cosa;
+       scalar_t nxsq = axis.x * axis.x;
+       scalar_t nysq = axis.y * axis.y;
+       scalar_t nzsq = axis.z * axis.z;
+
+       Matrix3x3 xform;
+       xform.m[0][0] = nxsq + (1-nxsq) * cosa;
+       xform.m[0][1] = axis.x * axis.y * invcosa - axis.z * sina;
+       xform.m[0][2] = axis.x * axis.z * invcosa + axis.y * sina;
+       xform.m[1][0] = axis.x * axis.y * invcosa + axis.z * sina;
+       xform.m[1][1] = nysq + (1-nysq) * cosa;
+       xform.m[1][2] = axis.y * axis.z * invcosa - axis.x * sina;
+       xform.m[2][0] = axis.x * axis.z * invcosa - axis.y * sina;
+       xform.m[2][1] = axis.y * axis.z * invcosa + axis.x * sina;
+       xform.m[2][2] = nzsq + (1-nzsq) * cosa;
+
+       *this *= xform;
+}
+
+void Matrix3x3::set_rotation(const Vector3 &axis, scalar_t angle) {
+       scalar_t sina = (scalar_t)sin(angle);
+       scalar_t cosa = (scalar_t)cos(angle);
+       scalar_t invcosa = 1-cosa;
+       scalar_t nxsq = axis.x * axis.x;
+       scalar_t nysq = axis.y * axis.y;
+       scalar_t nzsq = axis.z * axis.z;
+
+       reset_identity();
+       m[0][0] = nxsq + (1-nxsq) * cosa;
+       m[0][1] = axis.x * axis.y * invcosa - axis.z * sina;
+       m[0][2] = axis.x * axis.z * invcosa + axis.y * sina;
+       m[1][0] = axis.x * axis.y * invcosa + axis.z * sina;
+       m[1][1] = nysq + (1-nysq) * cosa;
+       m[1][2] = axis.y * axis.z * invcosa - axis.x * sina;
+       m[2][0] = axis.x * axis.z * invcosa - axis.y * sina;
+       m[2][1] = axis.y * axis.z * invcosa + axis.x * sina;
+       m[2][2] = nzsq + (1-nzsq) * cosa;
+}
+
+void Matrix3x3::scale(const Vector3 &scale_vec) {
+       Matrix3x3 smat( scale_vec.x, 0, 0,
+                                       0, scale_vec.y, 0,
+                                       0, 0, scale_vec.z);
+       *this *= smat;
+}
+
+void Matrix3x3::set_scaling(const Vector3 &scale_vec) {
+       *this = Matrix3x3(      scale_vec.x, 0, 0,
+                                               0, scale_vec.y, 0,
+                                               0, 0, scale_vec.z);
+}
+
+void Matrix3x3::set_column_vector(const Vector3 &vec, unsigned int col_index) {
+       m[0][col_index] = vec.x;
+       m[1][col_index] = vec.y;
+       m[2][col_index] = vec.z;
+}
+
+void Matrix3x3::set_row_vector(const Vector3 &vec, unsigned int row_index) {
+       m[row_index][0] = vec.x;
+       m[row_index][1] = vec.y;
+       m[row_index][2] = vec.z;
+}
+
+Vector3 Matrix3x3::get_column_vector(unsigned int col_index) const {
+       return Vector3(m[0][col_index], m[1][col_index], m[2][col_index]);
+}
+
+Vector3 Matrix3x3::get_row_vector(unsigned int row_index) const {
+       return Vector3(m[row_index][0], m[row_index][1], m[row_index][2]);
+}
+
+void Matrix3x3::transpose() {
+       Matrix3x3 tmp = *this;
+       for(int i=0; i<3; i++) {
+               for(int j=0; j<3; j++) {
+                       m[i][j] = tmp[j][i];
+               }
+       }
+}
+
+Matrix3x3 Matrix3x3::transposed() const {
+       Matrix3x3 res;
+       for(int i=0; i<3; i++) {
+               for(int j=0; j<3; j++) {
+                       res[i][j] = m[j][i];
+               }
+       }
+       return res;
+}
+
+scalar_t Matrix3x3::determinant() const {
+       return  m[0][0] * (m[1][1]*m[2][2] - m[1][2]*m[2][1]) -
+                       m[0][1] * (m[1][0]*m[2][2] - m[1][2]*m[2][0]) +
+                       m[0][2] * (m[1][0]*m[2][1] - m[1][1]*m[2][0]);
+}
+
+Matrix3x3 Matrix3x3::inverse() const {
+       // TODO: implement 3x3 inverse
+       return *this;
+}
+
+ostream &operator <<(ostream &out, const Matrix3x3 &mat) {
+       for(int i=0; i<3; i++) {
+               char str[100];
+               sprintf(str, "[ %12.5f %12.5f %12.5f ]\n", (float)mat.m[i][0], (float)mat.m[i][1], (float)mat.m[i][2]);
+               out << str;
+       }
+       return out;
+}
+
+
+
+////////////////////// Matrix4x4 implementation ///////////////////////
+
+Matrix4x4 Matrix4x4::identity_matrix = Matrix4x4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
+
+Matrix4x4::Matrix4x4() {
+       *this = identity_matrix;
+}
+
+Matrix4x4::Matrix4x4(  scalar_t m11, scalar_t m12, scalar_t m13, scalar_t m14,
+                                               scalar_t m21, scalar_t m22, scalar_t m23, scalar_t m24,
+                                               scalar_t m31, scalar_t m32, scalar_t m33, scalar_t m34,
+                                               scalar_t m41, scalar_t m42, scalar_t m43, scalar_t m44) {
+       m[0][0] = m11; m[0][1] = m12; m[0][2] = m13; m[0][3] = m14;
+       m[1][0] = m21; m[1][1] = m22; m[1][2] = m23; m[1][3] = m24;
+       m[2][0] = m31; m[2][1] = m32; m[2][2] = m33; m[2][3] = m34;
+       m[3][0] = m41; m[3][1] = m42; m[3][2] = m43; m[3][3] = m44;
+       //memcpy(m, &m11, 16 * sizeof(scalar_t));       // args are adjacent in the stack
+       
+       glmatrix = 0;
+}
+
+Matrix4x4::Matrix4x4(const Matrix3x3 &mat3x3) {
+       reset_identity();
+       for(int i=0; i<3; i++) {
+               for(int j=0; j<3; j++) {
+                       m[i][j] = mat3x3[i][j];
+               }
+       }
+
+       glmatrix = 0;
+}
+
+Matrix4x4::~Matrix4x4() {
+       if(glmatrix) delete [] glmatrix;
+}
+
+Matrix4x4 operator +(const Matrix4x4 &m1, const Matrix4x4 &m2) {
+       Matrix4x4 res;
+       const scalar_t *op1 = m1.m[0], *op2 = m2.m[0];
+       scalar_t *dest = res.m[0];
+       
+       for(int i=0; i<16; i++) {
+               *dest++ = *op1++ + *op2++;
+       }
+       return res;
+}
+
+Matrix4x4 operator -(const Matrix4x4 &m1, const Matrix4x4 &m2) {
+       Matrix4x4 res;
+       const scalar_t *op1 = m1.m[0], *op2 = m2.m[0];
+       scalar_t *dest = res.m[0];
+       
+       for(int i=0; i<16; i++) {
+               *dest++ = *op1++ - *op2++;
+       }
+       return res;
+}
+
+Matrix4x4 operator *(const Matrix4x4 &m1, const Matrix4x4 &m2) {
+       Matrix4x4 res;
+       
+       for(int i=0; i<4; i++) {
+               for(int j=0; j<4; j++) {
+                       res.m[i][j] = m1.m[i][0] * m2.m[0][j] + m1.m[i][1] * m2.m[1][j] + m1.m[i][2] * m2.m[2][j] + m1.m[i][3] * m2.m[3][j];
+               }
+       }
+
+       return res;
+}
+
+void operator +=(Matrix4x4 &m1, const Matrix4x4 &m2) {
+       scalar_t *op1 = m1.m[0];
+       const scalar_t *op2 = m2.m[0];
+       
+       for(int i=0; i<16; i++) {
+               *op1++ += *op2++;
+       }
+}
+
+void operator -=(Matrix4x4 &m1, const Matrix4x4 &m2) {
+       scalar_t *op1 = m1.m[0];
+       const scalar_t *op2 = m2.m[0];
+       
+       for(int i=0; i<16; i++) {
+               *op1++ -= *op2++;
+       }
+}
+
+void operator *=(Matrix4x4 &m1, const Matrix4x4 &m2) {
+       Matrix4x4 res;
+       
+       for(int i=0; i<4; i++) {
+               for(int j=0; j<4; j++) {
+                       res.m[i][j] = m1.m[i][0] * m2.m[0][j] + m1.m[i][1] * m2.m[1][j] + m1.m[i][2] * m2.m[2][j] + m1.m[i][3] * m2.m[3][j];
+               }
+       }
+
+       memcpy(m1.m, res.m, 16 * sizeof(scalar_t));
+}
+
+Matrix4x4 operator *(const Matrix4x4 &mat, scalar_t scalar) {
+       Matrix4x4 res;
+       const scalar_t *mptr = mat.m[0];
+       scalar_t *dptr = res.m[0];
+       
+       for(int i=0; i<16; i++) {
+               *dptr++ = *mptr++ * scalar;
+       }
+       return res;
+}
+
+Matrix4x4 operator *(scalar_t scalar, const Matrix4x4 &mat) {
+       Matrix4x4 res;
+       const scalar_t *mptr = mat.m[0];
+       scalar_t *dptr = res.m[0];
+       
+       for(int i=0; i<16; i++) {
+               *dptr++ = *mptr++ * scalar;
+       }
+       return res;
+}
+
+void operator *=(Matrix4x4 &mat, scalar_t scalar) {
+       scalar_t *mptr = mat.m[0];
+       
+       for(int i=0; i<16; i++) {
+               *mptr++ *= scalar;
+       }
+}
+
+void Matrix4x4::translate(const Vector3 &trans) {
+       Matrix4x4 tmat(1, 0, 0, trans.x, 0, 1, 0, trans.y, 0, 0, 1, trans.z, 0, 0, 0, 1);
+       *this *= tmat;
+}
+
+void Matrix4x4::set_translation(const Vector3 &trans) {
+       *this = Matrix4x4(1, 0, 0, trans.x, 0, 1, 0, trans.y, 0, 0, 1, trans.z, 0, 0, 0, 1);
+}
+
+void Matrix4x4::rotate(const Vector3 &euler_angles) {
+       Matrix3x3 xrot, yrot, zrot;
+       
+       xrot = Matrix3x3(       1,                      0,                                      0,
+                                               0,      cos(euler_angles.x),    -sin(euler_angles.x),
+                                               0,      sin(euler_angles.x),    cos(euler_angles.x));
+       
+       yrot = Matrix3x3(       cos(euler_angles.y),    0,      sin(euler_angles.y),
+                                                               0,                              1,                              0,
+                                               -sin(euler_angles.y),   0,      cos(euler_angles.y));
+       
+       zrot = Matrix3x3(       cos(euler_angles.z),    -sin(euler_angles.z),   0,
+                                               sin(euler_angles.z),    cos(euler_angles.z),    0,
+                                                               0,                                              0,                              1);
+       
+       *this *= Matrix4x4(xrot * yrot * zrot);
+}
+
+void Matrix4x4::set_rotation(const Vector3 &euler_angles) {
+       Matrix3x3 xrot, yrot, zrot;
+       
+       xrot = Matrix3x3(       1,                      0,                                      0,
+                                               0,      cos(euler_angles.x),    -sin(euler_angles.x),
+                                               0,      sin(euler_angles.x),    cos(euler_angles.x));
+       
+       yrot = Matrix3x3(       cos(euler_angles.y),    0,      sin(euler_angles.y),
+                                                               0,                              1,                              0,
+                                               -sin(euler_angles.y),   0,      cos(euler_angles.y));
+       
+       zrot = Matrix3x3(       cos(euler_angles.z),    -sin(euler_angles.z),   0,
+                                               sin(euler_angles.z),    cos(euler_angles.z),    0,
+                                                               0,                                              0,                              1);
+       
+       *this = Matrix4x4(xrot * yrot * zrot);
+}
+
+void Matrix4x4::rotate(const Vector3 &axis, scalar_t angle) {
+       scalar_t sina = (scalar_t)sin(angle);
+       scalar_t cosa = (scalar_t)cos(angle);
+       scalar_t invcosa = 1-cosa;
+       scalar_t nxsq = axis.x * axis.x;
+       scalar_t nysq = axis.y * axis.y;
+       scalar_t nzsq = axis.z * axis.z;
+
+       Matrix3x3 xform;
+       xform[0][0] = nxsq + (1-nxsq) * cosa;
+       xform[0][1] = axis.x * axis.y * invcosa - axis.z * sina;
+       xform[0][2] = axis.x * axis.z * invcosa + axis.y * sina;
+       xform[1][0] = axis.x * axis.y * invcosa + axis.z * sina;
+       xform[1][1] = nysq + (1-nysq) * cosa;
+       xform[1][2] = axis.y * axis.z * invcosa - axis.x * sina;
+       xform[2][0] = axis.x * axis.z * invcosa - axis.y * sina;
+       xform[2][1] = axis.y * axis.z * invcosa + axis.x * sina;
+       xform[2][2] = nzsq + (1-nzsq) * cosa;
+
+       *this *= Matrix4x4(xform);
+}
+
+void Matrix4x4::set_rotation(const Vector3 &axis, scalar_t angle) {
+       scalar_t sina = (scalar_t)sin(angle);
+       scalar_t cosa = (scalar_t)cos(angle);
+       scalar_t invcosa = 1-cosa;
+       scalar_t nxsq = axis.x * axis.x;
+       scalar_t nysq = axis.y * axis.y;
+       scalar_t nzsq = axis.z * axis.z;
+
+       reset_identity();
+       m[0][0] = nxsq + (1-nxsq) * cosa;
+       m[0][1] = axis.x * axis.y * invcosa - axis.z * sina;
+       m[0][2] = axis.x * axis.z * invcosa + axis.y * sina;
+       m[1][0] = axis.x * axis.y * invcosa + axis.z * sina;
+       m[1][1] = nysq + (1-nysq) * cosa;
+       m[1][2] = axis.y * axis.z * invcosa - axis.x * sina;
+       m[2][0] = axis.x * axis.z * invcosa - axis.y * sina;
+       m[2][1] = axis.y * axis.z * invcosa + axis.x * sina;
+       m[2][2] = nzsq + (1-nzsq) * cosa;
+}
+
+void Matrix4x4::scale(const Vector4 &scale_vec) {
+       Matrix4x4 smat( scale_vec.x, 0, 0, 0,
+                                       0, scale_vec.y, 0, 0,
+                                       0, 0, scale_vec.z, 0,
+                                       0, 0, 0, scale_vec.w);
+       *this *= smat;
+}
+
+void Matrix4x4::set_scaling(const Vector4 &scale_vec) {
+       *this = Matrix4x4(      scale_vec.x, 0, 0, 0,
+                                               0, scale_vec.y, 0, 0,
+                                               0, 0, scale_vec.z, 0,
+                                               0, 0, 0, scale_vec.w);
+}
+
+void Matrix4x4::set_column_vector(const Vector4 &vec, unsigned int col_index) {
+       m[0][col_index] = vec.x;
+       m[1][col_index] = vec.y;
+       m[2][col_index] = vec.z;
+       m[3][col_index] = vec.w;
+}
+
+void Matrix4x4::set_row_vector(const Vector4 &vec, unsigned int row_index) {
+       m[row_index][0] = vec.x;
+       m[row_index][1] = vec.y;
+       m[row_index][2] = vec.z;
+       m[row_index][3] = vec.w;
+}
+
+Vector4 Matrix4x4::get_column_vector(unsigned int col_index) const {
+       return Vector4(m[0][col_index], m[1][col_index], m[2][col_index], m[3][col_index]);
+}
+
+Vector4 Matrix4x4::get_row_vector(unsigned int row_index) const {
+       return Vector4(m[row_index][0], m[row_index][1], m[row_index][2], m[row_index][3]);
+}
+
+void Matrix4x4::transpose() {
+       Matrix4x4 tmp = *this;
+       for(int i=0; i<4; i++) {
+               for(int j=0; j<4; j++) {
+                       m[i][j] = tmp[j][i];
+               }
+       }
+}
+
+Matrix4x4 Matrix4x4::transposed() const {
+       Matrix4x4 res;
+       for(int i=0; i<4; i++) {
+               for(int j=0; j<4; j++) {
+                       res[i][j] = m[j][i];
+               }
+       }
+       return res;
+}
+
+scalar_t Matrix4x4::determinant() const {
+
+       scalar_t det11 =        (m[1][1] * (m[2][2] * m[3][3] - m[3][2] * m[2][3])) -
+                                               (m[1][2] * (m[2][1] * m[3][3] - m[3][1] * m[2][3])) +
+                                               (m[1][3] * (m[2][1] * m[3][2] - m[3][1] * m[2][2]));
+
+       scalar_t det12 =        (m[1][0] * (m[2][2] * m[3][3] - m[3][2] * m[2][3])) -
+                                               (m[1][2] * (m[2][0] * m[3][3] - m[3][0] * m[2][3])) +
+                                               (m[1][3] * (m[2][0] * m[3][2] - m[3][0] * m[2][2]));
+
+       scalar_t det13 =        (m[1][0] * (m[2][1] * m[3][3] - m[3][1] * m[2][3])) -
+                                               (m[1][1] * (m[2][0] * m[3][3] - m[3][0] * m[2][3])) +
+                                               (m[1][3] * (m[2][0] * m[3][1] - m[3][0] * m[2][1]));
+
+       scalar_t det14 =        (m[1][0] * (m[2][1] * m[3][2] - m[3][1] * m[2][2])) -
+                                               (m[1][1] * (m[2][0] * m[3][2] - m[3][0] * m[2][2])) +
+                                               (m[1][2] * (m[2][0] * m[3][1] - m[3][0] * m[2][1]));
+
+       return m[0][0] * det11 - m[0][1] * det12 + m[0][2] * det13 - m[0][3] * det14;
+}
+
+
+Matrix4x4 Matrix4x4::adjoint() const {
+
+       Matrix4x4 coef;
+
+       coef.m[0][0] =  (m[1][1] * (m[2][2] * m[3][3] - m[3][2] * m[2][3])) -
+                                       (m[1][2] * (m[2][1] * m[3][3] - m[3][1] * m[2][3])) +
+                                       (m[1][3] * (m[2][1] * m[3][2] - m[3][1] * m[2][2]));
+       coef.m[0][1] =  (m[1][0] * (m[2][2] * m[3][3] - m[3][2] * m[2][3])) -
+                                       (m[1][2] * (m[2][0] * m[3][3] - m[3][0] * m[2][3])) +
+                                       (m[1][3] * (m[2][0] * m[3][2] - m[3][0] * m[2][2]));
+       coef.m[0][2] =  (m[1][0] * (m[2][1] * m[3][3] - m[3][1] * m[2][3])) -
+                                       (m[1][1] * (m[2][0] * m[3][3] - m[3][0] * m[2][3])) +
+                                       (m[1][3] * (m[2][0] * m[3][1] - m[3][0] * m[2][1]));
+       coef.m[0][3] =  (m[1][0] * (m[2][1] * m[3][2] - m[3][1] * m[2][2])) -
+                                       (m[1][1] * (m[2][0] * m[3][2] - m[3][0] * m[2][2])) +
+                                       (m[1][2] * (m[2][0] * m[3][1] - m[3][0] * m[2][1]));
+
+       coef.m[1][0] =  (m[0][1] * (m[2][2] * m[3][3] - m[3][2] * m[2][3])) -
+                                       (m[0][2] * (m[2][1] * m[3][3] - m[3][1] * m[2][3])) +
+                                       (m[0][3] * (m[2][1] * m[3][2] - m[3][1] * m[2][2]));
+       coef.m[1][1] =  (m[0][0] * (m[2][2] * m[3][3] - m[3][2] * m[2][3])) -
+                                       (m[0][2] * (m[2][0] * m[3][3] - m[3][0] * m[2][3])) +
+                                       (m[0][3] * (m[2][0] * m[3][2] - m[3][0] * m[2][2]));
+       coef.m[1][2] =  (m[0][0] * (m[2][1] * m[3][3] - m[3][1] * m[2][3])) -
+                                       (m[0][1] * (m[2][0] * m[3][3] - m[3][0] * m[2][3])) +
+                                       (m[0][3] * (m[2][0] * m[3][1] - m[3][0] * m[2][1]));
+       coef.m[1][3] =  (m[0][0] * (m[2][1] * m[3][2] - m[3][1] * m[2][2])) -
+                                       (m[0][1] * (m[2][0] * m[3][2] - m[3][0] * m[2][2])) +
+                                       (m[0][2] * (m[2][0] * m[3][1] - m[3][0] * m[2][1]));
+
+       coef.m[2][0] =  (m[0][1] * (m[1][2] * m[3][3] - m[3][2] * m[1][3])) -
+                                       (m[0][2] * (m[1][1] * m[3][3] - m[3][1] * m[1][3])) +
+                                       (m[0][3] * (m[1][1] * m[3][2] - m[3][1] * m[1][2]));
+       coef.m[2][1] =  (m[0][0] * (m[1][2] * m[3][3] - m[3][2] * m[1][3])) -
+                                       (m[0][2] * (m[1][0] * m[3][3] - m[3][0] * m[1][3])) +
+                                       (m[0][3] * (m[1][0] * m[3][2] - m[3][0] * m[1][2]));
+       coef.m[2][2] =  (m[0][0] * (m[1][1] * m[3][3] - m[3][1] * m[1][3])) -
+                                       (m[0][1] * (m[1][0] * m[3][3] - m[3][0] * m[1][3])) +
+                                       (m[0][3] * (m[1][0] * m[3][1] - m[3][0] * m[1][1]));
+       coef.m[2][3] =  (m[0][0] * (m[1][1] * m[3][2] - m[3][1] * m[1][2])) -
+                                       (m[0][1] * (m[1][0] * m[3][2] - m[3][0] * m[1][2])) +
+                                       (m[0][2] * (m[1][0] * m[3][1] - m[3][0] * m[1][1]));
+
+       coef.m[3][0] =  (m[0][1] * (m[1][2] * m[2][3] - m[2][2] * m[1][3])) -
+                                       (m[0][2] * (m[1][1] * m[2][3] - m[2][1] * m[1][3])) +
+                                       (m[0][3] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]));
+       coef.m[3][1] =  (m[0][0] * (m[1][2] * m[2][3] - m[2][2] * m[1][3])) -
+                                       (m[0][2] * (m[1][0] * m[2][3] - m[2][0] * m[1][3])) +
+                                       (m[0][3] * (m[1][0] * m[2][2] - m[2][0] * m[1][2]));
+       coef.m[3][2] =  (m[0][0] * (m[1][1] * m[2][3] - m[2][1] * m[1][3])) -
+                                       (m[0][1] * (m[1][0] * m[2][3] - m[2][0] * m[1][3])) +
+                                       (m[0][3] * (m[1][0] * m[2][1] - m[2][0] * m[1][1]));
+       coef.m[3][3] =  (m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2])) -
+                                       (m[0][1] * (m[1][0] * m[2][2] - m[2][0] * m[1][2])) +
+                                       (m[0][2] * (m[1][0] * m[2][1] - m[2][0] * m[1][1]));
+
+       coef.transpose();
+
+       for(int i=0; i<4; i++) {
+               for(int j=0; j<4; j++) {
+                       coef.m[i][j] = j%2 ? -coef.m[i][j] : coef.m[i][j];
+                       if(i%2) coef.m[i][j] = -coef.m[i][j];
+               }
+       }
+
+       return coef;
+}
+
+Matrix4x4 Matrix4x4::inverse() const {
+
+       Matrix4x4 AdjMat = adjoint();
+
+       return AdjMat * (1.0f / determinant());
+}
+
+const scalar_t *Matrix4x4::opengl_matrix() const {
+       return (const scalar_t*)m;
+}
+
+ostream &operator <<(ostream &out, const Matrix4x4 &mat) {
+       for(int i=0; i<4; i++) {
+               char str[100];
+               sprintf(str, "[ %12.5f %12.5f %12.5f %12.5f ]\n", (float)mat.m[i][0], (float)mat.m[i][1], (float)mat.m[i][2], (float)mat.m[i][3]);
+               out << str;
+       }
+       return out;
+}
diff --git a/src/3dengfx/src/n3dmath2/n3dmath2_mat.hpp b/src/3dengfx/src/n3dmath2/n3dmath2_mat.hpp
new file mode 100644 (file)
index 0000000..630832a
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+Copyright 2004 John Tsiombikas <nuclear@siggraph.org>
+
+This file is part of the n3dmath2 library.
+
+The n3dmath2 library is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+The n3dmath2 library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with the n3dmath2 library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef _N3DMATH2_MAT_HPP_
+#define _N3DMATH2_MAT_HPP_
+
+#include "n3dmath2.hpp"
+
+class Matrix3x3 {
+private:
+       scalar_t m[3][3];
+public:
+       
+       static Matrix3x3 identity_matrix;
+
+       Matrix3x3();
+       Matrix3x3(      scalar_t m11, scalar_t m12, scalar_t m13,
+                               scalar_t m21, scalar_t m22, scalar_t m23,
+                               scalar_t m31, scalar_t m32, scalar_t m33);
+       
+       Matrix3x3(const Matrix4x4 &mat4x4);
+       
+       // binary operations matrix (op) matrix
+       friend Matrix3x3 operator +(const Matrix3x3 &m1, const Matrix3x3 &m2);
+       friend Matrix3x3 operator -(const Matrix3x3 &m1, const Matrix3x3 &m2);
+       friend Matrix3x3 operator *(const Matrix3x3 &m1, const Matrix3x3 &m2);
+       
+       friend void operator +=(Matrix3x3 &m1, const Matrix3x3 &m2);
+       friend void operator -=(Matrix3x3 &m1, const Matrix3x3 &m2);
+       friend void operator *=(Matrix3x3 &m1, const Matrix3x3 &m2);
+       
+       // binary operations matrix (op) scalar and scalar (op) matrix
+       friend Matrix3x3 operator *(const Matrix3x3 &mat, scalar_t scalar);
+       friend Matrix3x3 operator *(scalar_t scalar, const Matrix3x3 &mat);
+       
+       friend void operator *=(Matrix3x3 &mat, scalar_t scalar);
+       
+       inline scalar_t *operator [](int index);
+       inline const scalar_t *operator [](int index) const;
+       
+       inline void reset_identity();
+       
+       void translate(const Vector2 &trans);
+       void set_translation(const Vector2 &trans);
+       
+       void rotate(scalar_t angle);                                            // 2d rotation
+       void rotate(const Vector3 &euler_angles);                       // 3d rotation with euler angles
+       void rotate(const Vector3 &axis, scalar_t angle);       // 3d axis/angle rotation
+       void set_rotation(scalar_t angle);
+       void set_rotation(const Vector3 &euler_angles);
+       void set_rotation(const Vector3 &axis, scalar_t angle);
+       
+       void scale(const Vector3 &scale_vec);
+       void set_scaling(const Vector3 &scale_vec);
+       
+       void set_column_vector(const Vector3 &vec, unsigned int col_index);
+       void set_row_vector(const Vector3 &vec, unsigned int row_index);
+       Vector3 get_column_vector(unsigned int col_index) const;
+       Vector3 get_row_vector(unsigned int row_index) const;
+
+       void transpose();
+       Matrix3x3 transposed() const;   
+       scalar_t determinant() const;
+       Matrix3x3 inverse() const;
+       
+       friend std::ostream &operator <<(std::ostream &out, const Matrix3x3 &mat);
+};
+
+
+class Matrix4x4 {
+private:
+       scalar_t m[4][4];
+       mutable float *glmatrix;
+public:
+       
+       static Matrix4x4 identity_matrix;
+
+       Matrix4x4();
+       Matrix4x4(      scalar_t m11, scalar_t m12, scalar_t m13, scalar_t m14,
+                               scalar_t m21, scalar_t m22, scalar_t m23, scalar_t m24,
+                               scalar_t m31, scalar_t m32, scalar_t m33, scalar_t m34,
+                               scalar_t m41, scalar_t m42, scalar_t m43, scalar_t m44);
+       
+       Matrix4x4(const Matrix3x3 &mat3x3);
+       ~Matrix4x4();
+       
+       // binary operations matrix (op) matrix
+       friend Matrix4x4 operator +(const Matrix4x4 &m1, const Matrix4x4 &m2);
+       friend Matrix4x4 operator -(const Matrix4x4 &m1, const Matrix4x4 &m2);
+       friend Matrix4x4 operator *(const Matrix4x4 &m1, const Matrix4x4 &m2);
+       
+       friend void operator +=(Matrix4x4 &m1, const Matrix4x4 &m2);
+       friend void operator -=(Matrix4x4 &m1, const Matrix4x4 &m2);
+       friend void operator *=(Matrix4x4 &m1, const Matrix4x4 &m2);
+       
+       // binary operations matrix (op) scalar and scalar (op) matrix
+       friend Matrix4x4 operator *(const Matrix4x4 &mat, scalar_t scalar);
+       friend Matrix4x4 operator *(scalar_t scalar, const Matrix4x4 &mat);
+       
+       friend void operator *=(Matrix4x4 &mat, scalar_t scalar);
+       
+       inline scalar_t *operator [](int index);
+       inline const scalar_t *operator [](int index) const;
+       
+       inline void reset_identity();
+       
+       void translate(const Vector3 &trans);
+       void set_translation(const Vector3 &trans);
+       
+       void rotate(const Vector3 &euler_angles);                       // 3d rotation with euler angles
+       void rotate(const Vector3 &axis, scalar_t angle);       // 3d axis/angle rotation
+       void set_rotation(const Vector3 &euler_angles);
+       void set_rotation(const Vector3 &axis, scalar_t angle);
+       
+       void scale(const Vector4 &scale_vec);
+       void set_scaling(const Vector4 &scale_vec);
+       
+       void set_column_vector(const Vector4 &vec, unsigned int col_index);
+       void set_row_vector(const Vector4 &vec, unsigned int row_index);
+       Vector4 get_column_vector(unsigned int col_index) const;
+       Vector4 get_row_vector(unsigned int row_index) const;
+       
+       void transpose();
+       Matrix4x4 transposed() const;
+       scalar_t determinant() const;
+       Matrix4x4 adjoint() const;
+       Matrix4x4 inverse() const;
+       
+       const scalar_t *opengl_matrix() const;
+               
+       friend std::ostream &operator <<(std::ostream &out, const Matrix4x4 &mat);
+};
+
+#include "n3dmath2_mat.inl"
+
+#endif // _N3DMATH2_MAT_HPP_
diff --git a/src/3dengfx/src/n3dmath2/n3dmath2_mat.inl b/src/3dengfx/src/n3dmath2/n3dmath2_mat.inl
new file mode 100644 (file)
index 0000000..2350cd3
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+Copyright 2004 John Tsiombikas <nuclear@siggraph.org>
+
+This file is part of the n3dmath2 library.
+
+The n3dmath2 library is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+The n3dmath2 library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with the n3dmath2 library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#include <string.h>
+
+inline scalar_t *Matrix3x3::operator [](int index) {
+       return m[index];
+}
+
+inline const scalar_t *Matrix3x3::operator [](int index) const {
+       return m[index];
+}
+
+inline void Matrix3x3::reset_identity() {
+       memcpy(this->m, identity_matrix.m, 9 * sizeof(scalar_t));
+}
+
+inline scalar_t *Matrix4x4::operator [](int index) {
+       return m[index];
+}
+
+inline const scalar_t *Matrix4x4::operator [](int index) const {
+       return m[index];
+}
+
+inline void Matrix4x4::reset_identity() {
+       memcpy(this->m, identity_matrix.m, 16 * sizeof(scalar_t));
+}
diff --git a/src/3dengfx/src/n3dmath2/n3dmath2_qdr.cpp b/src/3dengfx/src/n3dmath2/n3dmath2_qdr.cpp
new file mode 100644 (file)
index 0000000..63950b6
--- /dev/null
@@ -0,0 +1,258 @@
+/*
+This file is part of the n3dmath2 library.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+The n3dmath2 library is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+The n3dmath2 library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with the n3dmath2 library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "n3dmath2_qdr.hpp"
+
+Surface::Surface(const Vector3 &pos) {
+       this->pos = pos;
+}
+
+Surface::~Surface() {}
+
+void Surface::set_position(const Vector3 &pos) {
+       this->pos = pos;
+}
+
+Vector3 Surface::get_position() const {
+       return pos;
+}
+
+void Surface::set_rotation(const Quaternion &rot) {
+       this->rot = rot;
+}
+
+Quaternion Surface::get_rotation() const {
+       return rot;
+}
+
+//////////////// sphere implementation ///////////////
+
+Sphere::Sphere(const Vector3 &pos, scalar_t rad) : Surface(pos) {
+       radius = rad;
+}
+
+Sphere::~Sphere() {}
+
+void Sphere::set_radius(scalar_t rad) {
+       radius = rad;
+}
+
+scalar_t Sphere::get_radius() const {
+       return radius;
+}
+
+Vector2 Sphere::inv_map(const Vector3 &pt) const {
+       Vector3 normal = (pt - pos) / radius;
+       Vector3 pole = Vector3(0, 1, 0).transformed(rot);
+       Vector3 equator = Vector3(0, 0, 1).transformed(rot);
+       Vector2 imap;
+
+       scalar_t phi = acos(dot_product(normal, pole));
+       imap.y = phi / pi;
+
+       if(imap.y < xsmall_number || 1.0 - imap.y < xsmall_number) {
+               imap.x = 0.0;
+               return imap;
+       }
+
+       scalar_t theta = acos(dot_product(equator, normal) / sin(phi)) / two_pi;
+       
+       imap.x = (dot_product(cross_product(pole, equator), normal) < 0.0) ? theta : 1.0 - theta;
+
+       return imap;
+}
+
+bool Sphere::check_intersection(const Ray &ray) const {
+       return find_intersection(ray, 0);
+}
+
+bool Sphere::find_intersection(const Ray &ray, SurfPoint *isect) const {       
+       // find terms of the quadratic equation
+       scalar_t a = SQ(ray.dir.x) + SQ(ray.dir.y) + SQ(ray.dir.z);
+       scalar_t b = 2.0 * ray.dir.x * (ray.origin.x - pos.x) +
+                               2.0 * ray.dir.y * (ray.origin.y - pos.y) +
+                               2.0 * ray.dir.z * (ray.origin.z - pos.z);
+       scalar_t c = SQ(pos.x) + SQ(pos.y) + SQ(pos.z) +
+                               SQ(ray.origin.x) + SQ(ray.origin.y) + SQ(ray.origin.z) +
+                               2.0 * (-pos.x * ray.origin.x - pos.y * ray.origin.y - pos.z * ray.origin.z) - SQ(radius);
+       
+       // find the discriminant
+       scalar_t d = SQ(b) - 4.0 * a * c;
+       if(d < 0.0) return false;
+       
+       // solve
+       scalar_t sqrt_d = sqrt(d);
+       scalar_t t1 = (-b + sqrt_d) / (2.0 * a);
+       scalar_t t2 = (-b - sqrt_d) / (2.0 * a);
+
+       if(t1 < error_margin && t2 < error_margin) return false;
+
+       if(isect) {
+               if(t1 < error_margin) t1 = t2;
+               if(t2 < error_margin) t2 = t1;
+               isect->t = t1 < t2 ? t1 : t2;
+               isect->pos = ray.origin + ray.dir * isect->t;
+
+               isect->normal = (isect->pos - pos) / radius;
+               isect->pre_ior = ray.ior;
+               //isect->post_ior = mat.ior;
+       }
+
+       return true;
+}
+
+
+Plane::Plane(const Vector3 &pos, const Vector3 &normal) : Surface(pos) {
+       this->normal = normal;
+}
+
+Plane::Plane(const Vector3 &p1, const Vector3 &p2, const Vector3 &p3) : Surface(p1)
+{
+       normal = cross_product(p2 - p1, p3 - p1).normalized();
+}
+
+Plane::~Plane() {}
+
+void Plane::set_normal(const Vector3 &normal) {
+       this->normal = normal;
+}
+
+Vector3 Plane::get_normal() const {
+       return normal;
+}
+
+Vector2 Plane::inv_map(const Vector3 &pt) const {
+       static int dbg; dbg++;
+       if(dbg == 1) std::cerr << "inverse mapping for planes not implemented yet!\n";
+       return Vector2(0, 0);
+}
+
+bool Plane::check_intersection(const Ray &ray) const {
+       return find_intersection(ray, 0);
+}
+
+bool Plane::find_intersection(const Ray &ray, SurfPoint *isect) const {
+       scalar_t normal_dot_dir = dot_product(normal, ray.dir);
+       if(fabs(normal_dot_dir) < error_margin) return false;
+       
+       // TODO: this is only correct if pos is the projection of the origin on the plane
+       scalar_t d = pos.length();
+       
+       scalar_t t = -(dot_product(normal, ray.origin) + d) / normal_dot_dir;
+
+       if(t < error_margin) return false;
+
+       if(isect) {
+               isect->pos = ray.origin + ray.dir * t;
+               isect->normal = normal;
+               isect->t = t;
+               isect->pre_ior = ray.ior;
+               //isect->post_ior = mat.ior;
+       }
+       return true;
+}
+
+
+Box::Box(const Vector3 &min_vec, const Vector3 &max_vec) {
+       verts[0] = Vector3(min_vec.x, max_vec.y, min_vec.z);
+       verts[1] = Vector3(max_vec.x, max_vec.y, min_vec.z);
+       verts[2] = Vector3(max_vec.x, min_vec.y, min_vec.z);
+       verts[3] = Vector3(min_vec.x, min_vec.y, min_vec.z);
+
+       verts[4] = Vector3(min_vec.x, max_vec.y, max_vec.z);
+       verts[5] = Vector3(max_vec.x, max_vec.y, max_vec.z);
+       verts[6] = Vector3(max_vec.x, min_vec.y, max_vec.z);
+       verts[7] = Vector3(min_vec.x, min_vec.y, max_vec.z);
+}
+
+Box::Box(const Vector3 &v0, const Vector3 &v1, const Vector3 &v2, const Vector3 &v3,
+               const Vector3 &v4, const Vector3 &v5, const Vector3 &v6, const Vector3 &v7) {
+       verts[0] = v0;
+       verts[1] = v1;
+       verts[2] = v2;
+       verts[3] = v3;
+       verts[4] = v4;
+       verts[5] = v5;
+       verts[6] = v6;
+       verts[7] = v7;
+}
+
+Box::Box(const Vector3 *array) {
+       memcpy(verts, array, sizeof verts);
+}
+
+Vector2 Box::inv_map(const Vector3 &pt) const {
+       return Vector2();       // TODO: implement
+}
+
+bool Box::check_intersection(const Ray &ray) const {
+       return false;   // TODO: implement
+}
+
+bool Box::find_intersection(const Ray &ray, SurfPoint *isect) const {
+       return false;   // TODO: implement
+}
+
+
+/*
+ * PointOverPlane (MG)
+ * returns true if the point is in the positive side of the
+ * plane
+ */
+bool point_over_plane(const Plane &plane, const Vector3 &point)
+{
+       if (dot_product(plane.get_position() - point, plane.get_normal()) < 0)
+       {
+               return true;
+       }
+
+       return false;
+}
+
+
+static inline bool check_correct_winding(const Vector3 &v0, const Vector3 &v1, const Vector3 &v2, const Vector3 &normal) {
+       Vector3 tri_normal = cross_product(v1 - v0, v2 - v0);
+       return dot_product(tri_normal, normal) > 0.0;
+}
+
+
+bool check_tri_ray_intersection(const Vector3 &v0, const Vector3 &v1, const Vector3 &v2, const Ray &ray) {
+       // find the cosine of the angle between the normal and the line
+       Vector3 normal = cross_product(v1 - v0, v2 - v0);
+       scalar_t dot = dot_product(normal, ray.dir);
+               
+       if(fabs(dot) < small_number) {
+               return false;
+       }
+
+       // further testing to verify intersection in the area of the triangle
+       scalar_t t = -(normal.x*(ray.origin.x - v0.x) + normal.y*(ray.origin.y - v0.y) + normal.z*(ray.origin.z - v0.z)) / (normal.x * ray.dir.x + normal.y * ray.dir.y + normal.z * ray.dir.z);
+       if(t > small_number) {
+               Vector3 intersect(ray.origin.x + ray.dir.x*t, ray.origin.y + ray.dir.y*t, ray.origin.z + ray.dir.z*t);
+
+               if(check_correct_winding(v0, v1, intersect, normal)
+                       && check_correct_winding(v1, v2, intersect, normal)
+                       && check_correct_winding(v2, v0, intersect, normal)) {
+                       return true;
+               }
+       }
+
+       return false;
+}
diff --git a/src/3dengfx/src/n3dmath2/n3dmath2_qdr.hpp b/src/3dengfx/src/n3dmath2/n3dmath2_qdr.hpp
new file mode 100644 (file)
index 0000000..a743305
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+This file is part of the n3dmath2 library.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+The n3dmath2 library is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+The n3dmath2 library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with the n3dmath2 library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef _N3DMATH2_QDR_HPP_
+#define _N3DMATH2_QDR_HPP_
+
+#include "n3dmath2.hpp"
+
+/* used to store intersections of a ray on the surface
+ * of a quadratic object
+ */
+struct SurfPoint {
+       Vector3 pos, normal;            // position and normal of surface at this position
+       scalar_t t;                                     // parametric distance of intersection along ray
+       scalar_t pre_ior, post_ior;     // obviously these come handy with raytracing
+};
+
+// Abstract base class for surfaces
+class Surface {
+protected:
+       Vector3 pos;
+       Quaternion rot;
+
+public:
+       Surface(const Vector3 &pos=Vector3(0,0,0));
+       virtual ~Surface();
+
+       virtual void set_position(const Vector3 &pos);
+       virtual Vector3 get_position() const;
+
+       virtual void set_rotation(const Quaternion &rot);
+       virtual Quaternion get_rotation() const;
+
+       virtual Vector2 inv_map(const Vector3 &pt) const = 0;
+       
+       virtual bool check_intersection(const Ray &ray) const = 0;
+       virtual bool find_intersection(const Ray &ray, SurfPoint *isect) const = 0;
+};
+
+// sphere (x² + y² + z² = r²)
+class Sphere : public Surface {
+protected:
+       scalar_t radius;
+       
+public:
+       Sphere(const Vector3 &pos=Vector3(0,0,0), scalar_t rad=1.0);
+       virtual ~Sphere();
+
+       virtual void set_radius(scalar_t rad);
+       virtual scalar_t get_radius() const;
+       
+       virtual Vector2 inv_map(const Vector3 &pt) const;
+       
+       virtual bool check_intersection(const Ray &ray) const;
+       virtual bool find_intersection(const Ray &ray, SurfPoint *isect) const;
+};
+
+// plane (ax + by + cz + d = 0)
+class Plane : public Surface {
+protected:
+       Vector3 normal;
+       
+public:
+       Plane(const Vector3 &pos=Vector3(0,0,0), const Vector3 &normal=Vector3(0,0,-1));
+       Plane(const Vector3 &p1, const Vector3 &p2, const Vector3 &p3);
+       virtual ~Plane();
+
+       virtual void set_normal(const Vector3 &normal);
+       virtual Vector3 get_normal() const;
+       
+       virtual Vector2 inv_map(const Vector3 &pt) const;
+       
+       virtual bool check_intersection(const Ray &ray) const;
+       virtual bool find_intersection(const Ray &ray, SurfPoint *isect) const;
+};
+
+class Box : public Surface {
+protected:
+       Vector3 verts[8];
+
+public:
+       Box(const Vector3 &min_vec = Vector3(-1,-1,-1), const Vector3 &max_vec = Vector3(1,1,1));
+       Box(const Vector3 &v0, const Vector3 &v1, const Vector3 &v2, const Vector3 &v3,
+               const Vector3 &v4, const Vector3 &v5, const Vector3 &v6, const Vector3 &v7);
+       Box(const Vector3 *array);
+
+       virtual Vector2 inv_map(const Vector3 &pt) const;
+
+       virtual bool check_intersection(const Ray &ray) const;
+       virtual bool find_intersection(const Ray &ray, SurfPoint *isect) const;
+};
+
+// utility functions
+bool point_over_plane(const Plane &plane, const Vector3 &point);
+bool check_tri_ray_intersection(const Vector3 &v1, const Vector3 &v2, const Vector3 &v3, const Ray &ray);
+
+#endif // _N3DMATH2_QDR_HPP_
diff --git a/src/3dengfx/src/n3dmath2/n3dmath2_qua.cpp b/src/3dengfx/src/n3dmath2/n3dmath2_qua.cpp
new file mode 100644 (file)
index 0000000..4178a5c
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+This file is part of the n3dmath2 library.
+
+Copyright (c) 2003 - 2005 John Tsiombikas <nuclear@siggraph.org>
+
+The n3dmath2 library is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+The n3dmath2 library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with the n3dmath2 library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* quaterinion math
+ *
+ * Author: John Tsiombikas 2003
+ * Modified: John Tsiombikas 2004, 2005
+ */
+
+#include "n3dmath2.hpp"
+
+Quaternion::Quaternion() {
+       s = 1.0;
+       v.x = v.y = v.z = 0.0;
+}
+
+Quaternion::Quaternion(scalar_t s, scalar_t x, scalar_t y, scalar_t z) {
+       v.x = x;
+       v.y = y;
+       v.z = z;
+       this->s = s;
+}
+
+Quaternion::Quaternion(scalar_t s, const Vector3 &v) {
+       this->s = s;
+       this->v = v;
+}
+
+Quaternion::Quaternion(const Vector3 &axis, scalar_t angle) {
+       set_rotation(axis, angle);
+}
+
+Quaternion Quaternion::operator +(const Quaternion &quat) const {
+       return Quaternion(s + quat.s, v + quat.v);
+}
+
+Quaternion Quaternion::operator -(const Quaternion &quat) const {
+       return Quaternion(s - quat.s, v - quat.v);
+}
+
+Quaternion Quaternion::operator -() const {
+       return Quaternion(-s, -v);
+}
+
+// Quaternion Multiplication:
+// Q1*Q2 = [s1*s2 - v1.v2,  s1*v2 + s2*v1 + v1(x)v2]
+Quaternion Quaternion::operator *(const Quaternion &quat) const {
+       Quaternion newq;        
+       newq.s = s * quat.s - dot_product(v, quat.v);
+       newq.v = quat.v * s + v * quat.s + cross_product(v, quat.v);    
+       return newq;
+}
+
+void Quaternion::operator +=(const Quaternion &quat) {
+       *this = Quaternion(s + quat.s, v + quat.v);
+}
+
+void Quaternion::operator -=(const Quaternion &quat) {
+       *this = Quaternion(s - quat.s, v - quat.v);
+}
+
+void Quaternion::operator *=(const Quaternion &quat) {
+       *this = *this * quat;
+}
+
+void Quaternion::reset_identity() {
+       s = 1.0;
+       v.x = v.y = v.z = 0.0;
+}
+
+Quaternion Quaternion::conjugate() const {
+       return Quaternion(s, -v);
+}
+
+scalar_t Quaternion::length() const {
+       return (scalar_t)sqrt(v.x*v.x + v.y*v.y + v.z*v.z + s*s);
+}
+
+// Q * ~Q = ||Q||^2
+scalar_t Quaternion::length_sq() const {
+       return v.x*v.x + v.y*v.y + v.z*v.z + s*s;
+}
+
+void Quaternion::normalize() {
+       scalar_t len = (scalar_t)sqrt(v.x*v.x + v.y*v.y + v.z*v.z + s*s);
+       v.x /= len;
+       v.y /= len;
+       v.z /= len;
+       s /= len;
+}
+
+Quaternion Quaternion::normalized() const {
+       Quaternion nq = *this;
+       scalar_t len = (scalar_t)sqrt(v.x*v.x + v.y*v.y + v.z*v.z + s*s);
+       nq.v.x /= len;
+       nq.v.y /= len;
+       nq.v.z /= len;
+       nq.s /= len;
+       return nq;
+}
+
+// Quaternion Inversion: Q^-1 = ~Q / ||Q||^2
+Quaternion Quaternion::inverse() const {
+       Quaternion inv = conjugate();
+       scalar_t lensq = length_sq();
+       inv.v /= lensq;
+       inv.s /= lensq;
+
+       return inv;
+}
+
+
+void Quaternion::set_rotation(const Vector3 &axis, scalar_t angle) {
+       scalar_t HalfAngle = angle / 2.0;
+       s = cos(HalfAngle);
+       v = axis * sin(HalfAngle);
+}
+
+void Quaternion::rotate(const Vector3 &axis, scalar_t angle) {
+       Quaternion q;
+       scalar_t HalfAngle = angle / 2.0;
+       q.s = cos(HalfAngle);
+       q.v = axis * sin(HalfAngle);
+
+       *this *= q;
+}
+
+void Quaternion::rotate(const Quaternion &q) {
+       *this = q * *this * q.conjugate();
+}
+
+Matrix3x3 Quaternion::get_rotation_matrix() const {
+       return Matrix3x3(       1.0 - 2.0 * v.y*v.y - 2.0 * v.z*v.z,    2.0 * v.x * v.y + 2.0 * s * v.z,                2.0 * v.z * v.x - 2.0 * s * v.y,
+                                               2.0 * v.x * v.y - 2.0 * s * v.z,                1.0 - 2.0 * v.x*v.x - 2.0 * v.z*v.z,    2.0 * v.y * v.z + 2.0 * s * v.x,
+                                               2.0 * v.z * v.x + 2.0 * s * v.y,                2.0 * v.y * v.z - 2.0 * s * v.x,                1.0 - 2.0 * v.x*v.x - 2.0 * v.y*v.y);
+}
+
+
+Quaternion slerp(const Quaternion &q1, const Quaternion &q2, scalar_t t) {
+       scalar_t dot = dot_product(Vector4(q1.s, q1.v.x, q1.v.y, q1.v.z), Vector4(q2.s, q2.v.x, q2.v.y, q2.v.z));
+       
+       if(fabs(1.0 - dot) < xsmall_number) return q1;  // avoids divisions by zero later on if q1 == q2
+       
+       if(dot >= 0.0f) {
+               scalar_t angle = acos(dot);
+               scalar_t coef1 = (angle * sin(1.0 - t)) / sin(angle);
+               scalar_t coef2 = sin(angle * t) / sin(angle);
+               return Quaternion(q1.s * coef1 + q2.s * coef2, q1.v * coef1 + q2.v * coef2).normalized();
+       } else {
+               scalar_t angle = acos(-dot);
+               scalar_t coef1 = (angle * sin(1.0 - t)) / sin(angle);
+               scalar_t coef2 = sin(angle * t) / sin(angle);
+               return Quaternion(q2.s * coef1 + q1.s * coef2, q2.v * coef1 + q1.v * coef2).normalized();
+       }
+}
+       
+
+
+std::ostream &operator <<(std::ostream &out, const Quaternion &q) {
+       out << "(" << q.s << ", " << q.v << ")";
+       return out;
+}
diff --git a/src/3dengfx/src/n3dmath2/n3dmath2_qua.hpp b/src/3dengfx/src/n3dmath2/n3dmath2_qua.hpp
new file mode 100644 (file)
index 0000000..8d503c7
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+This file is part of the n3dmath2 library.
+
+Copyright (c) 2003 - 2005 John Tsiombikas <nuclear@siggraph.org>
+
+The n3dmath2 library is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+The n3dmath2 library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with the n3dmath2 library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* quaterinion math
+ *
+ * Author: John Tsiombikas 2003
+ * Modified: John Tsiombikas 2004, 2005
+ */
+
+#ifndef _N3DMATH2_QUA_HPP_
+#define _N3DMATH2_QUA_HPP_
+
+#include <iostream>
+#include "n3dmath2_types.hpp"
+
+class Quaternion {
+public:
+       scalar_t s;
+       Vector3 v;
+
+       Quaternion();
+       Quaternion(scalar_t s, const Vector3 &v);
+       Quaternion(scalar_t s, scalar_t x, scalar_t y, scalar_t z);
+       Quaternion(const Vector3 &axis, scalar_t angle);
+
+       Quaternion operator +(const Quaternion &quat) const;
+       Quaternion operator -(const Quaternion &quat) const;
+       Quaternion operator -() const;
+       Quaternion operator *(const Quaternion &quat) const;
+       
+       void operator +=(const Quaternion &quat);
+       void operator -=(const Quaternion &quat);
+       void operator *=(const Quaternion &quat);
+
+       void reset_identity();
+
+       Quaternion conjugate() const;
+
+       scalar_t length() const;
+       scalar_t length_sq() const;
+       
+       void normalize();
+       Quaternion normalized() const;
+
+       Quaternion inverse() const;
+
+       void set_rotation(const Vector3 &axis, scalar_t angle);
+       void rotate(const Vector3 &axis, scalar_t angle);
+       /* note: this is a totally different operation from the above
+        * this treats the quaternion as signifying direction and rotates
+        * it by a rotation quaternion by rot * q * rot'
+        */
+       void rotate(const Quaternion &q);
+
+       Matrix3x3 get_rotation_matrix() const;
+       
+       friend Quaternion slerp(const Quaternion &q1, const Quaternion &q2, scalar_t t);
+       
+       friend std::ostream &operator <<(std::ostream &out, const Quaternion &q);
+};
+
+
+#endif // _N3DMATH2_QUA_HPP_
diff --git a/src/3dengfx/src/n3dmath2/n3dmath2_ray.cpp b/src/3dengfx/src/n3dmath2/n3dmath2_ray.cpp
new file mode 100644 (file)
index 0000000..fbba1bb
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+Copyright 2004 John Tsiombikas <nuclear@siggraph.org>
+
+This file is part of the n3dmath2 library.
+
+The n3dmath2 library is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+The n3dmath2 library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with the n3dmath2 library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "n3dmath2.hpp"
+
+using std::stack;
+
+Ray::Ray() {
+       energy = 1.0;
+       ior = 1.0;
+}
+
+Ray::Ray(const Vector3 &origin, const Vector3 &dir) {
+       this->origin = origin;
+       this->dir = dir;
+       energy = 1.0;
+       ior = 1.0;
+}
+
+void Ray::enter(scalar_t new_ior) {
+       ior = new_ior;
+       ior_stack.push(ior);
+}
+
+void Ray::leave() {
+       ior_stack.pop();
+       ior = ior_stack.empty() ? 1.0 : ior_stack.top();
+}
diff --git a/src/3dengfx/src/n3dmath2/n3dmath2_ray.hpp b/src/3dengfx/src/n3dmath2/n3dmath2_ray.hpp
new file mode 100644 (file)
index 0000000..7e2300b
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+Copyright 2004 John Tsiombikas <nuclear@siggraph.org>
+
+This file is part of the n3dmath2 library.
+
+The n3dmath2 library is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+The n3dmath2 library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with the n3dmath2 library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef _N3DMATH2_RAY_HPP_
+#define _N3DMATH2_RAY_HPP_
+
+#include <stack>
+#include "n3dmath2_types.hpp"
+
+class Ray {
+private:
+       std::stack<scalar_t> ior_stack;
+
+public:
+       Vector3 origin, dir;
+       scalar_t energy;
+       scalar_t ior;
+       
+       Ray();
+       Ray(const Vector3 &origin, const Vector3 &dir);
+       
+       void enter(scalar_t new_ior);
+       void leave();
+};
+
+#endif // _N3DMATH2_RAY_HPP_
diff --git a/src/3dengfx/src/n3dmath2/n3dmath2_sph.cpp b/src/3dengfx/src/n3dmath2/n3dmath2_sph.cpp
new file mode 100644 (file)
index 0000000..4aeba2a
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+This file is part of the n3dmath2 library.
+
+Copyright (C) 2005 John Tsiombikas <nuclear@siggraph.org>
+
+n3dmath2 is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+n3dmath2 is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with n3dmath2; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "n3dmath2.hpp"
+
+/**
+ * @param theta 0 <= theta <= 2pi, the angle around Y axis.
+ * @param phi 0 <= phi <= pi, the angle from Y axis.
+ * @param r Radius.
+ */
+SphVector::SphVector(scalar_t theta, scalar_t phi, scalar_t r) {
+       this->theta = theta;
+       this->phi = phi;
+       this->r = r;
+}
+
+/** Constructs a spherical coordinate vector from a cartesian vector */
+SphVector::SphVector(const Vector3 &cvec) {
+       *this = cvec;
+}
+
+/** Assignment operator that converts cartesian to spherical coords */
+SphVector &SphVector::operator =(const Vector3 &cvec) {
+       r = cvec.length();
+       //theta = atan2(cvec.y, cvec.x);
+       theta = atan2(cvec.z, cvec.x);
+       //phi = acos(cvec.z / r);
+       phi = acos(cvec.y / r);
+       return *this;
+}
diff --git a/src/3dengfx/src/n3dmath2/n3dmath2_sph.hpp b/src/3dengfx/src/n3dmath2/n3dmath2_sph.hpp
new file mode 100644 (file)
index 0000000..fd089d3
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+This file is part of the n3dmath2 library.
+
+Copyright (C) 2005 John Tsiombikas <nuclear@siggraph.org>
+
+n3dmath2 is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+n3dmath2 is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with n3dmath2; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef N3DMATH2_SPH_H_
+#define N3DMATH2_SPH_H_
+
+#include "n3dmath2_types.hpp"
+
+/** Vector in spherical coordinates */
+class SphVector {
+public:
+       scalar_t theta, phi, r;
+
+       SphVector(scalar_t theta = 0.0, scalar_t phi = 0.0, scalar_t r = 1.0);
+       SphVector(const Vector3 &cvec);
+       SphVector &operator =(const Vector3 &cvec);
+};
+
+#endif // N3DMATH2_SPH_H_
diff --git a/src/3dengfx/src/n3dmath2/n3dmath2_types.hpp b/src/3dengfx/src/n3dmath2/n3dmath2_types.hpp
new file mode 100644 (file)
index 0000000..3be3e74
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+Copyright 2004 John Tsiombikas <nuclear@siggraph.org>
+
+This file is part of the n3dmath2 library.
+
+The n3dmath2 library is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+The n3dmath2 library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with the n3dmath2 library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef _N3DMATH2_TYPES_HPP_
+#define _N3DMATH2_TYPES_HPP_
+
+#include "3dengfx_config.h"
+#include "common/types.h"
+
+// -- class forward declarations --
+class Vector2;
+class Vector2i;
+class Vector3;
+class Vector4;
+class Matrix3x3;
+class Matrix4x4;
+class Quaternion;
+class SphVector;
+class Base;
+class Ray;
+
+#endif // _N3DMATH2_TYPES_HPP_
diff --git a/src/3dengfx/src/n3dmath2/n3dmath2_vec.cpp b/src/3dengfx/src/n3dmath2/n3dmath2_vec.cpp
new file mode 100644 (file)
index 0000000..53d386b
--- /dev/null
@@ -0,0 +1,279 @@
+/*
+Copyright 2004 John Tsiombikas <nuclear@siggraph.org>
+
+This file is part of the n3dmath2 library.
+
+The n3dmath2 library is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+The n3dmath2 library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with the n3dmath2 library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "n3dmath2.hpp"
+
+// ---------- Vector2 -----------
+
+Vector2::Vector2(scalar_t x, scalar_t y) {
+       this->x = x;
+       this->y = y;
+}
+
+Vector2::Vector2(const Vector3 &vec) {
+       x = vec.x;
+       y = vec.y;
+}
+
+Vector2::Vector2(const Vector4 &vec) {
+       x = vec.x;
+       y = vec.y;
+}
+
+void Vector2::normalize() {
+       scalar_t len = length();
+       x /= len;
+       y /= len;
+}
+
+Vector2 Vector2::normalized() const {  
+       scalar_t len = length();
+       return Vector2(x / len, y / len);
+}      
+       
+void Vector2::transform(const Matrix3x3 &mat) {
+       scalar_t nx = mat[0][0] * x + mat[0][1] * y + mat[0][2];
+       y = mat[1][0] * x + mat[1][1] * y + mat[1][2];
+       x = nx;
+}
+
+Vector2 Vector2::transformed(const Matrix3x3 &mat) const {
+       Vector2 vec;
+       vec.x = mat[0][0] * x + mat[0][1] * y + mat[0][2];
+       vec.y = mat[1][0] * x + mat[1][1] * y + mat[1][2];
+       return vec;
+}
+
+void Vector2::rotate(scalar_t angle) {
+       *this = Vector2(cos(angle) * x - sin(angle) * y, sin(angle) * x + cos(angle) * y);
+}
+
+Vector2 Vector2::rotated(scalar_t angle) const {
+       return Vector2(cos(angle) * x - sin(angle) * y, sin(angle) * x + cos(angle) * y);
+}
+       
+Vector2 Vector2::reflection(const Vector2 &normal) const {
+       return 2.0 * dot_product(*this, normal) * normal - *this;
+}
+
+Vector2 Vector2::refraction(const Vector2 &normal, scalar_t src_ior, scalar_t dst_ior) const {
+       return *this;
+}
+
+std::ostream &operator <<(std::ostream &out, const Vector2 &vec) {
+       out << "[" << vec.x << " " << vec.y << "]";
+       return out;
+}
+
+
+
+// --------- Vector3 ----------
+
+Vector3::Vector3(scalar_t x, scalar_t y, scalar_t z) {
+       this->x = x;
+       this->y = y;
+       this->z = z;
+}
+
+Vector3::Vector3(const Vector2 &vec) {
+       x = vec.x;
+       y = vec.y;
+       z = 1;
+}
+
+Vector3::Vector3(const Vector4 &vec) {
+       x = vec.x;
+       y = vec.y;
+       z = vec.z;
+}
+
+Vector3::Vector3(const SphVector &sph) {
+       *this = sph;
+}
+
+Vector3 &Vector3::operator =(const SphVector &sph) {
+       x = sph.r * cos(sph.theta) * sin(sph.phi);
+       z = sph.r * sin(sph.theta) * sin(sph.phi);
+       y = sph.r * cos(sph.phi);
+       return *this;
+}
+
+void Vector3::normalize() {
+       scalar_t len = length();
+       x /= len;
+       y /= len;
+       z /= len;       
+}
+
+Vector3 Vector3::normalized() const {
+       scalar_t len = length();
+       return Vector3(x / len, y / len, z / len);
+}
+
+Vector3 Vector3::reflection(const Vector3 &normal) const {
+       return -(2.0 * dot_product(*this, normal) * normal - *this);
+}
+
+Vector3 Vector3::refraction(const Vector3 &normal, scalar_t src_ior, scalar_t dst_ior) const {
+       scalar_t cos_inc = dot_product(*this, -normal);
+       scalar_t ior = src_ior / dst_ior;
+
+       scalar_t radical = 1.0 + SQ(ior) * (SQ(cos_inc) - 1.0);
+
+       if(radical < 0.0) {             // total internal reflection
+               return reflection(normal);
+       }
+
+       scalar_t beta = ior * cos_inc - sqrt(radical);
+
+       return *this * ior + normal * beta;
+}
+
+void Vector3::transform(const Matrix3x3 &mat) {
+       scalar_t nx = mat[0][0] * x + mat[0][1] * y + mat[0][2] * z;
+       scalar_t ny = mat[1][0] * x + mat[1][1] * y + mat[1][2] * z;
+       z = mat[2][0] * x + mat[2][1] * y + mat[2][2] * z;
+       x = nx;
+       y = ny;
+}
+
+Vector3 Vector3::transformed(const Matrix3x3 &mat) const {
+       Vector3 vec;
+       vec.x = mat[0][0] * x + mat[0][1] * y + mat[0][2] * z;
+       vec.y = mat[1][0] * x + mat[1][1] * y + mat[1][2] * z;
+       vec.z = mat[2][0] * x + mat[2][1] * y + mat[2][2] * z;
+       return vec;
+}
+
+void Vector3::transform(const Matrix4x4 &mat) {
+       scalar_t nx = mat[0][0] * x + mat[0][1] * y + mat[0][2] * z + mat[0][3];
+       scalar_t ny = mat[1][0] * x + mat[1][1] * y + mat[1][2] * z + mat[1][3];
+       z = mat[2][0] * x + mat[2][1] * y + mat[2][2] * z + mat[2][3];
+       x = nx;
+       y = ny;
+}
+
+Vector3 Vector3::transformed(const Matrix4x4 &mat) const {
+       Vector3 vec;
+       vec.x = mat[0][0] * x + mat[0][1] * y + mat[0][2] * z + mat[0][3];
+       vec.y = mat[1][0] * x + mat[1][1] * y + mat[1][2] * z + mat[1][3];
+       vec.z = mat[2][0] * x + mat[2][1] * y + mat[2][2] * z + mat[2][3];
+       return vec;
+}
+
+void Vector3::transform(const Quaternion &quat) {
+       Quaternion vq(0.0f, *this);
+       vq = quat * vq * quat.inverse();
+       *this = vq.v;
+}
+
+Vector3 Vector3::transformed(const Quaternion &quat) const {
+       Quaternion vq(0.0f, *this);
+       vq = quat * vq * quat.inverse();
+       return vq.v;
+}
+
+void Vector3::rotate(const Vector3 &euler) {
+       Matrix4x4 rot;
+       rot.set_rotation(euler);
+       transform(rot);
+}
+
+Vector3 Vector3::rotated(const Vector3 &euler) const {
+       Matrix4x4 rot;
+       rot.set_rotation(euler);
+       return transformed(rot);
+}
+
+std::ostream &operator <<(std::ostream &out, const Vector3 &vec) {
+       out << "[" << vec.x << " " << vec.y << " " << vec.z << "]";
+       return out;
+}
+
+
+
+// -------------- Vector4 --------------
+Vector4::Vector4(scalar_t x, scalar_t y, scalar_t z, scalar_t w) {
+       this->x = x;
+       this->y = y;
+       this->z = z;
+       this->w = w;
+}
+
+Vector4::Vector4(const Vector2 &vec) {
+       x = vec.x;
+       y = vec.y;
+       z = 1;
+       w = 1;
+}
+
+Vector4::Vector4(const Vector3 &vec) {
+       x = vec.x;
+       y = vec.y;
+       z = vec.z;
+       w = 1;
+}
+
+void Vector4::normalize() {
+       scalar_t len = (scalar_t)sqrt(x*x + y*y + z*z + w*w);
+       x /= len;
+       y /= len;
+       z /= len;
+       w /= len;
+}
+
+Vector4 Vector4::normalized() const {
+       scalar_t len = (scalar_t)sqrt(x*x + y*y + z*z + w*w);
+       return Vector4(x / len, y / len, z / len, w / len);
+}
+
+void Vector4::transform(const Matrix4x4 &mat) {
+       scalar_t nx = mat[0][0] * x + mat[0][1] * y + mat[0][2] * z + mat[0][3] * w;
+       scalar_t ny = mat[1][0] * x + mat[1][1] * y + mat[1][2] * z + mat[1][3] * w;
+       scalar_t nz = mat[2][0] * x + mat[2][1] * y + mat[2][2] * z + mat[2][3] * w;
+       w = mat[3][0] * x + mat[3][1] * y + mat[3][2] * z + mat[3][3] * w;
+       x = nx;
+       y = ny;
+       z = nz;
+}
+
+Vector4 Vector4::transformed(const Matrix4x4 &mat) const {
+       Vector4 vec;
+       vec.x = mat[0][0] * x + mat[0][1] * y + mat[0][2] * z + mat[0][3] * w;
+       vec.y = mat[1][0] * x + mat[1][1] * y + mat[1][2] * z + mat[1][3] * w;
+       vec.z = mat[2][0] * x + mat[2][1] * y + mat[2][2] * z + mat[2][3] * w;
+       vec.w = mat[3][0] * x + mat[3][1] * y + mat[3][2] * z + mat[3][3] * w;
+       return vec;
+}
+
+// TODO: implement 4D vector reflection
+Vector4 Vector4::reflection(const Vector4 &normal) const {
+       return *this;
+}
+
+// TODO: implement 4D vector refraction
+Vector4 Vector4::refraction(const Vector4 &normal, scalar_t src_ior, scalar_t dst_ior) const {
+       return *this;
+}
+
+std::ostream &operator <<(std::ostream &out, const Vector4 &vec) {
+       out << "[" << vec.x << " " << vec.y << " " << vec.z << " " << vec.w << "]";
+       return out;
+}
diff --git a/src/3dengfx/src/n3dmath2/n3dmath2_vec.hpp b/src/3dengfx/src/n3dmath2/n3dmath2_vec.hpp
new file mode 100644 (file)
index 0000000..1c40520
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+This file is part of the n3dmath2 library.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+The n3dmath2 library is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+The n3dmath2 library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with the n3dmath2 library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef _N3DMATH2_VEC_HPP_
+#define _N3DMATH2_VEC_HPP_
+
+#include <iostream>
+#include "n3dmath2_types.hpp"
+
+class Vector2 {
+public:
+       scalar_t x, y;
+
+       Vector2(scalar_t x = 0.0, scalar_t y = 0.0);
+       Vector2(const Vector3 &vec);
+       Vector2(const Vector4 &vec);
+       
+       inline scalar_t &operator [](int elem); 
+       
+       // unary operations
+       friend inline Vector2 operator -(const Vector2 &vec);
+       
+       // binary vector (op) vector operations
+       friend inline scalar_t dot_product(const Vector2 &v1, const Vector2 &v2);
+       
+       friend inline Vector2 operator +(const Vector2 &v1, const Vector2 &v2);
+       friend inline Vector2 operator -(const Vector2 &v1, const Vector2 &v2); 
+       friend inline Vector2 operator *(const Vector2 &v1, const Vector2 &v2);
+       friend inline Vector2 operator /(const Vector2 &v1, const Vector2 &v2);
+       friend inline bool operator ==(const Vector2 &v1, const Vector2 &v2);
+       
+       friend inline void operator +=(Vector2 &v1, const Vector2 &v2);
+       friend inline void operator -=(Vector2 &v1, const Vector2 &v2);
+       friend inline void operator *=(Vector2 &v1, const Vector2 &v2);
+       friend inline void operator /=(Vector2 &v1, const Vector2 &v2);
+       
+       // binary vector (op) scalar and scalar (op) vector operations
+       friend inline Vector2 operator +(const Vector2 &vec, scalar_t scalar);
+       friend inline Vector2 operator +(scalar_t scalar, const Vector2 &vec);
+       friend inline Vector2 operator -(const Vector2 &vec, scalar_t scalar);
+       friend inline Vector2 operator -(scalar_t scalar, const Vector2 &vec);
+       friend inline Vector2 operator *(const Vector2 &vec, scalar_t scalar);
+       friend inline Vector2 operator *(scalar_t scalar, const Vector2 &vec);
+       friend inline Vector2 operator /(const Vector2 &vec, scalar_t scalar);
+       friend inline Vector2 operator /(scalar_t scalar, const Vector2 &vec);
+       
+       friend inline void operator +=(Vector2 &vec, scalar_t scalar);
+       friend inline void operator -=(Vector2 &vec, scalar_t scalar);
+       friend inline void operator *=(Vector2 &vec, scalar_t scalar);
+       friend inline void operator /=(Vector2 &vec, scalar_t scalar);
+       
+       inline scalar_t length() const;
+       inline scalar_t length_sq() const;
+       void normalize();
+       Vector2 normalized() const;
+
+       void transform(const Matrix3x3 &mat);
+       Vector2 transformed(const Matrix3x3 &mat) const;
+
+       void rotate(scalar_t angle);
+       Vector2 rotated(scalar_t angle) const;
+                       
+       Vector2 reflection(const Vector2 &normal) const;
+       Vector2 refraction(const Vector2 &normal, scalar_t src_ior, scalar_t dst_ior) const;
+       
+       friend std::ostream &operator <<(std::ostream &out, const Vector2 &vec);
+};
+
+class Vector3 {
+public:
+       scalar_t x, y, z;
+
+       Vector3(scalar_t x = 0.0, scalar_t y = 0.0, scalar_t z = 0.0);
+       Vector3(const Vector2 &vec);
+       Vector3(const Vector4 &vec);
+       Vector3(const SphVector &sph);
+
+       Vector3 &operator =(const SphVector &sph);
+       
+       inline scalar_t &operator [](int elem); 
+       
+       // unary operations
+       friend inline Vector3 operator -(const Vector3 &vec);
+       
+       // binary vector (op) vector operations
+       friend inline scalar_t dot_product(const Vector3 &v1, const Vector3 &v2);
+       friend inline Vector3 cross_product(const Vector3 &v1, const Vector3 &v2);
+       
+       friend inline Vector3 operator +(const Vector3 &v1, const Vector3 &v2);
+       friend inline Vector3 operator -(const Vector3 &v1, const Vector3 &v2); 
+       friend inline Vector3 operator *(const Vector3 &v1, const Vector3 &v2); 
+       friend inline Vector3 operator /(const Vector3 &v1, const Vector3 &v2); 
+       friend inline bool operator ==(const Vector3 &v1, const Vector3 &v2);
+       
+       friend inline void operator +=(Vector3 &v1, const Vector3 &v2);
+       friend inline void operator -=(Vector3 &v1, const Vector3 &v2);
+       friend inline void operator *=(Vector3 &v1, const Vector3 &v2);
+       friend inline void operator /=(Vector3 &v1, const Vector3 &v2);
+       
+       // binary vector (op) scalar and scalar (op) vector operations
+       friend inline Vector3 operator +(const Vector3 &vec, scalar_t scalar);
+       friend inline Vector3 operator +(scalar_t scalar, const Vector3 &vec);
+       friend inline Vector3 operator -(const Vector3 &vec, scalar_t scalar);
+       friend inline Vector3 operator -(scalar_t scalar, const Vector3 &vec);
+       friend inline Vector3 operator *(const Vector3 &vec, scalar_t scalar);
+       friend inline Vector3 operator *(scalar_t scalar, const Vector3 &vec);
+       friend inline Vector3 operator /(const Vector3 &vec, scalar_t scalar);
+       friend inline Vector3 operator /(scalar_t scalar, const Vector3 &vec);
+       
+       friend inline void operator +=(Vector3 &vec, scalar_t scalar);
+       friend inline void operator -=(Vector3 &vec, scalar_t scalar);
+       friend inline void operator *=(Vector3 &vec, scalar_t scalar);
+       friend inline void operator /=(Vector3 &vec, scalar_t scalar);
+       
+       inline scalar_t length() const;
+       inline scalar_t length_sq() const;
+       void normalize();
+       Vector3 normalized() const;
+       
+       void transform(const Matrix3x3 &mat);
+       Vector3 transformed(const Matrix3x3 &mat) const;
+       void transform(const Matrix4x4 &mat);
+       Vector3 transformed(const Matrix4x4 &mat) const;
+       void transform(const Quaternion &quat);
+       Vector3 transformed(const Quaternion &quat) const;
+
+       void rotate(const Vector3 &euler);
+       Vector3 rotated(const Vector3 &euler) const;
+       
+       Vector3 reflection(const Vector3 &normal) const;
+       Vector3 refraction(const Vector3 &normal, scalar_t src_ior, scalar_t dst_ior) const;
+       
+       friend std::ostream &operator <<(std::ostream &out, const Vector3 &vec);
+};
+
+class Vector4 {
+public:
+       scalar_t x, y, z, w;
+
+       Vector4(scalar_t x = 0.0, scalar_t y = 0.0, scalar_t z = 0.0, scalar_t w = 0.0);
+       Vector4(const Vector2 &vec);
+       Vector4(const Vector3 &vec);
+       
+       inline scalar_t &operator [](int elem); 
+       
+       // unary operations
+       friend inline Vector4 operator -(const Vector4 &vec);
+               
+       // binary vector (op) vector operations
+       friend inline scalar_t dot_product(const Vector4 &v1, const Vector4 &v2);
+       friend inline Vector4 cross_product(const Vector4 &v1, const Vector4 &v2, const Vector4 &v3);
+       
+       friend inline Vector4 operator +(const Vector4 &v1, const Vector4 &v2);
+       friend inline Vector4 operator -(const Vector4 &v1, const Vector4 &v2); 
+       friend inline Vector4 operator *(const Vector4 &v1, const Vector4 &v2); 
+       friend inline Vector4 operator /(const Vector4 &v1, const Vector4 &v2); 
+       friend inline bool operator ==(const Vector4 &v1, const Vector4 &v2);
+       
+       friend inline void operator +=(Vector4 &v1, const Vector4 &v2);
+       friend inline void operator -=(Vector4 &v1, const Vector4 &v2);
+       friend inline void operator *=(Vector4 &v1, const Vector4 &v2);
+       friend inline void operator /=(Vector4 &v1, const Vector4 &v2);
+       
+       // binary vector (op) scalar and scalar (op) vector operations
+       friend inline Vector4 operator +(const Vector4 &vec, scalar_t scalar);
+       friend inline Vector4 operator +(scalar_t scalar, const Vector4 &vec);
+       friend inline Vector4 operator -(const Vector4 &vec, scalar_t scalar);
+       friend inline Vector4 operator -(scalar_t scalar, const Vector4 &vec);
+       friend inline Vector4 operator *(const Vector4 &vec, scalar_t scalar);
+       friend inline Vector4 operator *(scalar_t scalar, const Vector4 &vec);
+       friend inline Vector4 operator /(const Vector4 &vec, scalar_t scalar);
+       friend inline Vector4 operator /(scalar_t scalar, const Vector4 &vec);
+       
+       friend inline void operator +=(Vector4 &vec, scalar_t scalar);
+       friend inline void operator -=(Vector4 &vec, scalar_t scalar);
+       friend inline void operator *=(Vector4 &vec, scalar_t scalar);
+       friend inline void operator /=(Vector4 &vec, scalar_t scalar);
+       
+       inline scalar_t length() const;
+       inline scalar_t length_sq() const;
+       void normalize();
+       Vector4 normalized() const;
+
+       void transform(const Matrix4x4 &mat);
+       Vector4 transformed(const Matrix4x4 &mat) const;
+               
+       Vector4 reflection(const Vector4 &normal) const;
+       Vector4 refraction(const Vector4 &normal, scalar_t src_ior, scalar_t dst_ior) const;
+       
+       friend std::ostream &operator <<(std::ostream &out, const Vector4 &vec);
+};
+
+#include "n3dmath2_vec.inl"
+
+#endif // _N3DMATH2_VEC_HPP_
diff --git a/src/3dengfx/src/n3dmath2/n3dmath2_vec.inl b/src/3dengfx/src/n3dmath2/n3dmath2_vec.inl
new file mode 100644 (file)
index 0000000..a6d3293
--- /dev/null
@@ -0,0 +1,425 @@
+/*
+Copyright 2004 John Tsiombikas <nuclear@siggraph.org>
+
+This file is part of the n3dmath2 library.
+
+The n3dmath2 library is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+The n3dmath2 library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with the n3dmath2 library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+// ------------------------------
+// inline function definitions
+// for Vector classes of n3dmath2
+// ------------------------------
+
+#include <cmath>
+
+// ---------- Vector2 -----------
+
+inline scalar_t &Vector2::operator [](int elem) {
+       return elem ? y : x;
+}
+
+inline Vector2 operator -(const Vector2 &vec) {
+       return Vector2(-vec.x, -vec.y);
+}
+
+inline scalar_t dot_product(const Vector2 &v1, const Vector2 &v2) {
+       return v1.x * v2.x + v1.y * v2.y;
+}
+
+inline Vector2 operator +(const Vector2 &v1, const Vector2 &v2) {
+       return Vector2(v1.x + v2.x, v1.y + v2.y);
+}
+
+inline Vector2 operator -(const Vector2 &v1, const Vector2 &v2) {
+       return Vector2(v1.x - v2.x, v1.y - v2.y);
+}
+
+inline Vector2 operator *(const Vector2 &v1, const Vector2 &v2) {
+       return Vector2(v1.x * v2.x, v1.y * v2.y);
+}
+
+inline Vector2 operator /(const Vector2 &v1, const Vector2 &v2) {
+       return Vector2(v1.x / v2.x, v1.y / v2.y);
+}
+
+inline bool operator ==(const Vector2 &v1, const Vector2 &v2) {
+       return (fabs(v1.x - v2.x) < xsmall_number) && (fabs(v1.y - v2.x) < xsmall_number);
+}
+
+inline void operator +=(Vector2 &v1, const Vector2 &v2) {
+       v1.x += v2.x;
+       v1.y += v2.y;
+}
+
+inline void operator -=(Vector2 &v1, const Vector2 &v2) {
+       v1.x -= v2.x;
+       v1.y -= v2.y;
+}
+
+inline void operator *=(Vector2 &v1, const Vector2 &v2) {
+       v1.x *= v2.x;
+       v1.y *= v2.y;
+}
+
+inline void operator /=(Vector2 &v1, const Vector2 &v2) {
+       v1.x /= v2.x;
+       v1.y /= v2.y;
+}
+
+inline Vector2 operator +(const Vector2 &vec, scalar_t scalar) {
+       return Vector2(vec.x + scalar, vec.y + scalar);
+}
+
+inline Vector2 operator +(scalar_t scalar, const Vector2 &vec) {
+       return Vector2(vec.x + scalar, vec.y + scalar);
+}
+
+inline Vector2 operator -(const Vector2 &vec, scalar_t scalar) {
+       return Vector2(vec.x - scalar, vec.y - scalar);
+}
+
+inline Vector2 operator -(scalar_t scalar, const Vector2 &vec) {
+       return Vector2(vec.x - scalar, vec.y - scalar);
+}
+
+inline Vector2 operator *(const Vector2 &vec, scalar_t scalar) {
+       return Vector2(vec.x * scalar, vec.y * scalar);
+}
+
+inline Vector2 operator *(scalar_t scalar, const Vector2 &vec) {
+       return Vector2(vec.x * scalar, vec.y * scalar);
+}
+
+inline Vector2 operator /(const Vector2 &vec, scalar_t scalar) {
+       return Vector2(vec.x / scalar, vec.y / scalar);
+}
+
+inline Vector2 operator /(scalar_t scalar, const Vector2 &vec) {
+       return Vector2(vec.x / scalar, vec.y / scalar);
+}
+
+inline void operator +=(Vector2 &vec, scalar_t scalar) {
+       vec.x += scalar;
+       vec.y += scalar;
+}
+
+inline void operator -=(Vector2 &vec, scalar_t scalar) {
+       vec.x -= scalar;
+       vec.y -= scalar;
+}
+
+inline void operator *=(Vector2 &vec, scalar_t scalar) {
+       vec.x *= scalar;
+       vec.y *= scalar;
+}
+
+inline void operator /=(Vector2 &vec, scalar_t scalar) {
+       vec.x /= scalar;
+       vec.y /= scalar;
+}
+
+inline scalar_t Vector2::length() const {
+       return sqrt(x*x + y*y);
+}
+
+inline scalar_t Vector2::length_sq() const {
+       return x*x + y*y;
+}
+
+
+
+// ------------- Vector3 --------------
+
+inline scalar_t &Vector3::operator [](int elem) {
+       return elem ? (elem == 1 ? y : z) : x;
+}
+
+// unary operations
+inline Vector3 operator -(const Vector3 &vec) {
+       return Vector3(-vec.x, -vec.y, -vec.z);
+}
+
+// binary vector (op) vector operations
+inline scalar_t dot_product(const Vector3 &v1, const Vector3 &v2) {
+       return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
+}
+
+inline Vector3 cross_product(const Vector3 &v1, const Vector3 &v2) {
+       return Vector3(v1.y * v2.z - v1.z * v2.y,  v1.z * v2.x - v1.x * v2.z,  v1.x * v2.y - v1.y * v2.x);
+}
+
+
+inline Vector3 operator +(const Vector3 &v1, const Vector3 &v2) {
+       return Vector3(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
+}
+
+inline Vector3 operator -(const Vector3 &v1, const Vector3 &v2) {
+       return Vector3(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
+}
+
+inline Vector3 operator *(const Vector3 &v1, const Vector3 &v2) {
+       return Vector3(v1.x * v2.x, v1.y * v2.y, v1.z * v2.z);
+}
+
+inline Vector3 operator /(const Vector3 &v1, const Vector3 &v2) {
+       return Vector3(v1.x / v2.x, v1.y / v2.y, v1.z / v2.z);
+}
+
+inline bool operator ==(const Vector3 &v1, const Vector3 &v2) {
+       return (fabs(v1.x - v2.x) < xsmall_number) && (fabs(v1.y - v2.y) < xsmall_number) && (fabs(v1.z - v2.z) < xsmall_number);
+}
+
+inline void operator +=(Vector3 &v1, const Vector3 &v2) {
+       v1.x += v2.x;
+       v1.y += v2.y;
+       v1.z += v2.z;
+}
+
+inline void operator -=(Vector3 &v1, const Vector3 &v2) {
+       v1.x -= v2.x;
+       v1.y -= v2.y;
+       v1.z -= v2.z;
+}
+
+inline void operator *=(Vector3 &v1, const Vector3 &v2) {
+       v1.x *= v2.x;
+       v1.y *= v2.y;
+       v1.z *= v2.z;
+}
+
+inline void operator /=(Vector3 &v1, const Vector3 &v2) {
+       v1.x /= v2.x;
+       v1.y /= v2.y;
+       v1.z /= v2.z;
+}
+// binary vector (op) scalar and scalar (op) vector operations
+inline Vector3 operator +(const Vector3 &vec, scalar_t scalar) {
+       return Vector3(vec.x + scalar, vec.y + scalar, vec.z + scalar);
+}
+
+inline Vector3 operator +(scalar_t scalar, const Vector3 &vec) {
+       return Vector3(vec.x + scalar, vec.y + scalar, vec.z + scalar);
+}
+
+inline Vector3 operator -(const Vector3 &vec, scalar_t scalar) {
+       return Vector3(vec.x - scalar, vec.y - scalar, vec.z - scalar);
+}
+
+inline Vector3 operator -(scalar_t scalar, const Vector3 &vec) {
+       return Vector3(vec.x - scalar, vec.y - scalar, vec.z - scalar);
+}
+
+inline Vector3 operator *(const Vector3 &vec, scalar_t scalar) {
+       return Vector3(vec.x * scalar, vec.y * scalar, vec.z * scalar);
+}
+
+inline Vector3 operator *(scalar_t scalar, const Vector3 &vec) {
+       return Vector3(vec.x * scalar, vec.y * scalar, vec.z * scalar);
+}
+
+inline Vector3 operator /(const Vector3 &vec, scalar_t scalar) {
+       return Vector3(vec.x / scalar, vec.y / scalar, vec.z / scalar);
+}
+
+inline Vector3 operator /(scalar_t scalar, const Vector3 &vec) {
+       return Vector3(vec.x / scalar, vec.y / scalar, vec.z / scalar);
+}
+
+inline void operator +=(Vector3 &vec, scalar_t scalar) {
+       vec.x += scalar;
+       vec.y += scalar;
+       vec.z += scalar;
+}
+
+inline void operator -=(Vector3 &vec, scalar_t scalar) {
+       vec.x -= scalar;
+       vec.y -= scalar;
+       vec.z -= scalar;
+}
+
+inline void operator *=(Vector3 &vec, scalar_t scalar) {
+       vec.x *= scalar;
+       vec.y *= scalar;
+       vec.z *= scalar;
+}
+
+inline void operator /=(Vector3 &vec, scalar_t scalar) {
+       vec.x /= scalar;
+       vec.y /= scalar;
+       vec.z /= scalar;
+}
+
+inline scalar_t Vector3::length() const {
+       return sqrt(x*x + y*y + z*z);
+}
+inline scalar_t Vector3::length_sq() const {
+       return x*x + y*y + z*z;
+}
+
+
+
+// ----------- Vector4 -----------------
+
+inline scalar_t &Vector4::operator [](int elem) {
+       return elem ? (elem == 1 ? y : (elem == 2 ? z : w)) : x;
+}
+
+inline Vector4 operator -(const Vector4 &vec) {
+       return Vector4(-vec.x, -vec.y, -vec.z, -vec.w);
+}
+
+inline scalar_t dot_product(const Vector4 &v1, const Vector4 &v2) {
+       return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z + v1.w * v2.w;
+}
+
+inline Vector4 cross_product(const Vector4 &v1, const Vector4 &v2, const Vector4 &v3) {
+       float  A, B, C, D, E, F;       // Intermediate Values
+    Vector4 result;
+
+    // Calculate intermediate values.
+    A = (v2.x * v3.y) - (v2.y * v3.x);
+    B = (v2.x * v3.z) - (v2.z * v3.x);
+    C = (v2.x * v3.w) - (v2.w * v3.x);
+    D = (v2.y * v3.z) - (v2.z * v3.y);
+    E = (v2.y * v3.w) - (v2.w * v3.y);
+    F = (v2.z * v3.w) - (v2.w * v3.z);
+
+    // Calculate the result-vector components.
+    result.x =   (v1.y * F) - (v1.z * E) + (v1.w * D);
+    result.y = - (v1.x * F) + (v1.z * C) - (v1.w * B);
+    result.z =   (v1.x * E) - (v1.y * C) + (v1.w * A);
+    result.w = - (v1.x * D) + (v1.y * B) - (v1.z * A);
+    return result;
+}
+
+inline Vector4 operator +(const Vector4 &v1, const Vector4 &v2) {
+       return Vector4(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z, v1.w + v2.w);
+}
+
+inline Vector4 operator -(const Vector4 &v1, const Vector4 &v2) {
+       return Vector4(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z, v1.w - v2.w);
+}
+
+inline Vector4 operator *(const Vector4 &v1, const Vector4 &v2) {
+       return Vector4(v1.x * v2.x, v1.y * v2.y, v1.z * v2.z, v1.w * v2.w);
+}
+
+inline Vector4 operator /(const Vector4 &v1, const Vector4 &v2) {
+       return Vector4(v1.x / v2.x, v1.y / v2.y, v1.z / v2.z, v1.w / v2.w);
+}
+
+inline bool operator ==(const Vector4 &v1, const Vector4 &v2) {
+       return  (fabs(v1.x - v2.x) < xsmall_number) && 
+                       (fabs(v1.y - v2.y) < xsmall_number) && 
+                       (fabs(v1.z - v2.z) < xsmall_number) &&
+                       (fabs(v1.w - v2.w) < xsmall_number);
+}
+
+inline void operator +=(Vector4 &v1, const Vector4 &v2) {
+       v1.x += v2.x;
+       v1.y += v2.y;
+       v1.z += v2.z;
+       v1.w += v2.w;
+}
+
+inline void operator -=(Vector4 &v1, const Vector4 &v2) {
+       v1.x -= v2.x;
+       v1.y -= v2.y;
+       v1.z -= v2.z;
+       v1.w -= v2.w;
+}
+
+inline void operator *=(Vector4 &v1, const Vector4 &v2) {
+       v1.x *= v2.x;
+       v1.y *= v2.y;
+       v1.z *= v2.z;
+       v1.w *= v2.w;
+}
+
+inline void operator /=(Vector4 &v1, const Vector4 &v2) {
+       v1.x /= v2.x;
+       v1.y /= v2.y;
+       v1.z /= v2.z;
+       v1.w /= v2.w;
+}
+
+// binary vector (op) scalar and scalar (op) vector operations
+inline Vector4 operator +(const Vector4 &vec, scalar_t scalar) {
+       return Vector4(vec.x + scalar, vec.y + scalar, vec.z + scalar, vec.w + scalar);
+}
+
+inline Vector4 operator +(scalar_t scalar, const Vector4 &vec) {
+       return Vector4(vec.x + scalar, vec.y + scalar, vec.z + scalar, vec.w + scalar);
+}
+
+inline Vector4 operator -(const Vector4 &vec, scalar_t scalar) {
+       return Vector4(vec.x - scalar, vec.y - scalar, vec.z - scalar, vec.w - scalar);
+}
+
+inline Vector4 operator -(scalar_t scalar, const Vector4 &vec) {
+       return Vector4(vec.x - scalar, vec.y - scalar, vec.z - scalar, vec.w - scalar);
+}
+
+inline Vector4 operator *(const Vector4 &vec, scalar_t scalar) {
+       return Vector4(vec.x * scalar, vec.y * scalar, vec.z * scalar, vec.w * scalar);
+}
+
+inline Vector4 operator *(scalar_t scalar, const Vector4 &vec) {
+       return Vector4(vec.x * scalar, vec.y * scalar, vec.z * scalar, vec.w * scalar);
+}
+
+inline Vector4 operator /(const Vector4 &vec, scalar_t scalar) {
+       return Vector4(vec.x / scalar, vec.y / scalar, vec.z / scalar, vec.w / scalar);
+}
+
+inline Vector4 operator /(scalar_t scalar, const Vector4 &vec) {
+       return Vector4(vec.x / scalar, vec.y / scalar, vec.z / scalar, vec.w / scalar);
+}
+
+inline void operator +=(Vector4 &vec, scalar_t scalar) {
+       vec.x += scalar;
+       vec.y += scalar;
+       vec.z += scalar;
+       vec.w += scalar;
+}
+
+inline void operator -=(Vector4 &vec, scalar_t scalar) {
+       vec.x -= scalar;
+       vec.y -= scalar;
+       vec.z -= scalar;
+       vec.w -= scalar;
+}
+
+inline void operator *=(Vector4 &vec, scalar_t scalar) {
+       vec.x *= scalar;
+       vec.y *= scalar;
+       vec.z *= scalar;
+       vec.w *= scalar;
+}
+
+inline void operator /=(Vector4 &vec, scalar_t scalar) {
+       vec.x /= scalar;
+       vec.y /= scalar;
+       vec.z /= scalar;
+       vec.w /= scalar;
+}
+
+inline scalar_t Vector4::length() const {
+       return sqrt(x*x + y*y + z*z + w*w);
+}
+inline scalar_t Vector4::length_sq() const {
+       return x*x + y*y + z*z + w*w;
+}
diff --git a/src/3dengfx/src/sim/makefile.part b/src/3dengfx/src/sim/makefile.part
new file mode 100644 (file)
index 0000000..f60c8e2
--- /dev/null
@@ -0,0 +1 @@
+sim_obj = src/sim/sim.o
diff --git a/src/3dengfx/src/sim/rigid.cpp b/src/3dengfx/src/sim/rigid.cpp
new file mode 100644 (file)
index 0000000..c528ae4
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+This file is part of the simulation module of 3dengfx.
+
+Copyright (c) 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "rigid.hpp"
+#include <ode/ode.h>
+
+RigidBody::RigidBody(dWorldID world) {
+       body = dBodyCreate(world);
+}
+
+RigidBody::~RigidBody() {
+       dBodyDestroy(body);
+}
+
+void RigidBody::enable() {
+       dBodyEnable(body);
+}
+
+void RigidBody::disable() {
+       dBodyDisable(body);
+}
+
+void RigidBody::set_position(const Vector3 &pos, unsigned long time) {
+       dBodySetPosition(body, pos.x, pos.y, pos.z);
+       Object::set_position(pos, time);
+}
+
+#define MAT3_TO_ODE(m, o)\
+       for(int i=0; i<3; i++) {\
+               for(int j=0; j<3; j++) {\
+                       dACCESS33(o, i, j) = m[i][j];\
+               }\
+       }
+
+
+void RigidBody::set_rotation(const Quaternion &rot, unsigned long time) {
+       Matrix3x3 mat = rot.get_rotation_matrix();
+       dMatrix3 ode_mat;
+       MAT3_TO_ODE(mat, ode_mat);
+       dBodySetRotation(body, ode_mat);
+       Object::set_rotation(rot, time);
+}
+
+void RigidBody::set_rotation(const Vector3 &euler, unsigned long time) {
+       Matrix3x3 mat;
+       dMatrix3 ode_mat;
+       mat.set_rotation(euler);
+       MAT3_TO_ODE(mat, ode_mat);
+       dBodySetRotation(body, ode_mat);
+       Object::set_rotation(euler, time);
+}
+
+void RigidBody::translate(const Vector3 &trans, unsigned long time) {
+}
+
+void RigidBody::rotate(const Quaternion &rot, unsigned long time) {
+}
+
+void RigidBody::rotate(const Vector3 &euler, unsigned long time) {
+}
+
+void RigidBody::rotate(const Matrix3x3 &rmat, unsigned long time) {
+}
+
+RigidSim::RigidSim() {
+       world = dWorldCreate();
+
+       set_gravity(Vector3(0, -9.81, 0));
+}
+
+RigidSim::~RigidSim() {
+       dWorldDestroy(world);
+}
+
+void RigidSim::run(unsigned long msec) {
+       dWorldStep(world, timeslice);
+}
+
+void RigidSim::set_gravity(const Vector3 &gvec) {
+       dWorldSetGravity(world, gvec.x, gvec.y, gvec.z);
+}
+
+void RigidSim::add_object(Object *obj) {
+       if(obj) {
+               obj_list.push_back(obj);
+               // TODO: cont. here...
+       }
+}
diff --git a/src/3dengfx/src/sim/rigid.hpp b/src/3dengfx/src/sim/rigid.hpp
new file mode 100644 (file)
index 0000000..478057a
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+This file is part of the simulation module of 3dengfx.
+
+Copyright (c) 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef RIGID_HPP_
+#define RIGID_HPP_
+
+#include <list>
+#include <ode/ode.h>
+#include "sim.hpp"
+#include "3dengfx/object.hpp"
+
+class RigidBody : Object {
+private:
+       dBodyID body;
+       dMass mass;
+       
+public:
+       RigidBody(dWorldID world);
+       ~RigidBody();
+
+       void enable();
+       void disable();
+
+       virtual void set_position(const Vector3 &pos, unsigned long time = XFORM_LOCAL_PRS);
+       virtual void set_rotation(const Quaternion &rot, unsigned long time = XFORM_LOCAL_PRS);
+       virtual void set_rotation(const Vector3 &euler, unsigned long time = XFORM_LOCAL_PRS);
+
+       virtual void translate(const Vector3 &trans, unsigned long time = XFORM_LOCAL_PRS);
+       virtual void rotate(const Quaternion &rot, unsigned long time = XFORM_LOCAL_PRS);
+       virtual void rotate(const Vector3 &euler, unsigned long time = XFORM_LOCAL_PRS);
+       virtual void rotate(const Matrix3x3 &rmat, unsigned long time = XFORM_LOCAL_PRS);
+}
+
+class RigidSim : public Simulation {
+protected:
+       dWorldID world;
+       std::list<Object*> obj_list;
+       
+       virtual void run(unsigned long msec);
+
+public:
+       RigidSim();
+       virtual ~RigidSim();
+
+       void set_gravity(const Vector3 &gvec);
+       void add_object(Object *obj);
+};
+
+#endif // RIGID_HPP_
diff --git a/src/3dengfx/src/sim/rope.cpp b/src/3dengfx/src/sim/rope.cpp
new file mode 100644 (file)
index 0000000..03333e3
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+This file is part of the simulation module of 3dengfx.
+
+Copyright (c) 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* rope (linear spring system) simulation
+ *
+ * Author: John Tsiombikas 2005
+ */
+
+#include "rope.hpp"
+
+RopeSim::RopeSim(scalar_t timeslice) : Simulation(timeslice) {}
+
+const SpringConn *RopeSim::add_connection(const SpringConn &conn) {
+       connections.push_back(conn);
+       return 0;       // TODO: fix
+}
diff --git a/src/3dengfx/src/sim/rope.hpp b/src/3dengfx/src/sim/rope.hpp
new file mode 100644 (file)
index 0000000..d039faf
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+This file is part of the simulation module of 3dengfx.
+
+Copyright (c) 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* rope (linear spring system) simulation
+ *
+ * Author: John Tsiombikas 2005
+ */
+#ifndef _ROPE_HPP_
+#define _ROPE_HPP_
+
+#include <string>
+#include <list>
+#include "sim.hpp"
+#include "spring.hpp"
+
+class RopeSim : public Simulation {
+private:
+       std::list<SpringConn> connections;
+       std::list<Spring> springs;
+       
+protected:
+       virtual void run(unsigned long msec);
+
+public:
+       RopeSim(scalar_t timeslice = SIM_STD_TIMESLICE);
+
+       const SpringConn *add_connection(const SpringConn &conn);
+       void add_spring(const Spring &spring);
+};
+
+#endif // _ROPE_HPP_
diff --git a/src/3dengfx/src/sim/sim.cpp b/src/3dengfx/src/sim/sim.cpp
new file mode 100644 (file)
index 0000000..00575a9
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+This file is part of the simulation module of 3dengfx.
+
+Copyright (c) 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* provides a basic framework for running time-based simulations
+ *
+ * Author: John Tsiombikas 2005
+ */
+
+#include "sim.hpp"
+
+Simulation::Simulation(scalar_t timeslice) {
+       this->timeslice = timeslice;
+       timer_reset(&timer);
+}
+
+Simulation::~Simulation() {}
+
+void Simulation::start() {
+       timer_start(&timer);
+}
+
+void Simulation::stop() {
+       timer_stop(&timer);
+}
+
+void Simulation::reset() {
+       timer_reset(&timer);
+}
+
+void Simulation::update() {
+       update(timer_getmsec(&timer));
+}
+
+void Simulation::update(unsigned long msec) {
+       scalar_t time = (scalar_t)msec / 1000.0;
+       int updates_missed = (int)round((time - prev_update) / timeslice);
+
+       if(!updates_missed) return;     // less than a timeslice has elapsed, nothing to do
+
+       scalar_t t = prev_update * 1000.0;
+       for(int i=0; i<updates_missed; i++) {
+               t += timeslice;
+               run((unsigned long)(t * 1000.0));
+       }
+
+       prev_update = msec;
+}
diff --git a/src/3dengfx/src/sim/sim.hpp b/src/3dengfx/src/sim/sim.hpp
new file mode 100644 (file)
index 0000000..3e92164
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+This file is part of the simulation module of 3dengfx.
+
+Copyright (c) 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* provides a basic framework for running time-based simulations
+ *
+ * Author: John Tsiombikas 2005
+ */
+
+#ifndef _SIM_HPP_
+#define _SIM_HPP_
+
+#include "n3dmath2/n3dmath2.hpp"
+#include "common/timer.h"
+
+#define SIM_STD_TIMESLICE      1.0 / 30.0
+
+class Simulation {
+private:
+       scalar_t timeslice;             // time between two updates (in seconds)
+       scalar_t prev_update;
+       ntimer timer;
+
+protected:
+       virtual void run(unsigned long msec) = 0;       // override this
+
+public:
+       Simulation(scalar_t timeslice = SIM_STD_TIMESLICE);
+       virtual ~Simulation();
+
+       void start();
+       void stop();
+       void reset();
+
+       void update();
+       void update(unsigned long msec);        // overrides dedicated timer
+};
+       
+
+#endif // _SIM_HPP_
diff --git a/src/3dengfx/src/sim/spring.cpp b/src/3dengfx/src/sim/spring.cpp
new file mode 100644 (file)
index 0000000..faf8a9e
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+This file is part of the simulation module of 3dengfx.
+
+Copyright (c) 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* Spring, not the season... the one with the -K
+ *
+ * Author: John Tsiombikas 2005
+ */
+
+#include "spring.hpp"
+
+SpringConn::spring_conn(const Vector3 &pos, bool fixed) {
+       this->fixed = fixed;
+       set_position(pos);
+       weight = 1.0;
+}
+
+void SpringConn::set_fixed(bool fixed) {
+       this->fixed = fixed;
+}
+
+bool SpringConn::is_fixed() const {
+       return fixed;
+}
+
+void SpringConn::set_weight(scalar_t weight) {
+       this->weight = weight;
+}
+
+scalar_t SpringConn::get_weight() const {
+       return weight;
+}
+
+
+Spring::Spring() {
+       stiffness = 1.0;
+       length = 1.0;
+       ends[0] = ends[1] = 0;
+}
+
+Spring::Spring(SpringConn *end1, SpringConn *end2, scalar_t k, scalar_t len) {
+       stiffness = k;
+       length = len;
+       ends[0] = end1;
+       ends[1] = end2;
+}
+
+void Spring::set_ends(SpringConn *end1, SpringConn *end2) {
+       ends[0] = end1;
+       ends[1] = end2;
+}
+
+void Spring::set_stiffness(scalar_t stiffness) {
+       this->stiffness = stiffness;
+}
+
+void Spring::set_length(scalar_t len) {
+       length = len;
+}
+
+Vector3 Spring::calc_force(int end) const {
+       return Vector3();
+}
diff --git a/src/3dengfx/src/sim/spring.hpp b/src/3dengfx/src/sim/spring.hpp
new file mode 100644 (file)
index 0000000..64f9e1d
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+This file is part of the simulation module of 3dengfx.
+
+Copyright (c) 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* Spring, not the season... the one with the -K
+ *
+ * Author: John Tsiombikas 2005
+ */
+
+#ifndef _SPRING_HPP_
+#define _SPRING_HPP_
+
+#include <gfx/animation.hpp>
+#include "spring.hpp"
+
+class SpringPoint : public XFormNode {
+public:
+       bool fixed;
+       scalar_t weight;
+       Spring *spr[2];
+
+       SpringPoint(const Vector3 &pos = Vector3(), bool fixed = false);
+
+       virtual void set_fixed(bool fixed);
+       virtual bool is_fixed() const;
+
+       virtual void set_weight(scalar_t weight);
+       virtual scalar_t get_weight() const;
+
+       virtual void calc();
+};
+
+
+class Spring {
+private:
+       scalar_t stiffness;     // the k thingy
+       scalar_t length;        // the length of the string with no forces acting on it
+
+public:
+       Spring();
+       Spring(SpringConn *end1, SpringConn *end2, scalar_t k, scalar_t len);
+
+       void set_ends(SpringConn *end1, SpringConn *end2);
+       void set_stiffness(scalar_t stiffness);
+       void set_length(scalar_t len);
+
+       Vector3 calc_force(int end) const;
+};
+
+#endif // _SPRING_HPP_