https://svn.lrde.epita.fr/svn/oln/trunk
Index: ChangeLog
from Roland Levillain <roland(a)lrde.epita.fr>
Add the trimesh2 library (version 2.8) as an external dependency.
* external/: New directory.
* external/README: New.
* external/trimesh/
* external/trimesh/COPYING,
* external/trimesh/Makedefs.Darwin,
* external/trimesh/Makedefs.Linux,
* external/trimesh/Makedefs.Linux64,
* external/trimesh/Makedefs.SunOS,
* external/trimesh/Makedefs.Win32,
* external/trimesh/Makefile,
* external/trimesh/Makerules,
* external/trimesh/README,
* external/trimesh/gluit/,
* external/trimesh/gluit/COPYING.freeglut,
* external/trimesh/gluit/COPYING.glui,
* external/trimesh/gluit/Makefile,
* external/trimesh/gluit/freeglut_callbacks.c,
* external/trimesh/gluit/freeglut_cursor.c,
* external/trimesh/gluit/freeglut_display.c,
* external/trimesh/gluit/freeglut_ext.c,
* external/trimesh/gluit/freeglut_font.c,
* external/trimesh/gluit/freeglut_font_data.c,
* external/trimesh/gluit/freeglut_gamemode.c,
* external/trimesh/gluit/freeglut_geometry.c,
* external/trimesh/gluit/freeglut_glutfont_definitions.c,
* external/trimesh/gluit/freeglut_init.c,
* external/trimesh/gluit/freeglut_internal.h,
* external/trimesh/gluit/freeglut_joystick.c,
* external/trimesh/gluit/freeglut_main.c,
* external/trimesh/gluit/freeglut_menu.c,
* external/trimesh/gluit/freeglut_misc.c,
* external/trimesh/gluit/freeglut_overlay.c,
* external/trimesh/gluit/freeglut_state.c,
* external/trimesh/gluit/freeglut_stroke_mono_roman.c,
* external/trimesh/gluit/freeglut_stroke_roman.c,
* external/trimesh/gluit/freeglut_structure.c,
* external/trimesh/gluit/freeglut_teapot.c,
* external/trimesh/gluit/freeglut_teapot_data.h,
* external/trimesh/gluit/freeglut_videoresize.c,
* external/trimesh/gluit/freeglut_window.c,
* external/trimesh/gluit/glui.cc,
* external/trimesh/gluit/glui_add_controls.cc,
* external/trimesh/gluit/glui_algebra3.cc,
* external/trimesh/gluit/glui_algebra3.h,
* external/trimesh/gluit/glui_arcball.cc,
* external/trimesh/gluit/glui_arcball.h,
* external/trimesh/gluit/glui_bitmap_img_data.cc,
* external/trimesh/gluit/glui_bitmaps.cc,
* external/trimesh/gluit/glui_button.cc,
* external/trimesh/gluit/glui_checkbox.cc,
* external/trimesh/gluit/glui_column.cc,
* external/trimesh/gluit/glui_control.cc,
* external/trimesh/gluit/glui_edittext.cc,
* external/trimesh/gluit/glui_img_checkbox_0.c,
* external/trimesh/gluit/glui_img_checkbox_0_dis.c,
* external/trimesh/gluit/glui_img_checkbox_1.c,
* external/trimesh/gluit/glui_img_checkbox_1_dis.c,
* external/trimesh/gluit/glui_img_downarrow.c,
* external/trimesh/gluit/glui_img_leftarrow.c,
* external/trimesh/gluit/glui_img_listbox_down.c,
* external/trimesh/gluit/glui_img_listbox_up.c,
* external/trimesh/gluit/glui_img_listbox_up_dis.c,
* external/trimesh/gluit/glui_img_radiobutton_0.c,
* external/trimesh/gluit/glui_img_radiobutton_0_dis.c,
* external/trimesh/gluit/glui_img_radiobutton_1.c,
* external/trimesh/gluit/glui_img_radiobutton_1_dis.c,
* external/trimesh/gluit/glui_img_rightarrow.c,
* external/trimesh/gluit/glui_img_spindown_0.c,
* external/trimesh/gluit/glui_img_spindown_1.c,
* external/trimesh/gluit/glui_img_spindown_dis.c,
* external/trimesh/gluit/glui_img_spinup_0.c,
* external/trimesh/gluit/glui_img_spinup_1.c,
* external/trimesh/gluit/glui_img_spinup_dis.c,
* external/trimesh/gluit/glui_img_uparrow.c,
* external/trimesh/gluit/glui_listbox.cc,
* external/trimesh/gluit/glui_mouse_iaction.cc,
* external/trimesh/gluit/glui_node.cc,
* external/trimesh/gluit/glui_panel.cc,
* external/trimesh/gluit/glui_quaternion.cc,
* external/trimesh/gluit/glui_quaternion.h,
* external/trimesh/gluit/glui_radio.cc,
* external/trimesh/gluit/glui_rollout.cc,
* external/trimesh/gluit/glui_rotation.cc,
* external/trimesh/gluit/glui_separator.cc,
* external/trimesh/gluit/glui_slider.cc,
* external/trimesh/gluit/glui_spinner.cc,
* external/trimesh/gluit/glui_statictext.cc,
* external/trimesh/gluit/glui_stdinc.h,
* external/trimesh/gluit/glui_translation.cc,
* external/trimesh/include/,
* external/trimesh/include/Color.h,
* external/trimesh/include/GL/,
* external/trimesh/include/GL/freeglut.h,
* external/trimesh/include/GL/freeglut_ext.h,
* external/trimesh/include/GL/freeglut_std.h,
* external/trimesh/include/GL/glui.h,
* external/trimesh/include/GL/glut.h,
* external/trimesh/include/GLCamera.h,
* external/trimesh/include/ICP.h,
* external/trimesh/include/KDtree.h,
* external/trimesh/include/TriMesh.h,
* external/trimesh/include/TriMesh_algo.h,
* external/trimesh/include/Vec.h,
* external/trimesh/include/XForm.h,
* external/trimesh/include/bsphere.h,
* external/trimesh/include/lineqn.h,
* external/trimesh/include/mempool.h,
* external/trimesh/include/noise3d.h,
* external/trimesh/include/timestamp.h,
* external/trimesh/libsrc/,
* external/trimesh/libsrc/GLCamera.cc,
* external/trimesh/libsrc/ICP.cc,
* external/trimesh/libsrc/KDtree.cc,
* external/trimesh/libsrc/Makefile,
* external/trimesh/libsrc/TriMesh_bounding.cc,
* external/trimesh/libsrc/TriMesh_connectivity.cc,
* external/trimesh/libsrc/TriMesh_curvature.cc,
* external/trimesh/libsrc/TriMesh_grid.cc,
* external/trimesh/libsrc/TriMesh_io.cc,
* external/trimesh/libsrc/TriMesh_normals.cc,
* external/trimesh/libsrc/TriMesh_pointareas.cc,
* external/trimesh/libsrc/TriMesh_stats.cc,
* external/trimesh/libsrc/TriMesh_tstrips.cc,
* external/trimesh/libsrc/diffuse.cc,
* external/trimesh/libsrc/edgeflip.cc,
* external/trimesh/libsrc/faceflip.cc,
* external/trimesh/libsrc/filter.cc,
* external/trimesh/libsrc/lmsmooth.cc,
* external/trimesh/libsrc/mesh_align.cc,
* external/trimesh/libsrc/mesh_view.cc,
* external/trimesh/libsrc/remove.cc,
* external/trimesh/libsrc/reorder_verts.cc,
* external/trimesh/libsrc/subdiv.cc,
* external/trimesh/utilsrc/,
* external/trimesh/utilsrc/Makefile,
* external/trimesh/utilsrc/mesh_align.cc,
* external/trimesh/utilsrc/mesh_cat.cc,
* external/trimesh/utilsrc/mesh_cc.cc,
* external/trimesh/utilsrc/mesh_filter.cc,
* external/trimesh/utilsrc/mesh_make.cc,
* external/trimesh/utilsrc/mesh_shade.cc,
* external/trimesh/utilsrc/mesh_view.cc:
New. Imported from
http://www.cs.princeton.edu/gfx/proj/trimesh2/src/trimesh2-2.8.tar.gz.
README | 60
trimesh/COPYING | 302 ++
trimesh/Makedefs.Darwin | 53
trimesh/Makedefs.Linux | 59
trimesh/Makedefs.Linux64 | 59
trimesh/Makedefs.SunOS | 50
trimesh/Makedefs.Win32 | 69
trimesh/Makefile | 20
trimesh/Makerules | 80
trimesh/README | 144 +
trimesh/gluit/COPYING.freeglut | 27
trimesh/gluit/COPYING.glui | 504 ++++
trimesh/gluit/Makefile | 75
trimesh/gluit/freeglut_callbacks.c | 336 +++
trimesh/gluit/freeglut_cursor.c | 270 ++
trimesh/gluit/freeglut_display.c | 99
trimesh/gluit/freeglut_ext.c | 205 +
trimesh/gluit/freeglut_font.c | 368 +++
trimesh/gluit/freeglut_font_data.c | 2024 ++++++++++++++++++
trimesh/gluit/freeglut_gamemode.c | 598 +++++
trimesh/gluit/freeglut_geometry.c | 1147 ++++++++++
trimesh/gluit/freeglut_glutfont_definitions.c | 77
trimesh/gluit/freeglut_init.c | 899 ++++++++
trimesh/gluit/freeglut_internal.h | 854 +++++++
trimesh/gluit/freeglut_joystick.c | 1805 ++++++++++++++++
trimesh/gluit/freeglut_main.c | 1982 ++++++++++++++++++
trimesh/gluit/freeglut_menu.c | 949 ++++++++
trimesh/gluit/freeglut_misc.c | 179 +
trimesh/gluit/freeglut_overlay.c | 49
trimesh/gluit/freeglut_state.c | 694 ++++++
trimesh/gluit/freeglut_stroke_mono_roman.c | 2821 ++++++++++++++++++++++++++
trimesh/gluit/freeglut_stroke_roman.c | 2821 ++++++++++++++++++++++++++
trimesh/gluit/freeglut_structure.c | 651 ++++++
trimesh/gluit/freeglut_teapot.c | 207 +
trimesh/gluit/freeglut_teapot_data.h | 2428 ++++++++++++++++++++++
trimesh/gluit/freeglut_videoresize.c | 54
trimesh/gluit/freeglut_window.c | 1092 ++++++++++
trimesh/gluit/glui.cc | 1960 ++++++++++++++++++
trimesh/gluit/glui_add_controls.cc | 742 ++++++
trimesh/gluit/glui_algebra3.cc | 1037 +++++++++
trimesh/gluit/glui_algebra3.h | 474 ++++
trimesh/gluit/glui_arcball.cc | 223 ++
trimesh/gluit/glui_arcball.h | 80
trimesh/gluit/glui_bitmap_img_data.cc | 22
trimesh/gluit/glui_bitmaps.cc | 104
trimesh/gluit/glui_button.cc | 208 +
trimesh/gluit/glui_checkbox.cc | 313 ++
trimesh/gluit/glui_column.cc | 76
trimesh/gluit/glui_control.cc | 1223 +++++++++++
trimesh/gluit/glui_edittext.cc | 1045 +++++++++
trimesh/gluit/glui_img_checkbox_0.c | 38
trimesh/gluit/glui_img_checkbox_0_dis.c | 38
trimesh/gluit/glui_img_checkbox_1.c | 38
trimesh/gluit/glui_img_checkbox_1_dis.c | 38
trimesh/gluit/glui_img_downarrow.c | 56
trimesh/gluit/glui_img_leftarrow.c | 56
trimesh/gluit/glui_img_listbox_down.c | 42
trimesh/gluit/glui_img_listbox_up.c | 42
trimesh/gluit/glui_img_listbox_up_dis.c | 42
trimesh/gluit/glui_img_radiobutton_0.c | 44
trimesh/gluit/glui_img_radiobutton_0_dis.c | 44
trimesh/gluit/glui_img_radiobutton_1.c | 44
trimesh/gluit/glui_img_radiobutton_1_dis.c | 44
trimesh/gluit/glui_img_rightarrow.c | 56
trimesh/gluit/glui_img_spindown_0.c | 24
trimesh/gluit/glui_img_spindown_1.c | 24
trimesh/gluit/glui_img_spindown_dis.c | 24
trimesh/gluit/glui_img_spinup_0.c | 24
trimesh/gluit/glui_img_spinup_1.c | 24
trimesh/gluit/glui_img_spinup_dis.c | 24
trimesh/gluit/glui_img_uparrow.c | 56
trimesh/gluit/glui_listbox.cc | 445 ++++
trimesh/gluit/glui_mouse_iaction.cc | 212 +
trimesh/gluit/glui_node.cc | 175 +
trimesh/gluit/glui_panel.cc | 178 +
trimesh/gluit/glui_quaternion.cc | 229 ++
trimesh/gluit/glui_quaternion.h | 97
trimesh/gluit/glui_radio.cc | 341 +++
trimesh/gluit/glui_rollout.cc | 286 ++
trimesh/gluit/glui_rotation.cc | 389 +++
trimesh/gluit/glui_separator.cc | 60
trimesh/gluit/glui_slider.cc | 725 ++++++
trimesh/gluit/glui_spinner.cc | 579 +++++
trimesh/gluit/glui_statictext.cc | 124 +
trimesh/gluit/glui_stdinc.h | 131 +
trimesh/gluit/glui_translation.cc | 518 ++++
trimesh/include/Color.h | 107
trimesh/include/GL/freeglut.h | 22
trimesh/include/GL/freeglut_ext.h | 124 +
trimesh/include/GL/freeglut_std.h | 579 +++++
trimesh/include/GL/glui.h | 1767 ++++++++++++++++
trimesh/include/GL/glut.h | 29
trimesh/include/GLCamera.h | 74
trimesh/include/ICP.h | 40
trimesh/include/KDtree.h | 46
trimesh/include/TriMesh.h | 161 +
trimesh/include/TriMesh_algo.h | 145 +
trimesh/include/Vec.h | 459 ++++
trimesh/include/XForm.h | 317 ++
trimesh/include/bsphere.h | 273 ++
trimesh/include/lineqn.h | 358 +++
trimesh/include/mempool.h | 88
trimesh/include/noise3d.h | 127 +
trimesh/include/timestamp.h | 69
trimesh/libsrc/GLCamera.cc | 378 +++
trimesh/libsrc/ICP.cc | 858 +++++++
trimesh/libsrc/KDtree.cc | 299 ++
trimesh/libsrc/Makefile | 45
trimesh/libsrc/TriMesh_bounding.cc | 135 +
trimesh/libsrc/TriMesh_connectivity.cc | 124 +
trimesh/libsrc/TriMesh_curvature.cc | 325 ++
trimesh/libsrc/TriMesh_grid.cc | 109 +
trimesh/libsrc/TriMesh_io.cc | 1925 +++++++++++++++++
trimesh/libsrc/TriMesh_normals.cc | 118 +
trimesh/libsrc/TriMesh_pointareas.cc | 77
trimesh/libsrc/TriMesh_stats.cc | 46
trimesh/libsrc/TriMesh_tstrips.cc | 245 ++
trimesh/libsrc/diffuse.cc | 353 +++
trimesh/libsrc/edgeflip.cc | 176 +
trimesh/libsrc/faceflip.cc | 30
trimesh/libsrc/filter.cc | 491 ++++
trimesh/libsrc/lmsmooth.cc | 76
trimesh/libsrc/mesh_align.cc | 78
trimesh/libsrc/mesh_view.cc | 599 +++++
trimesh/libsrc/remove.cc | 137 +
trimesh/libsrc/reorder_verts.cc | 210 +
trimesh/libsrc/subdiv.cc | 396 +++
trimesh/utilsrc/Makefile | 46
trimesh/utilsrc/mesh_align.cc | 91
trimesh/utilsrc/mesh_cat.cc | 84
trimesh/utilsrc/mesh_cc.cc | 333 +++
trimesh/utilsrc/mesh_filter.cc | 394 +++
trimesh/utilsrc/mesh_make.cc | 976 ++++++++
trimesh/utilsrc/mesh_shade.cc | 507 ++++
trimesh/utilsrc/mesh_view.cc | 598 +++++
135 files changed, 51973 insertions(+)
Index: external/trimesh/Makedefs.Win32
--- external/trimesh/Makedefs.Win32 (revision 0)
+++ external/trimesh/Makedefs.Win32 (revision 0)
@@ -0,0 +1,69 @@
+ifneq (,$(findstring CYGWIN,$(shell uname)))
+ # Cygwin
+ CC = gcc
+ CXX = g++
+ AR = ar
+else
+ # Mingw32 cross compiler
+ CC = i386-mingw32-gcc
+ CXX = i386-mingw32-g++
+ AR = i386-mingw32-ar
+endif
+
+EXE = .exe
+
+
+ifdef DEBUG
+ COPTS = -mno-cygwin
+ COPTS += -ggdb3
+ COPTS += -Wall -W -Wno-unused -Wno-sign-compare -Wno-unknown-pragmas
+ CXXOPTS = $(COPTS)
+else
+ COPTS = -mno-cygwin
+ #COPTS += -mwindows # No commandline window
+ COPTS += -march=pentium3 -mfpmath=sse
+ COPTS += -O3 -ffast-math -funroll-loops -fomit-frame-pointer
+ COPTS += -Wall -W -Wno-unused -Wno-sign-compare -Wno-unknown-pragmas
+ CXXOPTS = $(COPTS)
+ LDOPTS = -s
+endif
+
+CFLAGS = $(INCLUDES) $(DEFINES) $(COPTS)
+CXXFLAGS = $(INCLUDES) $(DEFINES) $(CXXOPTS)
+LDFLAGS = $(LIBDIR) $(LDOPTS)
+
+
+LIBS = -lm
+GLLIBS = -lgluit -lwinmm -lopengl32 -lglu32 -lgdi32
+
+
+$(OBJDIR)/%.o: %.c
+ @ echo "Compiling $<"
+ @ rm -f "$(@:.o=.d)" && env DEPENDENCIES_OUTPUT="$(@:.o=.d)
$@" $(CC) $(CFLAGS) -c $< -o $@
+
+$(OBJDIR)/%.o: %.cc
+ @ echo "Compiling $<"
+ @ rm -f "$(@:.o=.d)" && env DEPENDENCIES_OUTPUT="$(@:.o=.d)
$@" $(CXX) $(CXXFLAGS) -c $< -o $@
+
+
+define LINK
+ @ echo "Linking $@"
+ @ rm -f $@
+ @ $(CXX) $(CXXFLAGS) $^ $(LDFLAGS) $(LIBS) -o $@
+endef
+
+define STATICLIB
+ @ echo "Creating library $@"
+ @ rm -f $@
+ @ $(AR) -rcs $@ $^
+endef
+
+define SHAREDLIB
+ @ echo "Creating library $@"
+ @ rm -f $@
+ @ $(CXX) $(CXXFLAGS) -shared $^ -o $@
+endef
+
+
+-include $(OBJDIR)/*.d
+
Index: external/trimesh/Makedefs.Darwin
--- external/trimesh/Makedefs.Darwin (revision 0)
+++ external/trimesh/Makedefs.Darwin (revision 0)
@@ -0,0 +1,53 @@
+CC = gcc
+CXX = g++
+AR = ar
+
+ifdef DEBUG
+ COPTS += -ggdb3
+ COPTS += -Wall -W -Wno-unused -Wno-sign-compare -Wno-unknown-pragmas
+ CXXOPTS = $(COPTS)
+else
+ COPTS += -O3 -ffast-math -funroll-loops -fomit-frame-pointer
+ COPTS += -Wall -W -Wno-unused -Wno-sign-compare -Wno-unknown-pragmas
+ CXXOPTS = $(COPTS)
+endif
+
+CFLAGS = $(INCLUDES) $(DEFINES) $(COPTS)
+CXXFLAGS = $(INCLUDES) $(DEFINES) $(CXXOPTS) -DDARWIN
+LDFLAGS = $(LIBDIR) $(LDOPTS) -multiply_defined suppress
+
+
+LIBS = -lm -lobjc
+GLLIBS = -framework GLUT -framework OpenGL -lgluit
+
+
+$(OBJDIR)/%.o: %.c
+ @ echo "Compiling $<"
+ @ rm -f "$(@:.o=.d)" && env DEPENDENCIES_OUTPUT="$(@:.o=.d)
$@" $(CC) $(CFLAGS) -c $< -o $@
+
+$(OBJDIR)/%.o: %.cc
+ @ echo "Compiling $<"
+ @ rm -f "$(@:.o=.d)" && env DEPENDENCIES_OUTPUT="$(@:.o=.d)
$@" $(CXX) $(CXXFLAGS) -c $< -o $@
+
+
+define LINK
+ @ echo "Linking $@"
+ @ rm -f $@
+ @ $(CXX) $(CXXFLAGS) $^ $(LDFLAGS) $(LIBS) -o $@
+endef
+
+define STATICLIB
+ @ echo "Creating library $@"
+ @ rm -f $@
+ @ $(AR) -rcs $@ $^
+endef
+
+define SHAREDLIB
+ @ echo "Creating library $@"
+ @ rm -f $@
+ @ $(CXX) $(CXXFLAGS) -shared $^ -o $@
+endef
+
+
+-include $(OBJDIR)/*.d
+
Index: external/trimesh/include/GLCamera.h
--- external/trimesh/include/GLCamera.h (revision 0)
+++ external/trimesh/include/GLCamera.h (revision 0)
@@ -0,0 +1,74 @@
+#ifndef GLCAMERA_H
+#define GLCAMERA_H
+/*
+Szymon Rusinkiewicz
+Princeton University
+
+GLCamera.h
+Manages OpenGL camera and trackball/arcball interaction
+*/
+
+#include "Vec.h"
+#include "XForm.h"
+#include "timestamp.h"
+
+
+namespace Mouse {
+ enum button { NONE, ROTATE, MOVEXY, MOVEZ, WHEELUP, WHEELDOWN, LIGHT };
+};
+
+class GLCamera {
+private:
+ int lastmousex, lastmousey;
+ Mouse::button lastb;
+ timestamp last_time;
+
+ vec lightdir;
+
+ bool dospin;
+ point spincenter;
+ vec spinaxis;
+ float spinspeed;
+
+ float field_of_view, pixscale;
+ mutable float surface_depth;
+ float click_depth;
+ float tb_screen_x, tb_screen_y, tb_screen_size;
+ bool read_depth(int x, int y, point &p) const;
+
+ void startspin();
+ vec mouse2tb(float x, float y);
+ void rotate(int mousex, int mousey, xform &xf);
+ void movexy(int mousex, int mousey, xform &xf);
+ void movez(int mousex, int mousey, xform &xf);
+ void wheel(Mouse::button updown, xform &xf);
+ void relight(int mousex, int mousey);
+ void mouse_click(int mousex, int mousey,
+ const point &scene_center, float scene_size);
+
+public:
+ GLCamera() : lastb(Mouse::NONE), lightdir(vec(0,0,1)),
+ dospin(false), spinspeed(0), field_of_view(0.7f),
+ surface_depth(0.0f), click_depth(0.0f)
+ {
+ lightdir[0] = lightdir[1] = 0; lightdir[2] = 1;
+ last_time = now();
+ }
+
+ void setupGL(const point &scene_center, float scene_size) const;
+
+ void mouse(int mousex, int mousey, Mouse::button b,
+ const point &scene_center, float scene_size,
+ xform &xf);
+
+ bool autospin(xform &xf);
+ void stopspin() { dospin = false; }
+
+ vec light() const { return lightdir; }
+ void set_light(const vec &lightdir_) { lightdir = lightdir_; }
+
+ float fov() const { return field_of_view; }
+ void set_fov(float fov_) { field_of_view = fov_; }
+};
+
+#endif
Index: external/trimesh/include/ICP.h
--- external/trimesh/include/ICP.h (revision 0)
+++ external/trimesh/include/ICP.h (revision 0)
@@ -0,0 +1,40 @@
+#ifndef ICP_H
+#define ICP_H
+/*
+Szymon Rusinkiewicz
+Princeton University
+
+ICP.h
+Routines for doing ICP.
+*/
+
+#include "TriMesh.h"
+#include "XForm.h"
+#include "KDtree.h"
+
+
+// Determine which points on s1 and s2 overlap the other, filling in o1 and o2
+// Also fills in maxdist, if it is <= 0 on input
+extern void compute_overlaps(TriMesh *s1, TriMesh *s2,
+ const xform &xf1, const xform &xf2,
+ const KDtree *kd1, const KDtree *kd2,
+ vector<float> &o1, vector<float> &o2,
+ float &maxdist, int verbose);
+
+// Do ICP. Aligns mesh s2 to s1, updating xf2 with the new transform.
+// Returns alignment error, or -1 on failure.
+// Pass in 0 for maxdist to figure it out...
+// Pass in vector<float>() for weights to figure it out...
+extern float ICP(TriMesh *s1, TriMesh *s2,
+ const xform &xf1, xform &xf2,
+ const KDtree *kd1, const KDtree *kd2,
+ vector<float> &weights1, vector<float> &weights2,
+ float maxdist = 0.0f, int verbose = 0,
+ bool do_scale = false, bool do_affine = false);
+
+// Easier-to-use interface to ICP
+extern float ICP(TriMesh *s1, TriMesh *s2, const xform &xf1, xform &xf2,
+ int verbose = 0,
+ bool do_scale = false, bool do_affine = false);
+
+#endif
Index: external/trimesh/include/TriMesh.h
--- external/trimesh/include/TriMesh.h (revision 0)
+++ external/trimesh/include/TriMesh.h (revision 0)
@@ -0,0 +1,161 @@
+#ifndef TRIMESH_H
+#define TRIMESH_H
+/*
+Szymon Rusinkiewicz
+Princeton University
+
+TriMesh.h
+Class for triangle meshes.
+*/
+
+#include "Vec.h"
+#include "Color.h"
+#include <vector>
+using std::vector;
+
+
+class TriMesh {
+protected:
+ static bool read_helper(const char *filename, TriMesh *mesh);
+
+public:
+ // Types
+ struct Face {
+ int v[3];
+
+ Face() {}
+ Face(const int &v0, const int &v1, const int &v2)
+ { v[0] = v0; v[1] = v1; v[2] = v2; }
+ Face(const int *v_)
+ { v[0] = v_[0]; v[1] = v_[1]; v[2] = v_[2]; }
+ int &operator[] (int i) { return v[i]; }
+ const int &operator[] (int i) const { return v[i]; }
+ operator const int * () const { return &(v[0]); }
+ operator const int * () { return &(v[0]); }
+ operator int * () { return &(v[0]); }
+ int indexof(int v_) const
+ {
+ return (v[0] == v_) ? 0 :
+ (v[1] == v_) ? 1 :
+ (v[2] == v_) ? 2 : -1;
+ }
+ };
+
+ struct BBox {
+ point min, max;
+ point center() const { return 0.5f * (min+max); }
+ vec size() const { return max - min; }
+ bool valid;
+ BBox() : valid(false)
+ {}
+ };
+
+ struct BSphere {
+ point center;
+ float r;
+ bool valid;
+ BSphere() : valid(false)
+ {}
+ };
+
+ // Enums
+ enum tstrip_rep { TSTRIP_LENGTH, TSTRIP_TERM };
+ enum { GRID_INVALID = -1 };
+
+ // The basics: vertices and faces
+ vector<point> vertices;
+ vector<Face> faces;
+
+ // Triangle strips
+ vector<int> tstrips;
+
+ // Grid, if present
+ vector<int> grid;
+ int grid_width, grid_height;
+
+ // Other per-vertex properties
+ vector<Color> colors;
+ vector<float> confidences;
+ vector<unsigned> flags;
+ unsigned flag_curr;
+
+ // Computed per-vertex properties
+ vector<vec> normals;
+ vector<vec> pdir1, pdir2;
+ vector<float> curv1, curv2;
+ vector< Vec<4,float> > dcurv;
+ vector<vec> cornerareas;
+ vector<float> pointareas;
+
+ // Bounding structures
+ BBox bbox;
+ BSphere bsphere;
+
+ // Connectivity structures:
+ // For each vertex, all neighboring vertices
+ vector< vector<int> > neighbors;
+ // For each vertex, all neighboring faces
+ vector< vector<int> > adjacentfaces;
+ // For each face, the three faces attached to its edges
+ // (for example, across_edge[3][2] is the number of the face
+ // that's touching the edge opposite vertex 2 of face 3)
+ vector<Face> across_edge;
+
+ // Compute all this stuff...
+ void need_tstrips();
+ void convert_strips(tstrip_rep rep);
+ void unpack_tstrips();
+ void triangulate_grid();
+ void need_faces()
+ {
+ if (!faces.empty())
+ return;
+ if (!tstrips.empty())
+ unpack_tstrips();
+ else if (!grid.empty())
+ triangulate_grid();
+ }
+ void need_normals();
+ void need_pointareas();
+ void need_curvatures();
+ void need_dcurv();
+ void need_bbox();
+ void need_bsphere();
+ void need_neighbors();
+ void need_adjacentfaces();
+ void need_across_edge();
+
+ // Input and output
+ static TriMesh *read(const char *filename);
+ void write(const char *filename);
+
+ // Statistics
+ // XXX - Add stuff here
+ float feature_size();
+
+ // Useful queries
+ // XXX - Add stuff here
+ bool is_bdy(int v)
+ {
+ if (neighbors.empty()) need_neighbors();
+ if (adjacentfaces.empty()) need_adjacentfaces();
+ return neighbors[v].size() != adjacentfaces[v].size();
+ }
+ vec trinorm(int f)
+ {
+ if (faces.empty()) need_faces();
+ return ::trinorm(vertices[faces[f][0]], vertices[faces[f][1]],
+ vertices[faces[f][2]]);
+ }
+
+ // Debugging printout, controllable by a "verbose"ness parameter
+ static int verbose;
+ static void set_verbose(int);
+ static int dprintf(const char *format, ...);
+
+ // Constructor
+ TriMesh() : grid_width(-1), grid_height(-1), flag_curr(0)
+ {}
+};
+
+#endif
Index: external/trimesh/include/XForm.h
--- external/trimesh/include/XForm.h (revision 0)
+++ external/trimesh/include/XForm.h (revision 0)
@@ -0,0 +1,317 @@
+#ifndef XFORM_H
+#define XFORM_H
+/*
+Szymon Rusinkiewicz
+Princeton University
+
+XForm.h
+Affine transforms (represented internally as column-major 4x4 matrices)
+
+Supports the following operations:
+ xform xf1, xf2; // Initialized to the identity
+ XForm<float> xf3; // xform is XForm<double>
+ xf1=xform::trans(u,v,w);// An xform that translates.
+ xf1=xform::rot(ang,ax); // An xform that rotates.
+ xf1=xform::scale(s); // An xform that scales.
+ glMultMatrixd(xf1); // Conversion to column-major array
+ xf1.read("file.xf"); // Read xform from file
+ xf1.write("file.xf"); // Write xform to file
+ xf1 * xf2 // Matrix-matrix multiplication
+ xf1 * inv(xf2) // Inverse
+ xf1 * vec(1,2,3) // Matrix-vector multiplication
+ rot_only(xf1) // An xform that does the rotation of xf1
+ trans_only(xf1) // An xform that does the translation of xf1
+ norm_xf(xf1) // Normal xform: inverse transpose, no trans
+ invert(xf1); // Inverts xform in place
+ orthogonalize(xf1); // Makes matrix orthogonal
+*/
+
+#include "lineqn.h"
+#include <cmath>
+#include <algorithm>
+#include <iostream>
+#include <fstream>
+#include <string>
+using std::min;
+using std::max;
+using std::swap;
+using std::sqrt;
+
+template <class T>
+class XForm {
+private:
+ T m[16]; // Column-major (OpenGL) order
+
+public:
+ // Constructors: defaults to identity
+ XForm(const T m0 =1, const T m1 =0, const T m2 =0, const T m3 =0,
+ const T m4 =0, const T m5 =1, const T m6 =0, const T m7 =0,
+ const T m8 =0, const T m9 =0, const T m10=1, const T m11=0,
+ const T m12=0, const T m13=0, const T m14=0, const T m15=1)
+ {
+ m[0] = m0; m[1] = m1; m[2] = m2; m[3] = m3;
+ m[4] = m4; m[5] = m5; m[6] = m6; m[7] = m7;
+ m[8] = m8; m[9] = m9; m[10] = m10; m[11] = m11;
+ m[12] = m12; m[13] = m13; m[14] = m14; m[15] = m15;
+ }
+ template <class S> explicit XForm(const S &x)
+ { for (int i = 0; i < 16; i++) m[i] = x[i]; }
+
+ // Default destructor, copy constructor, assignment operator
+
+ // Array reference and conversion to array - no bounds checking
+ const T operator [] (int i) const
+ { return m[i]; }
+ T &operator [] (int i)
+ { return m[i]; }
+ operator const T *() const
+ { return m; }
+ operator const T *()
+ { return m; }
+ operator T *()
+ { return m; }
+
+ // Static members - really just fancy constructors
+ static XForm<T> identity()
+ { return XForm<T>(); }
+ static XForm<T> trans(const T &tx, const T &ty, const T &tz)
+ { return XForm<T>(1,0,0,0,0,1,0,0,0,0,1,0,tx,ty,tz,1); }
+ template <class S> static XForm<T> trans(const S &t)
+ { return XForm<T>::trans(t[0], t[1], t[2]); }
+ static XForm<T> rot(const T &angle,
+ const T &rx, const T &ry, const T &rz)
+ {
+ // Angle in radians, unlike OpenGL
+ T l = sqrt(rx*rx+ry*ry+rz*rz);
+ if (l == T(0))
+ return XForm<T>();
+ T l1 = T(1)/l, x = rx*l1, y = ry*l1, z = rz*l1;
+ T s = sin(angle), c = cos(angle);
+ T xs = x*s, ys = y*s, zs = z*s, c1 = T(1)-c;
+ T xx = c1*x*x, yy = c1*y*y, zz = c1*z*z;
+ T xy = c1*x*y, xz = c1*x*z, yz = c1*y*z;
+ return XForm<T>(xx+c, xy+zs, xz-ys, 0,
+ xy-zs, yy+c, yz+xs, 0,
+ xz+ys, yz-xs, zz+c, 0,
+ 0, 0, 0, 1);
+ }
+ template <class S> static XForm<T> rot(const T &angle, const S
&axis)
+ { return XForm<T>::rot(angle, axis[0], axis[1], axis[2]); }
+ static XForm<T> scale(const T &s)
+ { return XForm<T>(s,0,0,0,0,s,0,0,0,0,s,0,0,0,0,1); }
+ static XForm<T> scale(const T &sx, const T &sy, const T &sz)
+ { return XForm<T>(sx,0,0,0,0,sy,0,0,0,0,sz,0,0,0,0,1); }
+ static XForm<T> scale(const T &s, const T &dx, const T &dy, const T
&dz)
+ {
+ T dlen2 = dx*dx + dy*dy + dz*dz;
+ T s1 = (s - T(1)) / dlen2;
+ return XForm<T>(T(1) + s1*dx*dx, s1*dx*dy, s1*dx*dz, 0,
+ s1*dx*dy, T(1) + s1*dy*dy, s1*dy*dz, 0,
+ s1*dx*dz, s1*dy*dz, T(1) + s1*dz*dz, 0,
+ 0, 0, 0, 1);
+ }
+ template <class S> static XForm<T> scale(const T &s, const S &dir)
+ { return XForm<T>::scale(s, dir[0], dir[1], dir[2]); }
+
+ // Read an XForm from a file.
+ bool read(const std::string &filename)
+ {
+ std::ifstream f(filename.c_str());
+ XForm<T> M;
+ f >> M;
+ f.close();
+ if (f.good()) {
+ *this = M;
+ return true;
+ }
+ return false;
+ }
+
+ // Write an XForm to a file
+ bool write(const std::string &filename) const
+ {
+ std::ofstream f(filename.c_str());
+ f << *this;
+ f.close();
+ return f.good();
+ }
+};
+
+typedef XForm<double> xform;
+
+
+// Matrix multiplication
+template <class T>
+static inline XForm<T> operator * (const XForm<T> &xf1, const
XForm<T> &xf2)
+{
+ return XForm<T>(
+ xf1[ 0]*xf2[ 0]+xf1[ 4]*xf2[ 1]+xf1[ 8]*xf2[ 2]+xf1[12]*xf2[ 3],
+ xf1[ 1]*xf2[ 0]+xf1[ 5]*xf2[ 1]+xf1[ 9]*xf2[ 2]+xf1[13]*xf2[ 3],
+ xf1[ 2]*xf2[ 0]+xf1[ 6]*xf2[ 1]+xf1[10]*xf2[ 2]+xf1[14]*xf2[ 3],
+ xf1[ 3]*xf2[ 0]+xf1[ 7]*xf2[ 1]+xf1[11]*xf2[ 2]+xf1[15]*xf2[ 3],
+ xf1[ 0]*xf2[ 4]+xf1[ 4]*xf2[ 5]+xf1[ 8]*xf2[ 6]+xf1[12]*xf2[ 7],
+ xf1[ 1]*xf2[ 4]+xf1[ 5]*xf2[ 5]+xf1[ 9]*xf2[ 6]+xf1[13]*xf2[ 7],
+ xf1[ 2]*xf2[ 4]+xf1[ 6]*xf2[ 5]+xf1[10]*xf2[ 6]+xf1[14]*xf2[ 7],
+ xf1[ 3]*xf2[ 4]+xf1[ 7]*xf2[ 5]+xf1[11]*xf2[ 6]+xf1[15]*xf2[ 7],
+ xf1[ 0]*xf2[ 8]+xf1[ 4]*xf2[ 9]+xf1[ 8]*xf2[10]+xf1[12]*xf2[11],
+ xf1[ 1]*xf2[ 8]+xf1[ 5]*xf2[ 9]+xf1[ 9]*xf2[10]+xf1[13]*xf2[11],
+ xf1[ 2]*xf2[ 8]+xf1[ 6]*xf2[ 9]+xf1[10]*xf2[10]+xf1[14]*xf2[11],
+ xf1[ 3]*xf2[ 8]+xf1[ 7]*xf2[ 9]+xf1[11]*xf2[10]+xf1[15]*xf2[11],
+ xf1[ 0]*xf2[12]+xf1[ 4]*xf2[13]+xf1[ 8]*xf2[14]+xf1[12]*xf2[15],
+ xf1[ 1]*xf2[12]+xf1[ 5]*xf2[13]+xf1[ 9]*xf2[14]+xf1[13]*xf2[15],
+ xf1[ 2]*xf2[12]+xf1[ 6]*xf2[13]+xf1[10]*xf2[14]+xf1[14]*xf2[15],
+ xf1[ 3]*xf2[12]+xf1[ 7]*xf2[13]+xf1[11]*xf2[14]+xf1[15]*xf2[15]
+ );
+}
+
+
+// Component-wise equality and inequality (#include the usual caveats
+// about comparing floats for equality...)
+template <class T>
+static inline bool operator == (const XForm<T> &xf1, const XForm<T>
&xf2)
+{
+ for (int i = 0; i < 16; i++)
+ if (xf1[i] != xf2[i])
+ return false;
+ return true;
+}
+
+template <class T>
+static inline bool operator != (const XForm<T> &xf1, const XForm<T>
&xf2)
+{
+ for (int i = 0; i < 16; i++)
+ if (xf1[i] != xf2[i])
+ return true;
+ return false;
+}
+
+
+// Inverse
+template <class T>
+static inline XForm<T> inv(const XForm<T> &xf)
+{
+ T A[4][4] = { { xf[0], xf[4], xf[8], xf[12] },
+ { xf[1], xf[5], xf[9], xf[13] },
+ { xf[2], xf[6], xf[10], xf[14] },
+ { xf[3], xf[7], xf[11], xf[15] } };
+ int ind[4];
+ ludcmp<T,4>(A, ind);
+ T B[4][4] = { { 1, 0, 0, 0 },
+ { 0, 1, 0, 0 },
+ { 0, 0, 1, 0 },
+ { 0, 0, 0, 1 } };
+ for (int i = 0; i < 4; i++)
+ lubksb<T,4>(A, ind, B[i]);
+ return XForm<T>(B[0][0], B[0][1], B[0][2], B[0][3],
+ B[1][0], B[1][1], B[1][2], B[1][3],
+ B[2][0], B[2][1], B[2][2], B[2][3],
+ B[3][0], B[3][1], B[3][2], B[3][3]);
+}
+
+template <class T>
+static inline void invert(XForm<T> &xf)
+{
+ xf = inv(xf);
+}
+
+template <class T>
+static inline XForm<T> rot_only(const XForm<T> &xf)
+{
+ return XForm<T>(xf[0], xf[1], xf[2], 0,
+ xf[4], xf[5], xf[6], 0,
+ xf[8], xf[9], xf[10], 0,
+ 0, 0, 0, 1);
+}
+
+template <class T>
+static inline XForm<T> trans_only(const XForm<T> &xf)
+{
+ return XForm<T>(1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ xf[12], xf[13], xf[14], 1);
+}
+
+template <class T>
+static inline XForm<T> norm_xf(const XForm<T> &xf)
+{
+ XForm<T> M = inv(xf);
+ M[12] = M[13] = M[14] = T(0);
+ swap(M[1], M[4]);
+ swap(M[2], M[8]);
+ swap(M[6], M[9]);
+ return M;
+}
+
+template <class T>
+static inline void orthogonalize(XForm<T> &xf)
+{
+ if (xf[15] == T(0)) // Yuck. Doesn't make sense...
+ xf[15] = T(1);
+
+ T q0 = xf[0] + xf[5] + xf[10] + xf[15];
+ T q1 = xf[6] - xf[9];
+ T q2 = xf[8] - xf[2];
+ T q3 = xf[1] - xf[4];
+ T l = sqrt(q0*q0+q1*q1+q2*q2+q3*q3);
+
+ XForm<T> M = XForm<T>::rot(T(2)*acos(q0/l), q1, q2, q3);
+ M[12] = xf[12]/xf[15];
+ M[13] = xf[13]/xf[15];
+ M[14] = xf[14]/xf[15];
+
+ xf = M;
+}
+
+
+// Matrix-vector multiplication
+template <class S, class T>
+static inline const S operator * (const XForm<T> &xf, const S &v)
+{
+ T h = xf[3]*v[0] + xf[7]*v[1] + xf[11]*v[2] + xf[15];
+ h = T(1) / h;
+
+ return S(float(h*(xf[0]*v[0] + xf[4]*v[1] + xf[8]*v[2] + xf[12])),
+ float(h*(xf[1]*v[0] + xf[5]*v[1] + xf[9]*v[2] + xf[13])),
+ float(h*(xf[2]*v[0] + xf[6]*v[1] + xf[10]*v[2] + xf[14])));
+}
+
+// iostream operators
+template <class T>
+static inline std::ostream &operator << (std::ostream &os, const
XForm<T> &m)
+{
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < 4; j++) {
+ os << m[i+4*j];
+ if (j == 3)
+ os << std::endl;
+ else
+ os << " ";
+ }
+ }
+ return os;
+}
+template <class T>
+static inline std::istream &operator >> (std::istream &is, XForm<T>
&m)
+{
+ for (int i = 0; i < 4; i++)
+ for (int j = 0; j < 4; j++)
+ is >> m[i+4*j];
+ if (!is.good())
+ m = xform::identity();
+
+ return is;
+}
+
+// Generate a .xf filename from an input (scan) filename
+static inline std::string xfname(const std::string &filename)
+{
+ std::string x = filename;
+ std::string::size_type dot = x.rfind(".", x.length());
+ if (dot != std::string::npos)
+ x.erase(dot);
+ x += std::string(".xf");
+ return x;
+}
+
+#endif
Index: external/trimesh/include/GL/glut.h
--- external/trimesh/include/GL/glut.h (revision 0)
+++ external/trimesh/include/GL/glut.h (revision 0)
@@ -0,0 +1,29 @@
+#ifdef __APPLE__
+
+#include <GLUT/glut.h>
+
+#else
+
+#ifndef __GLUT_H__
+#define __GLUT_H__
+
+/*
+ * glut.h
+ *
+ * The freeglut library include file
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "freeglut_std.h"
+
+/*** END OF FILE ***/
+
+#endif /* __GLUT_H__ */
+
+#endif /* __APPLE__ */
Index: external/trimesh/include/GL/freeglut.h
--- external/trimesh/include/GL/freeglut.h (revision 0)
+++ external/trimesh/include/GL/freeglut.h (revision 0)
@@ -0,0 +1,22 @@
+#ifndef __FREEGLUT_H__
+#define __FREEGLUT_H__
+
+/*
+ * freeglut.h
+ *
+ * The freeglut library include file
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "freeglut_std.h"
+#include "freeglut_ext.h"
+
+/*** END OF FILE ***/
+
+#endif /* __FREEGLUT_H__ */
Index: external/trimesh/include/GL/freeglut_ext.h
--- external/trimesh/include/GL/freeglut_ext.h (revision 0)
+++ external/trimesh/include/GL/freeglut_ext.h (revision 0)
@@ -0,0 +1,124 @@
+#ifndef __FREEGLUT_EXT_H__
+#define __FREEGLUT_EXT_H__
+
+/*
+ * freeglut_ext.h
+ *
+ * The non-GLUT-compatible extensions to the freeglut library include file
+ *
+ * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
+ * Written by Pawel W. Olszta, <olszta(a)sourceforge.net>
+ * Creation date: Thu Dec 2 1999
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/*
+ * GLUT API Extension macro definitions -- behaviour when the user clicks on an
"x" to close a window
+ */
+#define GLUT_ACTION_EXIT 0
+#define GLUT_ACTION_GLUTMAINLOOP_RETURNS 1
+#define GLUT_ACTION_CONTINUE_EXECUTION 2
+
+/*
+ * Create a new rendering context when the user opens a new window?
+ */
+#define GLUT_CREATE_NEW_CONTEXT 0
+#define GLUT_USE_CURRENT_CONTEXT 1
+
+/*
+ * Direct/Indirect rendering context options (has meaning only in Unix/X11)
+ */
+#define GLUT_FORCE_INDIRECT_CONTEXT 0
+#define GLUT_ALLOW_DIRECT_CONTEXT 1
+#define GLUT_TRY_DIRECT_CONTEXT 2
+#define GLUT_FORCE_DIRECT_CONTEXT 3
+
+/*
+ * GLUT API Extension macro definitions -- the glutGet parameters
+ */
+#define GLUT_ACTION_ON_WINDOW_CLOSE 0x01F9
+
+#define GLUT_WINDOW_BORDER_WIDTH 0x01FA
+#define GLUT_WINDOW_HEADER_HEIGHT 0x01FB
+
+#define GLUT_VERSION 0x01FC
+
+#define GLUT_RENDERING_CONTEXT 0x01FD
+#define GLUT_DIRECT_RENDERING 0x01FE
+
+/*
+ * Process loop function, see freeglut_main.c
+ */
+FGAPI void FGAPIENTRY glutMainLoopEvent( void );
+FGAPI void FGAPIENTRY glutLeaveMainLoop( void );
+
+/*
+ * Window-specific callback functions, see freeglut_callbacks.c
+ */
+FGAPI void FGAPIENTRY glutMouseWheelFunc( void (* callback)( int, int, int, int ) );
+FGAPI void FGAPIENTRY glutCloseFunc( void (* callback)( void ) );
+FGAPI void FGAPIENTRY glutWMCloseFunc( void (* callback)( void ) );
+/* A. Donev: Also a destruction callback for menus */
+FGAPI void FGAPIENTRY glutMenuDestroyFunc( void (* callback)( void ) );
+
+/*
+ * State setting and retrieval functions, see freeglut_state.c
+ */
+FGAPI void FGAPIENTRY glutSetOption ( GLenum option_flag, int value ) ;
+/* A.Donev: User-data manipulation */
+FGAPI void* FGAPIENTRY glutGetWindowData( void );
+FGAPI void FGAPIENTRY glutSetWindowData(void* data);
+FGAPI void* FGAPIENTRY glutGetMenuData( void );
+FGAPI void FGAPIENTRY glutSetMenuData(void* data);
+
+/*
+ * Font stuff, see freeglut_font.c
+ */
+FGAPI int FGAPIENTRY glutBitmapHeight( void* font );
+FGAPI GLfloat FGAPIENTRY glutStrokeHeight( void* font );
+FGAPI void FGAPIENTRY glutBitmapString( void* font, const unsigned char *string );
+FGAPI void FGAPIENTRY glutStrokeString( void* font, const unsigned char *string );
+
+/*
+ * Geometry functions, see freeglut_geometry.c
+ */
+FGAPI void FGAPIENTRY glutWireRhombicDodecahedron( void );
+FGAPI void FGAPIENTRY glutSolidRhombicDodecahedron( void );
+FGAPI void FGAPIENTRY glutWireSierpinskiSponge ( int num_levels, GLdouble offset[3],
GLdouble scale ) ;
+FGAPI void FGAPIENTRY glutSolidSierpinskiSponge ( int num_levels, GLdouble offset[3],
GLdouble scale ) ;
+FGAPI void FGAPIENTRY glutWireCylinder( GLdouble radius, GLdouble height, GLint
slices, GLint stacks);
+FGAPI void FGAPIENTRY glutSolidCylinder( GLdouble radius, GLdouble height, GLint
slices, GLint stacks);
+
+/*
+ * Extension functions, see freeglut_ext.c
+ */
+FGAPI void * FGAPIENTRY glutGetProcAddress( const char *procName );
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+/*** END OF FILE ***/
+
+#endif /* __FREEGLUT_EXT_H__ */
Index: external/trimesh/include/GL/glui.h
--- external/trimesh/include/GL/glui.h (revision 0)
+++ external/trimesh/include/GL/glui.h (revision 0)
@@ -0,0 +1,1767 @@
+/****************************************************************************
+
+ GLUI User Interface Toolkit
+ ---------------------------
+
+ glui.h - Main header for GLUI User Interface Toolkit
+
+
+ --------------------------------------------------
+
+ Copyright (c) 1998 Paul Rademacher
+
+ This program is freely distributable without licensing fees and is
+ provided without guarantee or warrantee expressed or implied. This
+ program is -not- in the public domain.
+
+*****************************************************************************/
+
+
+#ifndef _GLUI_H_
+#define _GLUI_H_
+
+#include <GL/glut.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#define GLUI_VERSION 2.01f /********** Current version **********/
+
+//#ifdef WIN32
+//#pragma comment(lib, "glui32.lib") // Link against GLUI library
+//#endif
+
+class Arcball;
+
+/********** Do some basic defines *******/
+#ifndef false
+#define true 1
+#define false 0
+#endif
+
+#ifndef Byte
+#define Byte unsigned char
+#endif
+
+#ifndef _RGBC_
+class RGBc {
+public:
+ Byte r, g, b;
+
+ void set(Byte red, Byte green, Byte blue) {
+ r = red; g = green; b = blue;
+ }
+
+ RGBc( void ) {};
+ RGBc( Byte red, Byte green, Byte blue ) { set( red, green, blue ); }
+};
+#define _RGBC_
+#endif
+
+/********** List of GLUT callbacks ********/
+
+enum GLUI_Glut_CB_Types {
+ GLUI_GLUT_RESHAPE,
+ GLUI_GLUT_KEYBOARD,
+ GLUI_GLUT_DISPLAY,
+ GLUI_GLUT_MOUSE,
+ GLUI_GLUT_MOTION,
+ GLUI_GLUT_SPECIAL,
+ GLUI_GLUT_PASSIVE_MOTION,
+ GLUI_GLUT_ENTRY,
+ GLUI_GLUT_VISIBILITY
+};
+
+/********** List of control types **********/
+enum GLUI_Control_Types {
+ GLUI_CONTROL_CHECKBOX =1,
+ GLUI_CONTROL_BUTTON,
+ GLUI_CONTROL_RADIOBUTTON,
+ GLUI_CONTROL_RADIOGROUP,
+ GLUI_CONTROL_SLIDER,
+ GLUI_CONTROL_STATICTEXT,
+ GLUI_CONTROL_EDITTEXT,
+ GLUI_CONTROL_BITMAP,
+ GLUI_CONTROL_PANEL,
+ GLUI_CONTROL_SPINNER,
+ GLUI_CONTROL_SEPARATOR,
+ GLUI_CONTROL_COLUMN,
+ GLUI_CONTROL_LISTBOX,
+ GLUI_CONTROL_MOUSE_INTERACTION,
+ GLUI_CONTROL_ROTATION,
+ GLUI_CONTROL_TRANSLATION,
+ GLUI_CONTROL_ROLLOUT
+};
+
+
+/********* Constants for window placement **********/
+#define GLUI_XOFF 6
+#define GLUI_YOFF 6
+#define GLUI_ITEMSPACING 3
+#define GLUI_CHECKBOX_SIZE 13
+#define GLUI_RADIOBUTTON_SIZE 13
+#define GLUI_BUTTON_SIZE 20
+#define GLUI_STATICTEXT_SIZE 13
+#define GLUI_SEPARATOR_HEIGHT 8
+#define GLUI_DEFAULT_CONTROL_WIDTH 100
+#define GLUI_DEFAULT_CONTROL_HEIGHT 13
+#define GLUI_EDITTEXT_BOXINNERMARGINX 3
+#define GLUI_EDITTEXT_HEIGHT 20
+#define GLUI_EDITTEXT_WIDTH 130
+#define GLUI_EDITTEXT_MIN_INT_WIDTH 35
+#define GLUI_EDITTEXT_MIN_TEXT_WIDTH 50
+#define GLUI_PANEL_NAME_DROP 8
+#define GLUI_PANEL_EMBOSS_TOP 4
+/* #define GLUI_ROTATION_WIDTH 60*/
+/* #define GLUI_ROTATION_HEIGHT 78 */
+#define GLUI_ROTATION_WIDTH 50
+#define GLUI_ROTATION_HEIGHT (GLUI_ROTATION_WIDTH+18)
+#define GLUI_MOUSE_INTERACTION_WIDTH 50
+#define GLUI_MOUSE_INTERACTION_HEIGHT (GLUI_MOUSE_INTERACTION_WIDTH)+18
+
+#define GLUI_SLIDER_WIDTH 100
+#define GLUI_SLIDER_HEIGHT 80
+#define GLUI_SLIDER_LO 0
+#define GLUI_SLIDER_HI 100
+
+/** Different panel control types **/
+#define GLUI_PANEL_NONE 0
+#define GLUI_PANEL_EMBOSSED 1
+#define GLUI_PANEL_RAISED 2
+
+
+/** Max # of els in control's float_array **/
+#define GLUI_DEF_MAX_ARRAY 30
+
+/********* The control's 'active' behavior *********/
+#define GLUI_CONTROL_ACTIVE_MOUSEDOWN 1
+#define GLUI_CONTROL_ACTIVE_PERMANENT 2
+
+
+/********* Control alignment types **********/
+#define GLUI_ALIGN_CENTER 1
+#define GLUI_ALIGN_RIGHT 2
+#define GLUI_ALIGN_LEFT 3
+
+
+/********** Limit types - how to limit spinner values *********/
+#define GLUI_LIMIT_NONE 0
+#define GLUI_LIMIT_CLAMP 1
+#define GLUI_LIMIT_WRAP 2
+
+
+/********** Translation control types ********************/
+
+#define GLUI_TRANSLATION_XY 0
+#define GLUI_TRANSLATION_Z 1
+#define GLUI_TRANSLATION_X 2
+#define GLUI_TRANSLATION_Y 3
+
+#define GLUI_TRANSLATION_LOCK_NONE 0
+#define GLUI_TRANSLATION_LOCK_X 1
+#define GLUI_TRANSLATION_LOCK_Y 2
+
+/********** How was a control activated? *****************/
+#define GLUI_ACTIVATE_MOUSE 1
+#define GLUI_ACTIVATE_TAB 2
+
+
+/********** What type of live variable does a control have? **********/
+#define GLUI_LIVE_NONE 0
+#define GLUI_LIVE_INT 1
+#define GLUI_LIVE_FLOAT 2
+#define GLUI_LIVE_TEXT 3
+#define GLUI_LIVE_DOUBLE 4
+#define GLUI_LIVE_FLOAT_ARRAY 5
+
+
+/********** Translation codes **********/
+
+enum TranslationCodes {
+ GLUI_TRANSLATION_MOUSE_NONE=0,
+ GLUI_TRANSLATION_MOUSE_UP,
+ GLUI_TRANSLATION_MOUSE_DOWN,
+ GLUI_TRANSLATION_MOUSE_LEFT,
+ GLUI_TRANSLATION_MOUSE_RIGHT,
+ GLUI_TRANSLATION_MOUSE_UP_LEFT,
+ GLUI_TRANSLATION_MOUSE_UP_RIGHT,
+ GLUI_TRANSLATION_MOUSE_DOWN_LEFT,
+ GLUI_TRANSLATION_MOUSE_DOWN_RIGHT
+};
+
+/************ A string type for us to use **********/
+/* typedef char GLUI_String[300]; */
+class GLUI_String
+{
+public:
+ char string[300];
+
+ char &operator[]( int i ) {
+ return string[i];
+ }
+
+ operator char*() { return (char*) &string[0]; };
+ /* operator void*() { return (void*) &string[0]; }; */
+
+ GLUI_String( void ) {
+ string[0] = '\0';
+ }
+
+ GLUI_String( char *text ) {
+ strcpy( string, text );
+ }
+};
+
+
+/********* Pre-declare the various classes *********/
+class GLUI;
+class GLUI_Control;
+class GLUI_Listbox;
+class GLUI_Rotation;
+class GLUI_Translation;
+class GLUI_Mouse_Interaction;
+class GLUI_Checkbox;
+class GLUI_Slider;
+class GLUI_Button;
+class GLUI_StaticText;
+class GLUI_Bitmap;
+class GLUI_EditText;
+class GLUI_Node;
+class GLUI_Main;
+class GLUI_Panel;
+class GLUI_Spinner;
+class GLUI_RadioButton;
+class GLUI_RadioGroup;
+class GLUI_Separator;
+class GLUI_Column;
+class GLUI_Master;
+class GLUI_Glut_Window;
+class GLUI_Rollout;
+
+
+
+/*** Flags for GLUI class constructor ***/
+#define GLUI_SUBWINDOW ((long)(1<< 1))
+#define GLUI_SUBWINDOW_TOP ((long)(1<< 2))
+#define GLUI_SUBWINDOW_BOTTOM ((long)(1<< 3))
+#define GLUI_SUBWINDOW_LEFT ((long)(1<< 4))
+#define GLUI_SUBWINDOW_RIGHT ((long)(1<< 5))
+
+/*** Codes for different type of edittext boxes and spinners ***/
+#define GLUI_EDITTEXT_TEXT 1
+#define GLUI_EDITTEXT_INT 2
+#define GLUI_EDITTEXT_FLOAT 3
+#define GLUI_SPINNER_INT GLUI_EDITTEXT_INT
+#define GLUI_SPINNER_FLOAT GLUI_EDITTEXT_FLOAT
+
+#define GLUI_SLIDER_INT 1
+#define GLUI_SLIDER_FLOAT 2
+
+
+/*** Definition of callbacks ***/
+typedef void (*GLUI_Update_CB) (int id);
+typedef void (*Int1_CB) (int);
+typedef void (*Int2_CB) (int, int);
+typedef void (*Int3_CB) (int, int, int);
+typedef void (*Int4_CB) (int, int, int, int);
+
+
+
+/************************************************************/
+/* */
+/* Base class, for hierarchical relationships */
+/* */
+/************************************************************/
+
+class GLUI_Node {
+protected:
+ GLUI_Node *parent_node;
+ GLUI_Node *child_head;
+ GLUI_Node *child_tail;
+ GLUI_Node *next_sibling;
+ GLUI_Node *prev_sibling;
+
+public:
+ GLUI_Node *first_sibling( void );
+ GLUI_Node *last_sibling( void );
+ GLUI_Node *prev( void );
+ GLUI_Node *next( void );
+ GLUI_Node *first_child( void ) { return child_head; };
+ GLUI_Node *last_child( void ) { return child_tail; };
+ GLUI_Node *parent(void) { return parent_node; };
+
+ void link_this_to_parent_last( GLUI_Node *parent );
+ void link_this_to_parent_first( GLUI_Node *parent );
+ void link_this_to_sibling_next( GLUI_Node *sibling );
+ void link_this_to_sibling_prev( GLUI_Node *sibling );
+ void unlink( void );
+
+ void dump( FILE *out, char *name ) {
+ fprintf( out, "GLUI_node: %s\n", name );
+ fprintf( out, " parent: %p child_head: %p child_tail: %p\n",
+ parent_node, child_head, child_tail );
+ fprintf( out, " next: %p prev: %p\n", next_sibling, prev_sibling
);
+ }
+
+ GLUI_Node( void ) {
+ parent_node= child_head = child_tail = next_sibling = prev_sibling = NULL;
+ };
+
+ virtual ~GLUI_Node() {}
+ friend class GLUI_Rollout;
+ friend class GLUI_Main;
+};
+
+
+
+/************************************************************/
+/* */
+/* Standard Bitmap stuff */
+/* */
+/************************************************************/
+
+enum GLUI_StdBitmaps_Codes {
+ GLUI_STDBITMAP_CHECKBOX_OFF=0,
+ GLUI_STDBITMAP_CHECKBOX_ON,
+ GLUI_STDBITMAP_RADIOBUTTON_OFF,
+ GLUI_STDBITMAP_RADIOBUTTON_ON,
+ GLUI_STDBITMAP_UP_ARROW,
+ GLUI_STDBITMAP_DOWN_ARROW,
+ GLUI_STDBITMAP_LEFT_ARROW,
+ GLUI_STDBITMAP_RIGHT_ARROW,
+ GLUI_STDBITMAP_SPINNER_UP_OFF,
+ GLUI_STDBITMAP_SPINNER_UP_ON,
+ GLUI_STDBITMAP_SPINNER_DOWN_OFF,
+ GLUI_STDBITMAP_SPINNER_DOWN_ON,
+
+ GLUI_STDBITMAP_CHECKBOX_OFF_DIS, /*** Disactivated control bitmaps ***/
+ GLUI_STDBITMAP_CHECKBOX_ON_DIS,
+ GLUI_STDBITMAP_RADIOBUTTON_OFF_DIS,
+ GLUI_STDBITMAP_RADIOBUTTON_ON_DIS,
+ GLUI_STDBITMAP_SPINNER_UP_DIS,
+ GLUI_STDBITMAP_SPINNER_DOWN_DIS,
+ GLUI_STDBITMAP_LISTBOX_UP,
+ GLUI_STDBITMAP_LISTBOX_DOWN,
+ GLUI_STDBITMAP_LISTBOX_UP_DIS,
+ /***
+ GLUI_STDBITMAP_SLIDER_TAB,
+ ***/
+ GLUI_STDBITMAP_NUM_ITEMS
+};
+
+
+/************ Image Bitmap arrays **********/
+extern int glui_img_checkbox_0[];
+extern int glui_img_checkbox_1[];
+extern int glui_img_radiobutton_0[];
+extern int glui_img_radiobutton_1[];
+extern int glui_img_uparrow[];
+extern int glui_img_downarrow[];
+extern int glui_img_leftarrow[];
+extern int glui_img_rightarrow[];
+extern int glui_img_spinup_0[];
+extern int glui_img_spinup_1[];
+extern int glui_img_spindown_0[];
+extern int glui_img_spindown_1[];
+extern int glui_img_checkbox_0_dis[];
+extern int glui_img_checkbox_1_dis[];
+extern int glui_img_radiobutton_0_dis[];
+extern int glui_img_radiobutton_1_dis[];
+extern int glui_img_spinup_dis[];
+extern int glui_img_spindown_dis[];
+extern int glui_img_listbox_up[];
+extern int glui_img_listbox_down[];
+extern int glui_img_listbox_up_dis[];
+
+extern int *bitmap_arrays[];
+
+
+
+/************************************************************/
+/* */
+/* Class GLUI_Bitmap */
+/* */
+/************************************************************/
+class GLUI_Bitmap
+{
+public:
+ unsigned char *pixels;
+ int w, h;
+
+ void load_from_array( int *array );
+
+ GLUI_Bitmap( void ) {
+ pixels = NULL;
+ w = 0;
+ h = 0;
+ }
+};
+
+
+
+
+/************************************************************/
+/* */
+/* Class GLUI_StdBitmap */
+/* */
+/************************************************************/
+class GLUI_StdBitmaps
+{
+public:
+ GLUI_Bitmap bitmaps[ GLUI_STDBITMAP_NUM_ITEMS ];
+
+ void draw( int bitmap_num, int x, int y );
+
+ GLUI_StdBitmaps( void ) {
+ int i;
+
+ for( i=0; i<GLUI_STDBITMAP_NUM_ITEMS; i++ ) {
+ bitmaps[i].load_from_array( bitmap_arrays[i] );
+ }
+ }
+};
+
+
+
+
+/************************************************************/
+/* */
+/* Master GLUI Class */
+/* */
+/************************************************************/
+class GLUI_Master_Object {
+private:
+ GLUI_Node glut_windows;
+ void (*glut_idle_CB)(void);
+
+ void add_cb_to_glut_window(int window,int cb_type,void *cb);
+
+public:
+ GLUI_Node gluis;
+ GLUI_Control *active_control, *curr_left_button_glut_menu;
+ GLUI *active_control_glui;
+ int glui_id_counter;
+
+ GLUI_Glut_Window *find_glut_window( int window_id );
+
+ void set_glutIdleFunc(void (*f)(void));
+
+ /**************
+ void (*glut_keyboard_CB)(unsigned char, int, int);
+ void (*glut_reshape_CB)(int, int);
+ void (*glut_special_CB)(int, int, int);
+ void (*glut_mouse_CB)(int,int,int,int);
+
+ void (*glut_passive_motion_CB)(int,int);
+ void (*glut_visibility_CB)(int);
+ void (*glut_motion_CB)(int,int);
+ void (*glut_display_CB)(void);
+ void (*glut_entry_CB)(int);
+ **********/
+
+ void set_left_button_glut_menu_control( GLUI_Control *control );
+
+
+ /********** GLUT callthroughs **********/
+ /* These are the glut callbacks that we do not handle */
+
+ void set_glutReshapeFunc(void (*f)(int width, int height));
+ void set_glutKeyboardFunc(void (*f)(unsigned char key, int x, int y));
+ void set_glutSpecialFunc(void (*f)(int key, int x, int y));
+ void set_glutMouseFunc(void (*f)(int, int, int, int ));
+
+ void set_glutDisplayFunc(void (*f)(void)) {glutDisplayFunc(f);};
+ void set_glutTimerFunc(unsigned int millis, void (*f)(int value), int value)
+ { ::glutTimerFunc(millis,f,value);};
+ void set_glutOverlayDisplayFunc(void(*f)(void)){glutOverlayDisplayFunc(f);};
+ void set_glutSpaceballMotionFunc(Int3_CB f) {glutSpaceballMotionFunc(f);};
+ void set_glutSpaceballRotateFunc(Int3_CB f) {glutSpaceballRotateFunc(f);};
+ void set_glutSpaceballButtonFunc(Int2_CB f) {glutSpaceballButtonFunc(f);};
+ void set_glutTabletMotionFunc(Int2_CB f) {glutTabletMotionFunc(f);};
+ void set_glutTabletButtonFunc(Int4_CB f) {glutTabletButtonFunc(f);};
+ /* void set_glutWindowStatusFunc(Int1_CB f) {glutWindowStatusFunc(f);}; */
+ void set_glutMenuStatusFunc(Int3_CB f) {glutMenuStatusFunc(f);};
+ void set_glutMenuStateFunc(Int1_CB f) {glutMenuStateFunc(f);};
+ void set_glutButtonBoxFunc(Int2_CB f) {glutButtonBoxFunc(f);};
+ void set_glutDialsFunc(Int2_CB f) {glutDialsFunc(f);};
+
+
+ GLUI *create_glui( char *name, long flags=0, int x=-1, int y=-1 );
+ GLUI *create_glui_subwindow( int parent_window, long flags=0 );
+ GLUI *find_glui_by_window_id( int window_id );
+ void get_viewport_area( int *x, int *y, int *w, int *h );
+ void auto_set_viewport( void );
+ void close_all( void );
+ void sync_live_all( void );
+
+ void reshape( void );
+
+ float get_version( void ) { return GLUI_VERSION; };
+
+ friend void glui_idle_func(void);
+
+ GLUI_Master_Object( void ) {
+ glut_idle_CB = NULL;
+ glui_id_counter = 1;
+ }
+};
+
+extern GLUI_Master_Object GLUI_Master;
+
+
+
+/************************************************************/
+/* */
+/* Class for managing a GLUT window */
+/* */
+/************************************************************/
+
+class GLUI_Glut_Window : public GLUI_Node {
+public:
+ int glut_window_id;
+
+ /*********** Pointers to GLUT callthrough functions *****/
+ void (*glut_keyboard_CB)(unsigned char, int, int);
+ void (*glut_special_CB)(int, int, int);
+ void (*glut_reshape_CB)(int, int);
+ void (*glut_passive_motion_CB)(int,int);
+ void (*glut_mouse_CB)(int,int,int,int);
+ void (*glut_visibility_CB)(int);
+ void (*glut_motion_CB)(int,int);
+ void (*glut_display_CB)(void);
+ void (*glut_entry_CB)(int);
+
+ GLUI_Glut_Window( void ) {
+ glut_display_CB = NULL;
+ glut_reshape_CB = NULL;
+ glut_keyboard_CB = NULL;
+ glut_special_CB = NULL;
+ glut_mouse_CB = NULL;
+ glut_motion_CB = NULL;
+ glut_passive_motion_CB = NULL;
+ glut_entry_CB = NULL;
+ glut_visibility_CB = NULL;
+ glut_window_id = 0;
+ };
+};
+
+
+
+/************************************************************/
+/* */
+/* Main GLUI class (not user-level) */
+/* */
+/************************************************************/
+
+class GLUI_Main : public GLUI_Node {
+protected:
+ /*** Variables ***/
+ int main_gfx_window_id;
+ int mouse_button_down;
+ int glut_window_id;
+ int top_level_glut_window_id;
+ GLUI_Control *active_control;
+ GLUI_Control *mouse_over_control;
+ GLUI_Panel *main_panel;
+ int curr_cursor;
+ int w, h;
+ long flags;
+ int closing;
+ int parent_window;
+ int glui_id;
+
+ /********** Friend classes *************/
+
+ friend class GLUI_Control;
+ friend class GLUI_Rotation;
+ friend class GLUI_Translation;
+ friend class GLUI_Slider;
+ friend class GLUI;
+ friend class GLUI_Master_Object;
+
+
+ /********** Misc functions *************/
+
+ GLUI_Control *find_control( int x, int y );
+ GLUI_Control *find_next_control( GLUI_Control *control );
+ GLUI_Control *find_next_control_rec( GLUI_Control *control );
+ GLUI_Control *find_next_control_( GLUI_Control *control );
+ GLUI_Control *find_prev_control( GLUI_Control *control );
+ void create_standalone_window( char *name, int x=-1, int y=-1 );
+ void create_subwindow( int parent,int window_alignment );
+ void setup_default_glut_callbacks( void );
+
+ void mouse(int button, int state, int x, int y);
+ void keyboard(unsigned char key, int x, int y);
+ void special(int key, int x, int y);
+ void passive_motion(int x, int y);
+ void reshape( int w, int h );
+ void visibility(int state);
+ void motion(int x, int y);
+ void entry(int state);
+ void display( void );
+ void idle(void);
+
+ void (*glut_mouse_CB)(int, int, int, int);
+ void (*glut_keyboard_CB)(unsigned char, int, int);
+ void (*glut_special_CB)(int, int, int);
+ void (*glut_reshape_CB)(int, int);
+
+
+ /*********** Friend functions and classes **********/
+
+ friend void glui_mouse_func(int button, int state, int x, int y);
+ friend void glui_keyboard_func(unsigned char key, int x, int y);
+ friend void glui_special_func(int key, int x, int y);
+ friend void glui_passive_motion_func(int x, int y);
+ friend void glui_reshape_func( int w, int h );
+ friend void glui_visibility_func(int state);
+ friend void glui_motion_func(int x, int y);
+ friend void glui_entry_func(int state);
+ friend void glui_display_func( void );
+ friend void glui_idle_func(void);
+
+ friend void glui_parent_window_reshape_func( int w, int h );
+ friend void glui_parent_window_keyboard_func( unsigned char, int, int );
+ friend void glui_parent_window_special_func( int, int, int );
+ friend void glui_parent_window_mouse_func( int, int, int, int );
+
+
+ /*********** Controls ************/
+ GLUI_Control *controls;
+ int num_controls;
+
+ int add_control( GLUI_Node *parent, GLUI_Control *control );
+
+
+ /********** Constructors and Destructors ***********/
+
+ GLUI_Main( void );
+
+public:
+ GLUI_StdBitmaps std_bitmaps;
+ GLUI_String window_name;
+ RGBc bkgd_color;
+ float bkgd_color_f[3];
+
+ void *font;
+ int curr_modifiers;
+
+ void adjust_glut_xy( int &x, int &y ) { y = h-y; };
+ void activate_control( GLUI_Control *control, int how );
+ void align_controls( GLUI_Control *control );
+ void restore_draw_buffer( int buffer_state );
+ void disactivate_current_control( void );
+ void draw_raised_box( int x, int y, int w, int h );
+ void draw_lowered_box( int x, int y, int w, int h );
+ int set_front_draw_buffer( void );
+ void post_update_main_gfx( void );
+ void pack_controls( void );
+ void close_internal( void );
+ void check_subwindow_position( void );
+ void set_ortho_projection( void );
+ void set_viewport( void );
+ void refresh( void );
+};
+
+
+
+
+
+
+/************************************************************/
+/* */
+/* GLUI_Control: base class for all controls */
+/* */
+/************************************************************/
+
+class GLUI_Control : public GLUI_Node {
+public:
+
+ int w, h; /* dimensions of control */
+ int x_abs, y_abs;
+ int x_off, y_off_top, y_off_bot; /* INNER margins, by which
+ child controls are indented */
+ int contain_x, contain_y;
+ int contain_w, contain_h;
+ /* if this is a container control (e.g.,
+ radiogroup or panel) this indicated dimensions
+ of inner area in which controls reside */
+ int active, active_type, can_activate;
+ int spacebar_mouse_click;
+ long user_id, type;
+ int is_container; /* Is this a container class (e.g., panel) */
+ int alignment;
+ GLUI_Update_CB callback;
+ void *ptr_val; /* A pointer value */
+ float float_val; /* A float value */
+ int enabled; /* Is this control grayed out? */
+ int int_val; /* An integer value */
+ float float_array_val[GLUI_DEF_MAX_ARRAY];
+ int state;
+ GLUI_String name; /* The name of this control */
+ GLUI_String text;
+ GLUI *glui;
+ void *font;
+ int live_type, live_inited;
+ int last_live_int; /* last value that live var known to have */
+ float last_live_float;
+ GLUI_String last_live_text;
+ float last_live_float_array[GLUI_DEF_MAX_ARRAY];
+ int float_array_size;
+
+ int collapsible, is_open;
+ GLUI_Node collapsed_node;
+ int hidden; /* Collapsed controls (and children) are hidden */
+
+ /*** Get/Set values ***/
+
+ virtual void set_name( char *string );
+ virtual void set_int_val( int new_int ) { int_val = new_int;
output_live(true); };
+ virtual void set_float_val( float new_float ) { float_val = new_float;
output_live(true); };
+ virtual void set_ptr_val( void *new_ptr ) { ptr_val = new_ptr;
output_live(true); };
+ virtual void set_float_array_val( float *array_ptr );
+
+ virtual float get_float_val( void ) { return float_val; };
+ virtual int get_int_val( void ) { return int_val; };
+ virtual void get_float_array_val( float *array_ptr );
+
+ virtual int mouse_down_handler( int local_x, int local_y )
+ { return false; };
+ virtual int mouse_up_handler( int local_x, int local_y, int inside )
+ { return false; };
+ virtual int mouse_held_down_handler( int local_x, int local_y, int inside)
+ { return false; };
+ virtual int key_handler( unsigned char key, int modifiers )
+ { return false; };
+ virtual int special_handler( int key,int modifiers )
+ { return false; };
+
+ virtual void update_size( void ) { };
+ virtual void idle( void ) { };
+ virtual int mouse_over( int state, int x, int y ) { return false; };
+
+ virtual void enable( void );
+ virtual void disable( void );
+ virtual void activate( int how ) { active = true; };
+ virtual void disactivate( void ) { active = false; };
+
+ void hide_internal( int recurse );
+ void unhide_internal( int recurse );
+
+ int can_draw( void ) { return (glui != NULL && hidden == false); };
+
+ virtual void align( void );
+ void pack( int x, int y ); /* Recalculate positions and offsets */
+ void pack_old( int x, int y );
+ void draw_recursive( int x, int y );
+ int set_to_glut_window( void );
+ void restore_window( int orig );
+ void translate_and_draw_front( void );
+ void translate_to_origin( void )
+ {glTranslatef((float)x_abs+.5,(float)y_abs+.5,0.0);};
+ virtual void draw( int x, int y )=0;
+ void set_font( void *new_font );
+ void *get_font( void );
+ int string_width( char *text );
+ int char_width( char c );
+
+ void draw_name( int x, int y );
+ void draw_box_inwards_outline( int x_min, int x_max,
+ int y_min, int y_max );
+ void draw_box( int x_min, int x_max, int y_min, int y_max,
+ float r, float g, float b );
+ void draw_bkgd_box( int x_min, int x_max, int y_min, int y_max );
+ void draw_emboss_box( int x_min, int x_max,int y_min,int y_max);
+ void draw_string( char *text );
+ void draw_char( char c );
+ void draw_active_box( int x_min, int x_max, int y_min, int y_max );
+ void set_to_bkgd_color( void );
+
+ void set_w( int new_w );
+ void set_h( int new_w );
+ void set_alignment( int new_align );
+ void sync_live( int recurse, int draw ); /* Reads live variable */
+ void init_live( void );
+ void output_live( int update_main_gfx ); /** Writes live variable **/
+ virtual void set_text( char *t ) {};
+ void execute_callback( void );
+ void get_this_column_dims( int *col_x, int *col_y,
+ int *col_w, int *col_h,
+ int *col_x_off, int *col_y_off );
+ virtual int needs_idle( void );
+
+ GLUI_Control(void) {
+ x_off = GLUI_XOFF;
+ y_off_top = GLUI_YOFF;
+ y_off_bot = GLUI_YOFF;
+ x_abs = GLUI_XOFF;
+ y_abs = GLUI_YOFF;
+ state = 0;
+ active = false;
+ enabled = true;
+ int_val = 0;
+ last_live_int = 0;
+ float_array_size = 0;
+ sprintf( (char*)name, "Control: %p", this );
+ float_val = 0.0;
+ last_live_float = 0.0;
+ ptr_val = NULL;
+ glui = NULL;
+ w = GLUI_DEFAULT_CONTROL_WIDTH;
+ h = GLUI_DEFAULT_CONTROL_HEIGHT;
+ font = NULL;
+ active_type = GLUI_CONTROL_ACTIVE_MOUSEDOWN;
+ alignment = GLUI_ALIGN_LEFT;
+ is_container = false;
+ can_activate = true; /* By default, you can activate a control */
+ spacebar_mouse_click = true; /* Does spacebar simulate a mouse click? */
+ live_type = GLUI_LIVE_NONE;
+ strcpy( (char*)text, "" );
+ strcpy( (char*)last_live_text, "" );
+ live_inited = false;
+ collapsible = false;
+ is_open = true;
+ hidden = false;
+
+ int i;
+ for( i=0; i<GLUI_DEF_MAX_ARRAY; i++ )
+ float_array_val[i] = last_live_float_array[i] = 0.0;
+ };
+
+ virtual ~GLUI_Control();
+};
+
+
+
+
+/************************************************************/
+/* */
+/* Button class (container) */
+/* */
+/************************************************************/
+
+class GLUI_Button : public GLUI_Control
+{
+public:
+ int currently_inside;
+
+ int mouse_down_handler( int local_x, int local_y );
+ int mouse_up_handler( int local_x, int local_y, int same );
+ int mouse_held_down_handler( int local_x, int local_y, int inside );
+ int key_handler( unsigned char key,int modifiers );
+
+ void draw( int x, int y );
+ void draw_pressed( void );
+ void draw_unpressed( void );
+ void draw_text( int sunken );
+
+ void update_size( void );
+
+ GLUI_Button( void ) {
+ sprintf( name, "Button: %p", this );
+ type = GLUI_CONTROL_BUTTON;
+ h = GLUI_BUTTON_SIZE;
+ w = 100;
+ alignment = GLUI_ALIGN_CENTER;
+ can_activate = true;
+ };
+
+ virtual ~GLUI_Button() {};
+};
+
+
+
+/************************************************************/
+/* */
+/* Checkbox class (container) */
+/* */
+/************************************************************/
+
+class GLUI_Checkbox : public GLUI_Control
+{
+public:
+ int orig_value, currently_inside;
+ int text_x_offset;
+
+ int mouse_down_handler( int local_x, int local_y );
+ int mouse_up_handler( int local_x, int local_y, int inside );
+ int mouse_held_down_handler( int local_x, int local_y, int inside );
+ int key_handler( unsigned char key,int modifiers );
+
+ void update_size( void );
+
+ void draw( int x, int y );
+
+ void draw_active_area( void );
+ void draw_checked( void );
+ void draw_unchecked( void );
+ void draw_X( void );
+ void draw_empty_box( void );
+ void set_int_val( int new_val );
+
+ GLUI_Checkbox( void ) {
+ sprintf( name, "Checkbox: %p", this );
+ type = GLUI_CONTROL_CHECKBOX;
+ w = 100;
+ h = GLUI_CHECKBOX_SIZE;
+ orig_value = -1;
+ text_x_offset = 18;
+ can_activate = true;
+ live_type = GLUI_LIVE_INT; /* This control has an 'int' live var */
+ };
+
+ virtual ~GLUI_Checkbox() {};
+};
+
+
+/************************************************************/
+/* */
+/* Column class */
+/* */
+/************************************************************/
+
+class GLUI_Column : public GLUI_Control
+{
+public:
+ void draw( int x, int y );
+
+ GLUI_Column( void ) {
+ type = GLUI_CONTROL_COLUMN;
+ w = 0;
+ h = 0;
+ int_val = 0;
+ can_activate = false;
+ };
+
+ virtual ~GLUI_Column() {};
+};
+
+
+
+/************************************************************/
+/* */
+/* Panel class (container) */
+/* */
+/************************************************************/
+
+class GLUI_Panel : public GLUI_Control
+{
+public:
+ void draw( int x, int y );
+ void set_name( char *text );
+ void set_type( int new_type );
+
+ void update_size( void );
+
+ GLUI_Panel( void ) {
+ type = GLUI_CONTROL_PANEL;
+ w = 300;
+ h = GLUI_DEFAULT_CONTROL_HEIGHT + 7;
+ int_val = GLUI_PANEL_EMBOSSED;
+ alignment = GLUI_ALIGN_CENTER;
+ is_container = true;
+ can_activate = false;
+ strcpy( name, "" );
+ };
+
+ virtual ~GLUI_Panel() {};
+};
+
+
+/************************************************************/
+/* */
+/* Panel class (container) */
+/* */
+/************************************************************/
+
+class GLUI_Rollout : public GLUI_Panel
+{
+ /* private: */
+ /* GLUI_Panel panel; */
+public:
+ int currently_inside, initially_inside;
+ GLUI_Button button;
+
+ void draw( int x, int y );
+ void draw_pressed( void );
+ void draw_unpressed( void );
+ int mouse_down_handler( int local_x, int local_y );
+ int mouse_up_handler( int local_x, int local_y, int inside );
+ int mouse_held_down_handler( int local_x, int local_y, int inside );
+
+ void open( void );
+ void close( void );
+
+ /* void set_name( char *text ) { panel.set_name( text ); }; */
+ void update_size( void );
+
+ GLUI_Rollout( void ) {
+ currently_inside = false;
+ initially_inside = false;
+ can_activate = true;
+ is_container = true;
+ type = GLUI_CONTROL_ROLLOUT;
+ h = GLUI_DEFAULT_CONTROL_HEIGHT + 7;
+ w = GLUI_DEFAULT_CONTROL_WIDTH;
+ y_off_top = 21;
+ collapsible = true;
+ strcpy( name, "" );
+ };
+
+ virtual ~GLUI_Rollout() {};
+};
+
+
+/************************************************************/
+/* */
+/* User-Level GLUI class */
+/* */
+/************************************************************/
+
+class GLUI : public GLUI_Main {
+private:
+public:
+ void add_column( int draw_bar = true );
+ void add_column_to_panel( GLUI_Panel *panel, int draw_bar = true );
+
+ void add_separator( void );
+ void add_separator_to_panel( GLUI_Panel *panel );
+
+ GLUI_RadioGroup
+ *add_radiogroup( int *live_var=NULL,
+ int user_id=-1,GLUI_Update_CB callback=NULL);
+
+ GLUI_RadioGroup
+ *add_radiogroup_to_panel( GLUI_Panel *panel,
+ int *live_var=NULL,
+ int user_id=-1, GLUI_Update_CB callback=NULL );
+ GLUI_RadioButton
+ *add_radiobutton_to_group( GLUI_RadioGroup *group,
+ char *name );
+
+ GLUI_Listbox *add_listbox( char *name, int *live_var=NULL,
+ int id=-1, GLUI_Update_CB callback=NULL );
+ GLUI_Listbox *add_listbox_to_panel( GLUI_Panel *panel,
+ char *name, int *live_var=NULL,
+ int id=-1, GLUI_Update_CB callback=NULL);
+
+ GLUI_Rotation *add_rotation( char *name, float *live_var=NULL,
+ int id=-1, GLUI_Update_CB callback=NULL );
+ GLUI_Rotation *add_rotation_to_panel( GLUI_Panel *panel,
+ char *name, float *live_var=NULL,
+ int id=-1, GLUI_Update_CB callback=NULL);
+ GLUI_Slider *add_slider( char *name,
+ int data_type=GLUI_SLIDER_INT,
+ float limit_lo = GLUI_SLIDER_LO, float limit_hi = GLUI_SLIDER_HI,
+ void *data=NULL,
+ int id=-1, GLUI_Update_CB callback=NULL );
+ GLUI_Slider *add_slider_to_panel( GLUI_Panel *panel, char *name,
+ int data_type=GLUI_SLIDER_INT,
+ float limit_lo = GLUI_SLIDER_LO, float limit_hi = GLUI_SLIDER_HI,
+ void *data=NULL,
+ int id=-1, GLUI_Update_CB callback=NULL);
+
+
+ GLUI_Translation *add_translation( char *name,
+ int trans_type, float *live_var=NULL,
+ int id=-1, GLUI_Update_CB callback=NULL );
+ GLUI_Translation *add_translation_to_panel(
+ GLUI_Panel *panel, char *name,
+ int trans_type, float *live_var=NULL,
+ int id=-1, GLUI_Update_CB callback=NULL);
+
+ GLUI_Checkbox *add_checkbox( char *name,
+ int *live_var=NULL,
+ int id=-1, GLUI_Update_CB callback=NULL);
+ GLUI_Checkbox *add_checkbox_to_panel( GLUI_Panel *panel, char *name,
+ int *live_var=NULL, int id=-1,
+ GLUI_Update_CB callback=NULL);
+
+ GLUI_Button *add_button( char *name, int id=-1,
+ GLUI_Update_CB callback=NULL);
+ GLUI_Button *add_button_to_panel( GLUI_Panel *panel, char *name,
+ int id=-1, GLUI_Update_CB callback=NULL );
+
+ GLUI_StaticText *add_statictext( char *name );
+ GLUI_StaticText *add_statictext_to_panel( GLUI_Panel *panel, char *name );
+
+ GLUI_EditText *add_edittext( char *name,
+ int data_type=GLUI_EDITTEXT_TEXT,
+ void *live_var=NULL,
+ int id=-1, GLUI_Update_CB callback=NULL );
+ GLUI_EditText *add_edittext_to_panel( GLUI_Panel *panel,
+ char *name,
+ int data_type=GLUI_EDITTEXT_TEXT,
+ void *live_var=NULL, int id=-1,
+ GLUI_Update_CB callback=NULL );
+
+ GLUI_Spinner *add_spinner( char *name,
+ int data_type=GLUI_SPINNER_INT,
+ void *live_var=NULL,
+ int id=-1, GLUI_Update_CB callback=NULL );
+ GLUI_Spinner *add_spinner_to_panel( GLUI_Panel *panel,
+ char *name,
+ int data_type=GLUI_SPINNER_INT,
+ void *live_var=NULL,
+ int id=-1,
+ GLUI_Update_CB callback=NULL );
+
+ GLUI_Panel *add_panel( char *name, int type=GLUI_PANEL_EMBOSSED );
+ GLUI_Panel *add_panel_to_panel( GLUI_Panel *panel, char *name,
+ int type=GLUI_PANEL_EMBOSSED );
+
+ GLUI_Rollout *add_rollout( char *name, int open=true );
+ GLUI_Rollout *add_rollout_to_panel( GLUI_Panel *panel, char *name, int open=true );
+
+ void set_main_gfx_window( int window_id );
+ int get_glut_window_id( void ) { return glut_window_id; };
+
+ void enable( void ) { main_panel->enable(); };
+ void disable( void );
+
+ void sync_live( void );
+
+ void close( void );
+
+ void show( void );
+ void hide( void );
+
+ /***** GLUT callback setup functions *****/
+ /*
+ void set_glutDisplayFunc(void (*f)(void));
+ void set_glutReshapeFunc(void (*f)(int width, int height));
+ void set_glutKeyboardFunc(void (*f)(unsigned char key, int x, int y));
+ void set_glutSpecialFunc(void (*f)(int key, int x, int y));
+ void set_glutMouseFunc(void (*f)(int button, int state, int x, int y));
+ void set_glutMotionFunc(void (*f)(int x, int y));
+ void set_glutPassiveMotionFunc(void (*f)(int x, int y));
+ void set_glutEntryFunc(void (*f)(int state));
+ void set_glutVisibilityFunc(void (*f)(int state));
+ void set_glutInit( int *argcp, char **argv );
+ void set_glutInitWindowSize(int width, int height);
+ void set_glutInitWindowPosition(int x, int y);
+ void set_glutInitDisplayMode(unsigned int mode);
+ int set_glutCreateWindow(char *name);
+ */
+
+ /***** Constructors and desctructors *****/
+
+ int init( char *name, long flags, int x, int y, int parent_window );
+};
+
+
+
+
+/************************************************************/
+/* */
+/* EditText class */
+/* */
+/************************************************************/
+
+class GLUI_EditText : public GLUI_Control
+{
+public:
+ int has_limits;
+ int data_type;
+ GLUI_String orig_text;
+ int insertion_pt;
+ int title_x_offset;
+ int text_x_offset;
+ int substring_start; /*substring that gets displayed in box*/
+ int substring_end;
+ int sel_start, sel_end; /* current selection */
+ int num_periods;
+ int last_insertion_pt;
+ float float_low, float_high;
+ int int_low, int_high;
+ GLUI_Spinner *spinner;
+ int debug;
+ int draw_text_only;
+
+
+ int mouse_down_handler( int local_x, int local_y );
+ int mouse_up_handler( int local_x, int local_y, int same );
+ int mouse_held_down_handler( int local_x, int local_y, int inside );
+ int key_handler( unsigned char key,int modifiers );
+ int special_handler( int key,int modifiers );
+
+ void activate( int how );
+ void disactivate( void );
+
+ void draw( int x, int y );
+
+ int mouse_over( int state, int x, int y );
+
+ int find_word_break( int start, int direction );
+ int substring_width( int start, int end );
+ void clear_substring( int start, int end );
+ int find_insertion_pt( int x, int y );
+ int update_substring_bounds( void );
+ void update_and_draw_text( void );
+ void draw_text( int x, int y );
+ void draw_insertion_pt( void );
+ void set_numeric_text( void );
+ void update_x_offsets( void );
+ void update_size( void );
+
+ void set_float_limits( float low,float high,int limit_type=GLUI_LIMIT_CLAMP);
+ void set_int_limits( int low, int high, int limit_type=GLUI_LIMIT_CLAMP );
+ void set_float_val( float new_val );
+ void set_int_val( int new_val );
+ void set_text( char *text );
+ char *get_text( void ) { return text; };
+
+ void dump( FILE *out, char *text );
+
+ GLUI_EditText( void ) {
+ type = GLUI_CONTROL_EDITTEXT;
+ h = GLUI_EDITTEXT_HEIGHT;
+ w = GLUI_EDITTEXT_WIDTH;
+ title_x_offset = 0;
+ text_x_offset = 55;
+ insertion_pt = -1;
+ last_insertion_pt = -1;
+ name[0] = '\0';
+ substring_start = 0;
+ data_type = GLUI_EDITTEXT_TEXT;
+ substring_end = 2;
+ num_periods = 0;
+ has_limits = GLUI_LIMIT_NONE;
+ sel_start = 0;
+ sel_end = 0;
+ active_type = GLUI_CONTROL_ACTIVE_PERMANENT;
+ can_activate = true;
+ spacebar_mouse_click = false;
+ spinner = NULL;
+ debug = false;
+ draw_text_only = false;
+ };
+};
+
+
+
+
+/************************************************************/
+/* */
+/* RadioGroup class (container) */
+/* */
+/************************************************************/
+
+class GLUI_RadioGroup : public GLUI_Control
+{
+public:
+ int num_buttons;
+
+ void draw( int x, int y );
+ void set_name( char *text );
+ void set_int_val( int int_val );
+ void set_selected( int int_val );
+
+ void draw_group( int translate );
+
+ GLUI_RadioGroup( void ) {
+ type = GLUI_CONTROL_RADIOGROUP;
+ x_off = 0;
+ y_off_top = 0;
+ y_off_bot = 0;
+ is_container = true;
+ w = 300;
+ h = 300;
+ num_buttons = 0;
+ name[0] = '\0';
+ can_activate = false;
+ live_type = GLUI_LIVE_INT;
+ };
+};
+
+
+
+/************************************************************/
+/* */
+/* RadioButton class (container) */
+/* */
+/************************************************************/
+
+class GLUI_RadioButton : public GLUI_Control
+{
+public:
+ int orig_value, currently_inside;
+ int text_x_offset;
+
+ int mouse_down_handler( int local_x, int local_y );
+ int mouse_up_handler( int local_x, int local_y, int inside );
+ int mouse_held_down_handler( int local_x, int local_y, int inside );
+
+ void draw( int x, int y );
+ void update_size( void );
+
+ void draw_active_area( void );
+ void draw_checked( void );
+ void draw_unchecked( void );
+ void draw_O( void );
+
+ GLUI_RadioGroup *group;
+
+ GLUI_RadioButton( void ) {
+ sprintf( name, "RadioButton: %p", this );
+ type = GLUI_CONTROL_RADIOBUTTON;
+ h = GLUI_RADIOBUTTON_SIZE;
+ group = NULL;
+ orig_value = -1;
+ text_x_offset = 18;
+ can_activate = true;
+ };
+};
+
+
+/************************************************************/
+/* */
+/* Separator class (container) */
+/* */
+/************************************************************/
+
+class GLUI_Separator : public GLUI_Control
+{
+public:
+ void draw( int x, int y );
+
+ GLUI_Separator( void ) {
+ type = GLUI_CONTROL_SEPARATOR;
+ w = 100;
+ h = GLUI_SEPARATOR_HEIGHT;
+ can_activate = false;
+ };
+};
+
+
+#define GLUI_SPINNER_ARROW_WIDTH 12
+#define GLUI_SPINNER_ARROW_HEIGHT 8
+#define GLUI_SPINNER_ARROW_Y 2
+
+#define GLUI_SPINNER_STATE_NONE 0
+#define GLUI_SPINNER_STATE_UP 1
+#define GLUI_SPINNER_STATE_DOWN 2
+#define GLUI_SPINNER_STATE_BOTH 3
+
+#define GLUI_SPINNER_DEFAULT_GROWTH_EXP 1.05f
+
+
+/************************************************************/
+/* */
+/* Spinner class (container) */
+/* */
+/************************************************************/
+
+class GLUI_Spinner : public GLUI_Control
+{
+public:
+ int currently_inside;
+ int state;
+ float growth, growth_exp;
+ int last_x, last_y;
+ int data_type;
+ int callback_count;
+ int last_int_val;
+ float last_float_val;
+ int first_callback;
+ float user_speed;
+
+ GLUI_EditText *edittext;
+
+ int mouse_down_handler( int local_x, int local_y );
+ int mouse_up_handler( int local_x, int local_y, int same );
+ int mouse_held_down_handler( int local_x, int local_y, int inside );
+ int key_handler( unsigned char key,int modifiers );
+ int special_handler( int key,int modifiers );
+
+ void draw( int x, int y );
+ void draw_pressed( void );
+ void draw_unpressed( void );
+ void draw_text( int sunken );
+
+ void update_size( void );
+
+ void set_float_limits( float low,float high,int limit_type=GLUI_LIMIT_CLAMP);
+ void set_int_limits( int low, int high,int limit_type=GLUI_LIMIT_CLAMP);
+ int find_arrow( int local_x, int local_y );
+ void do_drag( int x, int y );
+ void do_callbacks( void );
+ void draw_arrows( void );
+ void do_click( void );
+ void idle( void );
+ int needs_idle( void );
+
+ char *get_text( void );
+
+ void set_float_val( float new_val );
+ void set_int_val( int new_val );
+ float get_float_val( void );
+ int get_int_val( void );
+ void increase_growth( void );
+ void reset_growth( void );
+
+ void set_speed( float speed ) { user_speed = speed; };
+
+ GLUI_Spinner( void ) {
+ sprintf( name, "Spinner: %p", this );
+ type = GLUI_CONTROL_SPINNER;
+ h = GLUI_EDITTEXT_HEIGHT;
+ w = GLUI_EDITTEXT_WIDTH;
+ x_off = 0;
+ y_off_top = 0;
+ y_off_bot = 0;
+ can_activate = true;
+ state = GLUI_SPINNER_STATE_NONE;
+ edittext = NULL;
+ growth_exp = GLUI_SPINNER_DEFAULT_GROWTH_EXP;
+ callback_count = 0;
+ first_callback = true;
+ user_speed = 1.0;
+ };
+};
+
+/************************************************************/
+
+/* */
+/* StaticText class */
+/* */
+/************************************************************/
+
+class GLUI_StaticText : public GLUI_Control
+{
+public:
+ void set_text( char *text );
+ void draw( int x, int y );
+ void draw_text( void );
+ void update_size( void );
+ void erase_text( void );
+
+ GLUI_StaticText( void ) {
+ type = GLUI_CONTROL_STATICTEXT;
+ h = GLUI_STATICTEXT_SIZE;
+ name[0] = '\0';
+ can_activate = false;
+ };
+};
+
+
+
+/************************************************************/
+/* */
+/* Listbox class */
+/* */
+/************************************************************/
+
+class GLUI_Listbox_Item : public GLUI_Node
+{
+public:
+ GLUI_String text;
+ int id;
+};
+
+class GLUI_Listbox : public GLUI_Control
+{
+public:
+ GLUI_String curr_text;
+ GLUI_Listbox_Item items_list;
+ int depressed;
+
+ int orig_value, currently_inside;
+ int text_x_offset, title_x_offset;
+ int glut_menu_id;
+
+ int mouse_down_handler( int local_x, int local_y );
+ int mouse_up_handler( int local_x, int local_y, int inside );
+ int mouse_held_down_handler( int local_x, int local_y, int inside );
+ int key_handler( unsigned char key,int modifiers );
+ int special_handler( int key,int modifiers );
+
+ void update_size( void );
+ void draw( int x, int y );
+ int mouse_over( int state, int x, int y );
+
+ void draw_active_area( void );
+ void set_int_val( int new_val );
+ void dump( FILE *output );
+
+ int add_item( int id, char *text );
+ int delete_item( char *text );
+ int delete_item( int id );
+ int sort_items( void );
+
+ int do_selection( int item );
+
+ void increase_width( void );
+
+ GLUI_Listbox_Item *get_item_ptr( char *text );
+ GLUI_Listbox_Item *get_item_ptr( int id );
+
+
+ GLUI_Listbox( void ) {
+ sprintf( name, "Listbox: %p", this );
+ type = GLUI_CONTROL_LISTBOX;
+ w = GLUI_EDITTEXT_WIDTH;
+ h = GLUI_EDITTEXT_HEIGHT;
+ orig_value = -1;
+ title_x_offset = 0;
+ text_x_offset = 55;
+ can_activate = true;
+ curr_text[0] = '\0';
+ live_type = GLUI_LIVE_INT; /* This has an integer live var */
+ depressed = false;
+ glut_menu_id = -1;
+ };
+
+ ~GLUI_Listbox();
+};
+
+
+/************************************************************/
+/* */
+/* Mouse_Interaction class */
+/* */
+/************************************************************/
+
+class GLUI_Mouse_Interaction : public GLUI_Control
+{
+public:
+ /*int get_main_area_size( void ) { return MIN( h-18, */
+ int draw_active_area_only;
+
+ int mouse_down_handler( int local_x, int local_y );
+ int mouse_up_handler( int local_x, int local_y, int inside );
+ int mouse_held_down_handler( int local_x, int local_y, int inside );
+ int special_handler( int key, int modifiers );
+ void update_size( void );
+ void draw( int x, int y );
+ void draw_active_area( void );
+
+ /*** The following methods (starting with "iaction_") need to
+ be overloaded ***/
+ virtual int iaction_mouse_down_handler( int local_x, int local_y ) = 0;
+ virtual int iaction_mouse_up_handler( int local_x, int local_y, int inside )=0;
+ virtual int iaction_mouse_held_down_handler( int local_x, int local_y, int inside
)=0;
+ virtual int iaction_special_handler( int key, int modifiers )=0;
+ virtual void iaction_draw_active_area_persp( void )=0;
+ virtual void iaction_draw_active_area_ortho( void )=0;
+ virtual void iaction_dump( FILE *output )=0;
+ virtual void iaction_init( void ) = 0;
+
+ GLUI_Mouse_Interaction( void ) {
+ sprintf( name, "Mouse_Interaction: %p", this );
+ type = GLUI_CONTROL_MOUSE_INTERACTION;
+ w = GLUI_MOUSE_INTERACTION_WIDTH;
+ h = GLUI_MOUSE_INTERACTION_HEIGHT;
+ can_activate = true;
+ live_type = GLUI_LIVE_NONE;
+ alignment = GLUI_ALIGN_CENTER;
+ draw_active_area_only = false;
+ };
+};
+
+
+/************************************************************/
+/* */
+/* Rotation class */
+/* */
+/************************************************************/
+
+class GLUI_Rotation : public GLUI_Mouse_Interaction
+{
+public:
+ Arcball *ball;
+ GLUquadricObj *quadObj;
+ int can_spin, spinning;
+ float damping;
+
+ int iaction_mouse_down_handler( int local_x, int local_y );
+ int iaction_mouse_up_handler( int local_x, int local_y, int inside );
+ int iaction_mouse_held_down_handler( int local_x, int local_y, int inside );
+ int iaction_special_handler( int key, int modifiers );
+ void iaction_init( void ) { init_ball(); };
+ void iaction_draw_active_area_persp( void );
+ void iaction_draw_active_area_ortho( void );
+ void iaction_dump( FILE *output );
+
+ /* void update_size( void ); */
+ /* void draw( int x, int y ); */
+ /* int mouse_over( int state, int x, int y ); */
+
+ void setup_texture( void );
+ void setup_lights( void );
+ void draw_ball( float radius );
+
+ void init_ball( void );
+
+ void reset( void );
+
+ int needs_idle( void );
+ void idle( void );
+
+ void copy_float_array_to_ball( void );
+ void copy_ball_to_float_array( void );
+
+ void set_spin( float damp_factor );
+
+ GLUI_Rotation(void);
+};
+
+
+
+/************************************************************/
+/* */
+/* Translation class */
+/* */
+/************************************************************/
+
+class GLUI_Translation : public GLUI_Mouse_Interaction
+{
+public:
+ int trans_type; /* Is this an XY or a Z controller? */
+ int down_x, down_y;
+ float scale_factor;
+ GLUquadricObj *quadObj;
+ int trans_mouse_code;
+ float orig_x, orig_y, orig_z;
+ int locked;
+
+ int iaction_mouse_down_handler( int local_x, int local_y );
+ int iaction_mouse_up_handler( int local_x, int local_y, int inside );
+ int iaction_mouse_held_down_handler( int local_x, int local_y, int inside );
+ int iaction_special_handler( int key, int modifiers );
+ void iaction_init( void ) { };
+ void iaction_draw_active_area_persp( void );
+ void iaction_draw_active_area_ortho( void );
+ void iaction_dump( FILE *output );
+
+ void set_speed( float s ) { scale_factor = s; };
+
+ void setup_texture( void );
+ void setup_lights( void );
+ void draw_2d_arrow( int radius, int filled, int orientation );
+ void draw_2d_x_arrows( int radius );
+ void draw_2d_y_arrows( int radius );
+ void draw_2d_z_arrows( int radius );
+ void draw_2d_xy_arrows( int radius );
+
+ int get_mouse_code( int x, int y );
+
+ /* Float array is either a single float (for single-axis controls),
+ or two floats for X and Y (if an XY controller) */
+
+ float get_z( void ) { return float_array_val[0]; }
+ float get_x( void ) { return float_array_val[0]; }
+ float get_y( void ) {
+ if ( trans_type == GLUI_TRANSLATION_XY ) return float_array_val[1];
+ else return float_array_val[0];
+ }
+
+ void set_z( float val );
+ void set_x( float val );
+ void set_y( float val );
+ void set_one_val( float val, int index );
+
+ GLUI_Translation( void ) {
+ locked = GLUI_TRANSLATION_LOCK_NONE;
+ sprintf( name, "Translation: %p", this );
+ type = GLUI_CONTROL_TRANSLATION;
+ w = GLUI_MOUSE_INTERACTION_WIDTH;
+ h = GLUI_MOUSE_INTERACTION_HEIGHT;
+ can_activate = true;
+ live_type = GLUI_LIVE_FLOAT_ARRAY;
+ float_array_size = 0;
+ alignment = GLUI_ALIGN_CENTER;
+ trans_type = GLUI_TRANSLATION_XY;
+ scale_factor = 1.0;
+ quadObj = NULL;
+ trans_mouse_code = GLUI_TRANSLATION_MOUSE_NONE;
+ };
+};
+
+
+
+
+/********** Misc functions *********************/
+int _glutBitmapWidthString( void *font, char *s );
+void _glutBitmapString( void *font, char *s );
+
+
+
+/********** Our own callbacks for glut *********/
+/* These are the callbacks that we pass to glut. They take
+ some action if necessary, then (possibly) call the user-level
+ glut callbacks.
+ */
+
+void glui_display_func( void );
+void glui_reshape_func( int w, int h );
+void glui_keyboard_func(unsigned char key, int x, int y);
+void glui_special_func(int key, int x, int y);
+void glui_mouse_func(int button, int state, int x, int y);
+void glui_motion_func(int x, int y);
+void glui_passive_motion_func(int x, int y);
+void glui_entry_func(int state);
+void glui_visibility_func(int state);
+void glui_idle_func(void);
+
+void glui_parent_window_reshape_func( int w, int h );
+void glui_parent_window_keyboard_func(unsigned char key, int x, int y);
+void glui_parent_window_mouse_func(int, int, int, int );
+void glui_parent_window_special_func(int key, int x, int y);
+
+/************************************************************/
+/* */
+/* Slider class */
+/* */
+/************************************************************/
+
+#ifndef CLAMP
+#define CLAMP(x,lo,hi) {if ((x) < (lo)) {(x)=(lo);} else if((x) > (hi))
{(x)=(hi);}}
+#endif
+
+class GLUI_Slider : public GLUI_Control
+{
+public:
+ int pressed;
+ int data_type;
+ float float_low, float_high;
+ int int_low, int_high;
+ int graduations;
+
+ int mouse_down_handler( int local_x, int local_y );
+ int mouse_up_handler( int local_x, int local_y, int inside );
+ int mouse_held_down_handler( int local_x, int local_y, int inside );
+ int special_handler( int key, int modifiers );
+
+ void draw( int x, int y );
+ void draw_active_area( void );
+ void draw_translated_active_area( void );
+
+ void draw_val( void );
+ void draw_slider( void );
+ void draw_knob( int x, int off_l, int off_r, int off_t, int off_b,
+ unsigned char r, unsigned char g, unsigned char b );
+ void update_val(int x, int y);
+
+ virtual void set_int_val( int new_int )
+ { CLAMP(new_int, int_low, int_high); int_val = new_int;
+ output_live(true); if (can_draw()) draw_translated_active_area();};
+ virtual void set_float_val( float new_float )
+ { CLAMP(new_float, float_low, float_high); float_val = new_float;
+ output_live(true); if (can_draw()) draw_translated_active_area();};
+
+ void set_float_limits( float low,float high);
+ void set_int_limits( int low, int high);
+ void set_num_graduations( int grads );
+
+ void update_size( void );
+
+ /* int mouse_over( int state, int x, int y ); */
+
+ GLUI_Slider(void);
+};
+
+
+
+#endif
Index: external/trimesh/include/GL/freeglut_std.h
--- external/trimesh/include/GL/freeglut_std.h (revision 0)
+++ external/trimesh/include/GL/freeglut_std.h (revision 0)
@@ -0,0 +1,579 @@
+#ifndef __FREEGLUT_STD_H__
+#define __FREEGLUT_STD_H__
+
+/*
+ * freeglut_std.h
+ *
+ * The GLUT-compatible part of the freeglut library include file
+ *
+ * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
+ * Written by Pawel W. Olszta, <olszta(a)sourceforge.net>
+ * Creation date: Thu Dec 2 1999
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#define FREEGLUT_STATIC
+
+/*
+ * Under windows, we have to differentiate between static and dynamic libraries
+ */
+#if defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__)
+
+/* #pragma may not be supported by some compilers.
+ * Discussion by FreeGLUT developers suggests that
+ * Visual C++ specific code involving pragmas may
+ * need to move to a separate header. 24th Dec 2003
+ */
+
+# define WIN32_LEAN_AND_MEAN
+# define NO_MIN_MAX
+# include <windows.h>
+# undef min
+# undef max
+
+/* Windows static library */
+# ifdef FREEGLUT_STATIC
+
+# define FGAPI
+# define FGAPIENTRY
+
+ /* Link with Win32 static freeglut lib */
+# if defined(_MSC_VER)
+# pragma comment (lib, "freeglut_static.lib")
+# endif
+
+/* Windows shared library (DLL) */
+# else
+
+# if defined(FREEGLUT_EXPORTS)
+# define FGAPI __declspec(dllexport)
+# else
+# define FGAPI __declspec(dllimport)
+
+ /* link with Win32 shared freeglut lib */
+# if defined(_MSC_VER)
+# ifndef _WIN32_WCE
+# pragma comment (lib, "freeglut.lib")
+# endif
+# endif
+
+# endif
+
+# define FGAPIENTRY __stdcall
+
+# endif
+
+/* Drag in other Windows libraries as required by FreeGLUT */
+# if defined(_MSC_VER)
+# ifndef _WIN32_WCE
+# pragma comment (lib, "winmm.lib") /* link Windows MultiMedia lib
*/
+# pragma comment (lib, "user32.lib") /* link Windows user lib
*/
+# pragma comment (lib, "gdi32.lib") /* link Windows GDI lib
*/
+# pragma comment (lib, "opengl32.lib") /* link Microsoft OpenGL lib
*/
+# pragma comment (lib, "glu32.lib") /* link OpenGL Utility lib
*/
+# endif //_WIN32_WCE
+# endif
+
+#else
+
+/* Non-Windows definition of FGAPI and FGAPIENTRY */
+# define FGAPI
+# define FGAPIENTRY
+
+#endif
+
+/*
+ * The freeglut and GLUT API versions
+ */
+#define FREEGLUT 1
+#define GLUT_API_VERSION 4
+#define FREEGLUT_VERSION_2_0 1
+#define GLUT_XLIB_IMPLEMENTATION 13
+
+/*
+ * Always include OpenGL and GLU headers
+ */
+#include <GL/gl.h>
+#include <GL/glu.h>
+
+/*
+ * GLUT API macro definitions -- the special key codes:
+ */
+#define GLUT_KEY_F1 0x0001
+#define GLUT_KEY_F2 0x0002
+#define GLUT_KEY_F3 0x0003
+#define GLUT_KEY_F4 0x0004
+#define GLUT_KEY_F5 0x0005
+#define GLUT_KEY_F6 0x0006
+#define GLUT_KEY_F7 0x0007
+#define GLUT_KEY_F8 0x0008
+#define GLUT_KEY_F9 0x0009
+#define GLUT_KEY_F10 0x000A
+#define GLUT_KEY_F11 0x000B
+#define GLUT_KEY_F12 0x000C
+#define GLUT_KEY_LEFT 0x0064
+#define GLUT_KEY_UP 0x0065
+#define GLUT_KEY_RIGHT 0x0066
+#define GLUT_KEY_DOWN 0x0067
+#define GLUT_KEY_PAGE_UP 0x0068
+#define GLUT_KEY_PAGE_DOWN 0x0069
+#define GLUT_KEY_HOME 0x006A
+#define GLUT_KEY_END 0x006B
+#define GLUT_KEY_INSERT 0x006C
+
+/*
+ * GLUT API macro definitions -- mouse state definitions
+ */
+#define GLUT_LEFT_BUTTON 0x0000
+#define GLUT_MIDDLE_BUTTON 0x0001
+#define GLUT_RIGHT_BUTTON 0x0002
+#define GLUT_DOWN 0x0000
+#define GLUT_UP 0x0001
+#define GLUT_LEFT 0x0000
+#define GLUT_ENTERED 0x0001
+
+/*
+ * GLUT API macro definitions -- the display mode definitions
+ */
+#define GLUT_RGB 0x0000
+#define GLUT_RGBA 0x0000
+#define GLUT_INDEX 0x0001
+#define GLUT_SINGLE 0x0000
+#define GLUT_DOUBLE 0x0002
+#define GLUT_ACCUM 0x0004
+#define GLUT_ALPHA 0x0008
+#define GLUT_DEPTH 0x0010
+#define GLUT_STENCIL 0x0020
+#define GLUT_MULTISAMPLE 0x0080
+#define GLUT_STEREO 0x0100
+#define GLUT_LUMINANCE 0x0200
+
+/*
+ * GLUT API macro definitions -- windows and menu related definitions
+ */
+#define GLUT_MENU_NOT_IN_USE 0x0000
+#define GLUT_MENU_IN_USE 0x0001
+#define GLUT_NOT_VISIBLE 0x0000
+#define GLUT_VISIBLE 0x0001
+#define GLUT_HIDDEN 0x0000
+#define GLUT_FULLY_RETAINED 0x0001
+#define GLUT_PARTIALLY_RETAINED 0x0002
+#define GLUT_FULLY_COVERED 0x0003
+
+/*
+ * GLUT API macro definitions -- fonts definitions
+ *
+ * Steve Baker suggested to make it binary compatible with GLUT:
+ */
+#if defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__)
+# define GLUT_STROKE_ROMAN ((void *)0x0000)
+# define GLUT_STROKE_MONO_ROMAN ((void *)0x0001)
+# define GLUT_BITMAP_9_BY_15 ((void *)0x0002)
+# define GLUT_BITMAP_8_BY_13 ((void *)0x0003)
+# define GLUT_BITMAP_TIMES_ROMAN_10 ((void *)0x0004)
+# define GLUT_BITMAP_TIMES_ROMAN_24 ((void *)0x0005)
+# define GLUT_BITMAP_HELVETICA_10 ((void *)0x0006)
+# define GLUT_BITMAP_HELVETICA_12 ((void *)0x0007)
+# define GLUT_BITMAP_HELVETICA_18 ((void *)0x0008)
+#else
+ /*
+ * I don't really know if it's a good idea... But here it goes:
+ */
+ extern void* glutStrokeRoman;
+ extern void* glutStrokeMonoRoman;
+ extern void* glutBitmap9By15;
+ extern void* glutBitmap8By13;
+ extern void* glutBitmapTimesRoman10;
+ extern void* glutBitmapTimesRoman24;
+ extern void* glutBitmapHelvetica10;
+ extern void* glutBitmapHelvetica12;
+ extern void* glutBitmapHelvetica18;
+
+ /*
+ * Those pointers will be used by following definitions:
+ */
+# define GLUT_STROKE_ROMAN ((void *) &glutStrokeRoman)
+# define GLUT_STROKE_MONO_ROMAN ((void *) &glutStrokeMonoRoman)
+# define GLUT_BITMAP_9_BY_15 ((void *) &glutBitmap9By15)
+# define GLUT_BITMAP_8_BY_13 ((void *) &glutBitmap8By13)
+# define GLUT_BITMAP_TIMES_ROMAN_10 ((void *) &glutBitmapTimesRoman10)
+# define GLUT_BITMAP_TIMES_ROMAN_24 ((void *) &glutBitmapTimesRoman24)
+# define GLUT_BITMAP_HELVETICA_10 ((void *) &glutBitmapHelvetica10)
+# define GLUT_BITMAP_HELVETICA_12 ((void *) &glutBitmapHelvetica12)
+# define GLUT_BITMAP_HELVETICA_18 ((void *) &glutBitmapHelvetica18)
+#endif
+
+/*
+ * GLUT API macro definitions -- the glutGet parameters
+ */
+#define GLUT_WINDOW_X 0x0064
+#define GLUT_WINDOW_Y 0x0065
+#define GLUT_WINDOW_WIDTH 0x0066
+#define GLUT_WINDOW_HEIGHT 0x0067
+#define GLUT_WINDOW_BUFFER_SIZE 0x0068
+#define GLUT_WINDOW_STENCIL_SIZE 0x0069
+#define GLUT_WINDOW_DEPTH_SIZE 0x006A
+#define GLUT_WINDOW_RED_SIZE 0x006B
+#define GLUT_WINDOW_GREEN_SIZE 0x006C
+#define GLUT_WINDOW_BLUE_SIZE 0x006D
+#define GLUT_WINDOW_ALPHA_SIZE 0x006E
+#define GLUT_WINDOW_ACCUM_RED_SIZE 0x006F
+#define GLUT_WINDOW_ACCUM_GREEN_SIZE 0x0070
+#define GLUT_WINDOW_ACCUM_BLUE_SIZE 0x0071
+#define GLUT_WINDOW_ACCUM_ALPHA_SIZE 0x0072
+#define GLUT_WINDOW_DOUBLEBUFFER 0x0073
+#define GLUT_WINDOW_RGBA 0x0074
+#define GLUT_WINDOW_PARENT 0x0075
+#define GLUT_WINDOW_NUM_CHILDREN 0x0076
+#define GLUT_WINDOW_COLORMAP_SIZE 0x0077
+#define GLUT_WINDOW_NUM_SAMPLES 0x0078
+#define GLUT_WINDOW_STEREO 0x0079
+#define GLUT_WINDOW_CURSOR 0x007A
+
+#define GLUT_SCREEN_WIDTH 0x00C8
+#define GLUT_SCREEN_HEIGHT 0x00C9
+#define GLUT_SCREEN_WIDTH_MM 0x00CA
+#define GLUT_SCREEN_HEIGHT_MM 0x00CB
+#define GLUT_MENU_NUM_ITEMS 0x012C
+#define GLUT_DISPLAY_MODE_POSSIBLE 0x0190
+#define GLUT_INIT_WINDOW_X 0x01F4
+#define GLUT_INIT_WINDOW_Y 0x01F5
+#define GLUT_INIT_WINDOW_WIDTH 0x01F6
+#define GLUT_INIT_WINDOW_HEIGHT 0x01F7
+#define GLUT_INIT_DISPLAY_MODE 0x01F8
+#define GLUT_ELAPSED_TIME 0x02BC
+#define GLUT_WINDOW_FORMAT_ID 0x007B
+#define GLUT_INIT_STATE 0x007C
+
+/*
+ * GLUT API macro definitions -- the glutDeviceGet parameters
+ */
+#define GLUT_HAS_KEYBOARD 0x0258
+#define GLUT_HAS_MOUSE 0x0259
+#define GLUT_HAS_SPACEBALL 0x025A
+#define GLUT_HAS_DIAL_AND_BUTTON_BOX 0x025B
+#define GLUT_HAS_TABLET 0x025C
+#define GLUT_NUM_MOUSE_BUTTONS 0x025D
+#define GLUT_NUM_SPACEBALL_BUTTONS 0x025E
+#define GLUT_NUM_BUTTON_BOX_BUTTONS 0x025F
+#define GLUT_NUM_DIALS 0x0260
+#define GLUT_NUM_TABLET_BUTTONS 0x0261
+#define GLUT_DEVICE_IGNORE_KEY_REPEAT 0x0262
+#define GLUT_DEVICE_KEY_REPEAT 0x0263
+#define GLUT_HAS_JOYSTICK 0x0264
+#define GLUT_OWNS_JOYSTICK 0x0265
+#define GLUT_JOYSTICK_BUTTONS 0x0266
+#define GLUT_JOYSTICK_AXES 0x0267
+#define GLUT_JOYSTICK_POLL_RATE 0x0268
+
+/*
+ * GLUT API macro definitions -- the glutLayerGet parameters
+ */
+#define GLUT_OVERLAY_POSSIBLE 0x0320
+#define GLUT_LAYER_IN_USE 0x0321
+#define GLUT_HAS_OVERLAY 0x0322
+#define GLUT_TRANSPARENT_INDEX 0x0323
+#define GLUT_NORMAL_DAMAGED 0x0324
+#define GLUT_OVERLAY_DAMAGED 0x0325
+
+/*
+ * GLUT API macro definitions -- the glutVideoResizeGet parameters
+ */
+#define GLUT_VIDEO_RESIZE_POSSIBLE 0x0384
+#define GLUT_VIDEO_RESIZE_IN_USE 0x0385
+#define GLUT_VIDEO_RESIZE_X_DELTA 0x0386
+#define GLUT_VIDEO_RESIZE_Y_DELTA 0x0387
+#define GLUT_VIDEO_RESIZE_WIDTH_DELTA 0x0388
+#define GLUT_VIDEO_RESIZE_HEIGHT_DELTA 0x0389
+#define GLUT_VIDEO_RESIZE_X 0x038A
+#define GLUT_VIDEO_RESIZE_Y 0x038B
+#define GLUT_VIDEO_RESIZE_WIDTH 0x038C
+#define GLUT_VIDEO_RESIZE_HEIGHT 0x038D
+
+/*
+ * GLUT API macro definitions -- the glutUseLayer parameters
+ */
+#define GLUT_NORMAL 0x0000
+#define GLUT_OVERLAY 0x0001
+
+/*
+ * GLUT API macro definitions -- the glutGetModifiers parameters
+ */
+#define GLUT_ACTIVE_SHIFT 0x0001
+#define GLUT_ACTIVE_CTRL 0x0002
+#define GLUT_ACTIVE_ALT 0x0004
+
+/*
+ * GLUT API macro definitions -- the glutSetCursor parameters
+ */
+#define GLUT_CURSOR_RIGHT_ARROW 0x0000
+#define GLUT_CURSOR_LEFT_ARROW 0x0001
+#define GLUT_CURSOR_INFO 0x0002
+#define GLUT_CURSOR_DESTROY 0x0003
+#define GLUT_CURSOR_HELP 0x0004
+#define GLUT_CURSOR_CYCLE 0x0005
+#define GLUT_CURSOR_SPRAY 0x0006
+#define GLUT_CURSOR_WAIT 0x0007
+#define GLUT_CURSOR_TEXT 0x0008
+#define GLUT_CURSOR_CROSSHAIR 0x0009
+#define GLUT_CURSOR_UP_DOWN 0x000A
+#define GLUT_CURSOR_LEFT_RIGHT 0x000B
+#define GLUT_CURSOR_TOP_SIDE 0x000C
+#define GLUT_CURSOR_BOTTOM_SIDE 0x000D
+#define GLUT_CURSOR_LEFT_SIDE 0x000E
+#define GLUT_CURSOR_RIGHT_SIDE 0x000F
+#define GLUT_CURSOR_TOP_LEFT_CORNER 0x0010
+#define GLUT_CURSOR_TOP_RIGHT_CORNER 0x0011
+#define GLUT_CURSOR_BOTTOM_RIGHT_CORNER 0x0012
+#define GLUT_CURSOR_BOTTOM_LEFT_CORNER 0x0013
+#define GLUT_CURSOR_INHERIT 0x0064
+#define GLUT_CURSOR_NONE 0x0065
+#define GLUT_CURSOR_FULL_CROSSHAIR 0x0066
+
+/*
+ * GLUT API macro definitions -- RGB color component specification definitions
+ */
+#define GLUT_RED 0x0000
+#define GLUT_GREEN 0x0001
+#define GLUT_BLUE 0x0002
+
+/*
+ * GLUT API macro definitions -- additional keyboard and joystick definitions
+ */
+#define GLUT_KEY_REPEAT_OFF 0x0000
+#define GLUT_KEY_REPEAT_ON 0x0001
+#define GLUT_KEY_REPEAT_DEFAULT 0x0002
+
+#define GLUT_JOYSTICK_BUTTON_A 0x0001
+#define GLUT_JOYSTICK_BUTTON_B 0x0002
+#define GLUT_JOYSTICK_BUTTON_C 0x0004
+#define GLUT_JOYSTICK_BUTTON_D 0x0008
+
+/*
+ * GLUT API macro definitions -- game mode definitions
+ */
+#define GLUT_GAME_MODE_ACTIVE 0x0000
+#define GLUT_GAME_MODE_POSSIBLE 0x0001
+#define GLUT_GAME_MODE_WIDTH 0x0002
+#define GLUT_GAME_MODE_HEIGHT 0x0003
+#define GLUT_GAME_MODE_PIXEL_DEPTH 0x0004
+#define GLUT_GAME_MODE_REFRESH_RATE 0x0005
+#define GLUT_GAME_MODE_DISPLAY_CHANGED 0x0006
+
+/*
+ * Initialization functions, see fglut_init.c
+ */
+FGAPI void FGAPIENTRY glutInit( int* pargc, char** argv );
+FGAPI void FGAPIENTRY glutInitWindowPosition( int x, int y );
+FGAPI void FGAPIENTRY glutInitWindowSize( int width, int height );
+FGAPI void FGAPIENTRY glutInitDisplayMode( unsigned int displayMode );
+FGAPI void FGAPIENTRY glutInitDisplayString( const char* displayMode );
+
+/*
+ * Process loop function, see freeglut_main.c
+ */
+FGAPI void FGAPIENTRY glutMainLoop( void );
+
+/*
+ * Window management functions, see freeglut_window.c
+ */
+FGAPI int FGAPIENTRY glutCreateWindow( const char* title );
+FGAPI int FGAPIENTRY glutCreateSubWindow( int window, int x, int y, int width, int
height );
+FGAPI void FGAPIENTRY glutDestroyWindow( int window );
+FGAPI void FGAPIENTRY glutSetWindow( int window );
+FGAPI int FGAPIENTRY glutGetWindow( void );
+FGAPI void FGAPIENTRY glutSetWindowTitle( const char* title );
+FGAPI void FGAPIENTRY glutSetIconTitle( const char* title );
+FGAPI void FGAPIENTRY glutReshapeWindow( int width, int height );
+FGAPI void FGAPIENTRY glutPositionWindow( int x, int y );
+FGAPI void FGAPIENTRY glutShowWindow( void );
+FGAPI void FGAPIENTRY glutHideWindow( void );
+FGAPI void FGAPIENTRY glutIconifyWindow( void );
+FGAPI void FGAPIENTRY glutPushWindow( void );
+FGAPI void FGAPIENTRY glutPopWindow( void );
+FGAPI void FGAPIENTRY glutFullScreen( void );
+
+/*
+ * Display-connected functions, see freeglut_display.c
+ */
+FGAPI void FGAPIENTRY glutPostWindowRedisplay( int window );
+FGAPI void FGAPIENTRY glutPostRedisplay( void );
+FGAPI void FGAPIENTRY glutSwapBuffers( void );
+
+/*
+ * Mouse cursor functions, see freeglut_cursor.c
+ */
+FGAPI void FGAPIENTRY glutWarpPointer( int x, int y );
+FGAPI void FGAPIENTRY glutSetCursor( int cursor );
+
+/*
+ * Overlay stuff, see freeglut_overlay.c
+ */
+FGAPI void FGAPIENTRY glutEstablishOverlay( void );
+FGAPI void FGAPIENTRY glutRemoveOverlay( void );
+FGAPI void FGAPIENTRY glutUseLayer( GLenum layer );
+FGAPI void FGAPIENTRY glutPostOverlayRedisplay( void );
+FGAPI void FGAPIENTRY glutPostWindowOverlayRedisplay( int window );
+FGAPI void FGAPIENTRY glutShowOverlay( void );
+FGAPI void FGAPIENTRY glutHideOverlay( void );
+
+/*
+ * Menu stuff, see freeglut_menu.c
+ */
+FGAPI int FGAPIENTRY glutCreateMenu( void (* callback)( int menu ) );
+FGAPI void FGAPIENTRY glutDestroyMenu( int menu );
+FGAPI int FGAPIENTRY glutGetMenu( void );
+FGAPI void FGAPIENTRY glutSetMenu( int menu );
+FGAPI void FGAPIENTRY glutAddMenuEntry( const char* label, int value );
+FGAPI void FGAPIENTRY glutAddSubMenu( const char* label, int subMenu );
+FGAPI void FGAPIENTRY glutChangeToMenuEntry( int item, const char* label, int value
);
+FGAPI void FGAPIENTRY glutChangeToSubMenu( int item, const char* label, int value );
+FGAPI void FGAPIENTRY glutRemoveMenuItem( int item );
+FGAPI void FGAPIENTRY glutAttachMenu( int button );
+FGAPI void FGAPIENTRY glutDetachMenu( int button );
+
+/*
+ * Global callback functions, see freeglut_callbacks.c
+ */
+FGAPI void FGAPIENTRY glutTimerFunc( unsigned int time, void (* callback)( int ), int
value );
+FGAPI void FGAPIENTRY glutIdleFunc( void (* callback)( void ) );
+
+/*
+ * Window-specific callback functions, see freeglut_callbacks.c
+ */
+FGAPI void FGAPIENTRY glutKeyboardFunc( void (* callback)( unsigned char, int, int )
);
+FGAPI void FGAPIENTRY glutSpecialFunc( void (* callback)( int, int, int ) );
+FGAPI void FGAPIENTRY glutReshapeFunc( void (* callback)( int, int ) );
+FGAPI void FGAPIENTRY glutVisibilityFunc( void (* callback)( int ) );
+FGAPI void FGAPIENTRY glutDisplayFunc( void (* callback)( void ) );
+FGAPI void FGAPIENTRY glutMouseFunc( void (* callback)( int, int, int, int ) );
+FGAPI void FGAPIENTRY glutMotionFunc( void (* callback)( int, int ) );
+FGAPI void FGAPIENTRY glutPassiveMotionFunc( void (* callback)( int, int ) );
+FGAPI void FGAPIENTRY glutEntryFunc( void (* callback)( int ) );
+
+FGAPI void FGAPIENTRY glutKeyboardUpFunc( void (* callback)( unsigned char, int, int )
);
+FGAPI void FGAPIENTRY glutSpecialUpFunc( void (* callback)( int, int, int ) );
+FGAPI void FGAPIENTRY glutJoystickFunc( void (* callback)( unsigned int, int, int, int
), int pollInterval );
+FGAPI void FGAPIENTRY glutMenuStateFunc( void (* callback)( int ) );
+FGAPI void FGAPIENTRY glutMenuStatusFunc( void (* callback)( int, int, int ) );
+FGAPI void FGAPIENTRY glutOverlayDisplayFunc( void (* callback)( void ) );
+FGAPI void FGAPIENTRY glutWindowStatusFunc( void (* callback)( int ) );
+
+FGAPI void FGAPIENTRY glutSpaceballMotionFunc( void (* callback)( int, int, int ) );
+FGAPI void FGAPIENTRY glutSpaceballRotateFunc( void (* callback)( int, int, int ) );
+FGAPI void FGAPIENTRY glutSpaceballButtonFunc( void (* callback)( int, int ) );
+FGAPI void FGAPIENTRY glutButtonBoxFunc( void (* callback)( int, int ) );
+FGAPI void FGAPIENTRY glutDialsFunc( void (* callback)( int, int ) );
+FGAPI void FGAPIENTRY glutTabletMotionFunc( void (* callback)( int, int ) );
+FGAPI void FGAPIENTRY glutTabletButtonFunc( void (* callback)( int, int, int, int )
);
+
+/*
+ * State setting and retrieval functions, see freeglut_state.c
+ */
+FGAPI int FGAPIENTRY glutGet( GLenum query );
+FGAPI int FGAPIENTRY glutDeviceGet( GLenum query );
+FGAPI int FGAPIENTRY glutGetModifiers( void );
+FGAPI int FGAPIENTRY glutLayerGet( GLenum query );
+
+/*
+ * Font stuff, see freeglut_font.c
+ */
+FGAPI void FGAPIENTRY glutBitmapCharacter( void* font, int character );
+FGAPI int FGAPIENTRY glutBitmapWidth( void* font, int character );
+FGAPI void FGAPIENTRY glutStrokeCharacter( void* font, int character );
+FGAPI int FGAPIENTRY glutStrokeWidth( void* font, int character );
+FGAPI int FGAPIENTRY glutBitmapLength( void* font, const unsigned char* string );
+FGAPI int FGAPIENTRY glutStrokeLength( void* font, const unsigned char* string );
+
+/*
+ * Geometry functions, see freeglut_geometry.c
+ */
+FGAPI void FGAPIENTRY glutWireCube( GLdouble size );
+FGAPI void FGAPIENTRY glutSolidCube( GLdouble size );
+FGAPI void FGAPIENTRY glutWireSphere( GLdouble radius, GLint slices, GLint stacks );
+FGAPI void FGAPIENTRY glutSolidSphere( GLdouble radius, GLint slices, GLint stacks );
+FGAPI void FGAPIENTRY glutWireCone( GLdouble base, GLdouble height, GLint slices,
GLint stacks );
+FGAPI void FGAPIENTRY glutSolidCone( GLdouble base, GLdouble height, GLint slices,
GLint stacks );
+
+FGAPI void FGAPIENTRY glutWireTorus( GLdouble innerRadius, GLdouble outerRadius, GLint
sides, GLint rings );
+FGAPI void FGAPIENTRY glutSolidTorus( GLdouble innerRadius, GLdouble outerRadius,
GLint sides, GLint rings );
+FGAPI void FGAPIENTRY glutWireDodecahedron( void );
+FGAPI void FGAPIENTRY glutSolidDodecahedron( void );
+FGAPI void FGAPIENTRY glutWireOctahedron( void );
+FGAPI void FGAPIENTRY glutSolidOctahedron( void );
+FGAPI void FGAPIENTRY glutWireTetrahedron( void );
+FGAPI void FGAPIENTRY glutSolidTetrahedron( void );
+FGAPI void FGAPIENTRY glutWireIcosahedron( void );
+FGAPI void FGAPIENTRY glutSolidIcosahedron( void );
+
+/*
+ * Teapot rendering functions, found in freeglut_teapot.c
+ */
+FGAPI void FGAPIENTRY glutWireTeapot( GLdouble size );
+FGAPI void FGAPIENTRY glutSolidTeapot( GLdouble size );
+
+/*
+ * Game mode functions, see freeglut_gamemode.c
+ */
+FGAPI void FGAPIENTRY glutGameModeString( const char* string );
+FGAPI int FGAPIENTRY glutEnterGameMode( void );
+FGAPI void FGAPIENTRY glutLeaveGameMode( void );
+FGAPI int FGAPIENTRY glutGameModeGet( GLenum query );
+
+/*
+ * Video resize functions, see freeglut_videoresize.c
+ */
+FGAPI int FGAPIENTRY glutVideoResizeGet( GLenum query );
+FGAPI void FGAPIENTRY glutSetupVideoResizing( void );
+FGAPI void FGAPIENTRY glutStopVideoResizing( void );
+FGAPI void FGAPIENTRY glutVideoResize( int x, int y, int width, int height );
+FGAPI void FGAPIENTRY glutVideoPan( int x, int y, int width, int height );
+
+/*
+ * Colormap functions, see freeglut_misc.c
+ */
+FGAPI void FGAPIENTRY glutSetColor( int color, GLfloat red, GLfloat green, GLfloat
blue );
+FGAPI GLfloat FGAPIENTRY glutGetColor( int color, int component );
+FGAPI void FGAPIENTRY glutCopyColormap( int window );
+
+/*
+ * Misc keyboard and joystick functions, see freeglut_misc.c
+ */
+FGAPI void FGAPIENTRY glutIgnoreKeyRepeat( int ignore );
+FGAPI void FGAPIENTRY glutSetKeyRepeat( int repeatMode );
+FGAPI void FGAPIENTRY glutForceJoystickFunc( void );
+
+/*
+ * Misc functions, see freeglut_misc.c
+ */
+FGAPI int FGAPIENTRY glutExtensionSupported( const char* extension );
+FGAPI void FGAPIENTRY glutReportErrors( void );
+
+#ifdef __cplusplus
+ }
+#endif
+
+/*** END OF FILE ***/
+
+#endif /* __FREEGLUT_STD_H__ */
+
Index: external/trimesh/include/TriMesh_algo.h
--- external/trimesh/include/TriMesh_algo.h (revision 0)
+++ external/trimesh/include/TriMesh_algo.h (revision 0)
@@ -0,0 +1,145 @@
+#ifndef TRIMESH_ALGO_H
+#define TRIMESH_ALGO_H
+/*
+Szymon Rusinkiewicz
+Princeton University
+
+TriMesh_algo.h
+Various mesh-munging algorithms using TriMeshes
+*/
+
+
+#include "Vec.h"
+#include "XForm.h"
+#include "TriMesh.h"
+
+
+// Optimally re-triangulate a mesh by doing edge flips
+extern void edgeflip(TriMesh *mesh);
+
+// Flip the order of vertices in each face. Turns the mesh inside out.
+extern void faceflip(TriMesh *mesh);
+
+// One iteration of umbrella-operator smoothing
+extern void umbrella(TriMesh *mesh, float stepsize);
+
+// Taubin lambda/mu mesh smoothing
+extern void lmsmooth(TriMesh *mesh, int niters);
+
+// Remove the indicated vertices from the TriMesh.
+extern void remove_vertices(TriMesh *mesh, const std::vector<bool> &toremove);
+
+// Remove vertices that aren't referenced by any face
+extern void remove_unused_vertices(TriMesh *mesh);
+
+// Remove faces as indicated by toremove. Should probably be
+// followed by a call to remove_unused_vertices()
+extern void remove_faces(TriMesh *mesh, const std::vector<bool> &toremove);
+
+// Remove long, skinny faces. Should probably be followed by a
+// call to remove_unused_vertices()
+extern void remove_sliver_faces(TriMesh *mesh);
+
+// Remap vertices according to the given table
+extern void remap_verts(TriMesh *mesh, const std::vector<int> &remap_table);
+
+// Reorder vertices in a mesh according to the order in which
+// they are referenced by the tstrips or faces.
+extern void reorder_verts(TriMesh *mesh);
+
+// Perform one iteration of subdivision on a mesh.
+enum { SUBDIV_PLANAR, SUBDIV_LOOP, SUBDIV_LOOP_ORIG, SUBDIV_LOOP_NEW,
+ SUBDIV_BUTTERFLY, SUBDIV_BUTTERFLY_MODIFIED };
+extern void subdiv(TriMesh *mesh, int scheme = SUBDIV_LOOP);
+
+// Smooth the mesh geometry
+extern void smooth_mesh(TriMesh *themesh, float sigma);
+
+// Bilateral smoothing
+extern void bilateral_smooth_mesh(TriMesh *themesh, float sigma1, float sigma2);
+
+// Diffuse the normals across the mesh
+extern void diffuse_normals(TriMesh *themesh, float sigma);
+
+// Diffuse the curvatures across the mesh
+extern void diffuse_curv(TriMesh *themesh, float sigma);
+
+// Diffuse the curvature derivatives across the mesh
+extern void diffuse_dcurv(TriMesh *themesh, float sigma);
+
+// Given a curvature tensor, find principal directions and curvatures
+extern void diagonalize_curv(const vec &old_u, const vec &old_v,
+ float ku, float kuv, float kv,
+ const vec &new_norm,
+ vec &pdir1, vec &pdir2, float &k1, float &k2);
+
+// Reproject a curvature tensor from the basis spanned by old_u and old_v
+// (which are assumed to be unit-length and perpendicular) to the
+// new_u, new_v basis.
+extern void proj_curv(const vec &old_u, const vec &old_v,
+ float old_ku, float old_kuv, float old_kv,
+ const vec &new_u, const vec &new_v,
+ float &new_ku, float &new_kuv, float &new_kv);
+
+// Like the above, but for dcurv
+extern void proj_dcurv(const vec &old_u, const vec &old_v,
+ const Vec<4> old_dcurv,
+ const vec &new_u, const vec &new_v,
+ Vec<4> &new_dcurv);
+
+// Create an offset surface from a mesh
+extern void inflate(TriMesh *mesh, float amount);
+
+// Transform the mesh by the given matrix
+extern void apply_xform(TriMesh *mesh, const xform &xf);
+
+// Translate the mesh
+extern void trans(TriMesh *mesh, const vec &transvec);
+
+// Rotate the mesh by r radians
+extern void rot(TriMesh *mesh, float r, const vec &axis);
+
+// Scale the mesh - isotropic
+extern void scale(TriMesh *mesh, float s);
+
+// Scale the mesh - anisotropic in X, Y, Z
+extern void scale(TriMesh *mesh, float sx, float sy, float sz);
+
+// Scale the mesh - anisotropic in an arbitrary direction
+extern void scale(TriMesh *mesh, float s, const vec &d);
+
+// Clip mesh to the given bounding box
+extern void clip(TriMesh *mesh, const TriMesh::BBox &b);
+
+// Find center of mass of a bunch of points
+extern point point_center_of_mass(const vector<point> &pts);
+
+// Find (area-weighted) center of mass of a mesh
+extern point mesh_center_of_mass(TriMesh *mesh);
+
+// Compute covariance of a bunch of points
+extern void point_covariance(const vector<point> &pts, float C[3][3]);
+
+// Compute covariance of faces (area-weighted) in a mesh
+extern void mesh_covariance(TriMesh *mesh, float C[3][3]);
+
+// Scale the mesh so that mean squared distance from center of mass is 1
+extern void normalize_variance(TriMesh *mesh);
+
+// Rotate model so that first principal axis is along +X (using
+// forward weighting), and the second is along +Y
+extern void pca_rotate(TriMesh *mesh);
+
+// As above, but only rotate by 90/180/etc. degrees w.r.t. original
+extern void pca_snap(TriMesh *mesh);
+
+// Flip faces so that orientation among touching faces is consistent
+extern void orient(TriMesh *mesh);
+
+// Remove boundary vertices (and faces that touch them)
+extern void erode(TriMesh *mesh);
+
+// Add a bit of noise to the mesh
+extern void noisify(TriMesh *mesh, float amount);
+
+#endif
Index: external/trimesh/include/Vec.h
--- external/trimesh/include/Vec.h (revision 0)
+++ external/trimesh/include/Vec.h (revision 0)
@@ -0,0 +1,459 @@
+#ifndef VEC_H
+#define VEC_H
+/*
+Szymon Rusinkiewicz
+Princeton University
+
+Vec.h
+Class for a constant-length vector
+
+Supports the following operations:
+ vec v1; // Initialized to (0,0,0)
+ vec v2(1,2,3); // Initializes the 3 components
+ vec v3(v2); // Copy constructor
+ float farray[3];
+ vec v4 = vec(farray); // Explicit: "v4 = farray" won't work
+ Vec<3,double> vd; // The "vec" used above is Vec<3,float>
+ point p1, p2, p3; // Same as vec
+
+ v3 = v1 + v2; // Also -, *, / (all componentwise)
+ v3 = 3.5f * v1; // Also vec * scalar, vec / scalar
+ // NOTE: scalar has to be the same type:
+ // it won't work to do double * vec<float>
+
+ v3 = v1 DOT v2; // Actually operator^
+ v3 = v1 CROSS v2; // Actually operator%
+
+ float f = v1[0]; // Subscript
+ float *fp = v1; // Implicit conversion to float *
+
+ f = len(v1); // Length (also len2 == squared length)
+ f = dist(p1, p2); // Distance (also dist2 == squared distance)
+ normalize(v1); // Normalize (i.e., make it unit length)
+ // normalize(vec(0,0,0)) => vec(1,0,0)
+
+ cout << v1 << endl; // iostream output in the form (1,2,3)
+ cin >> v2; // iostream input using the same syntax
+
+Also defines the utility functions sqr, cube, sgn, swap,
+fract, clamp, mix, step, smoothstep, and trinorm
+*/
+
+
+// Windows defines these as macros, which prevents us from using the
+// type-safe versions from std::, as well as interfering with method defns
+#undef min
+#undef max
+
+
+#include <cmath>
+#include <iostream>
+#include <algorithm>
+using std::min;
+using std::max;
+using std::swap;
+using std::sqrt;
+
+
+// Let gcc optimize conditional branches a bit better...
+#ifndef likely
+# if !defined(__GNUC__) || (__GNUC__ == 2 && __GNUC_MINOR__ < 96)
+# define likely(x) (x)
+# define unlikely(x) (x)
+# else
+# define likely(x) (__builtin_expect((x), 1))
+# define unlikely(x) (__builtin_expect((x), 0))
+# endif
+#endif
+
+
+// Boost-like compile-time assertion checking
+template <bool X> struct VEC_STATIC_ASSERTION_FAILURE;
+template <> struct VEC_STATIC_ASSERTION_FAILURE<true>
+ { void operator () () {} };
+#define VEC_STATIC_CHECK(expr) VEC_STATIC_ASSERTION_FAILURE<bool(expr)>()
+
+
+template <int D, class T = float>
+class Vec {
+private:
+ T v[D];
+
+public:
+ // Constructor for no arguments. Everything initialized to 0.
+ Vec() { for (int i = 0; i < D; i++) v[i] = T(0); }
+
+ // Constructors for 2-4 arguments
+ Vec(T x, T y)
+ { VEC_STATIC_CHECK(D == 2); v[0] = x; v[1] = y; }
+ Vec(T x, T y, T z)
+ { VEC_STATIC_CHECK(D == 3); v[0] = x; v[1] = y; v[2] = z; }
+ Vec(T x, T y, T z, T w)
+ { VEC_STATIC_CHECK(D == 4); v[0] = x; v[1] = y; v[2] = z; v[3] = w; }
+
+ // Constructor from anything that can be accessed using []
+ // This one's pretty aggressive, so marked explicit
+ template <class S> explicit Vec(const S &x)
+ { for (int i = 0; i < D; i++) v[i] = T(x[i]); }
+
+ // No destructor or assignment operator needed
+
+ // Array reference and conversion to pointer - no bounds checking
+ const T &operator [] (int i) const
+ { return v[i]; }
+ T &operator [] (int i)
+ { return v[i]; }
+ operator const T * () const
+ { return v; }
+ operator const T * ()
+ { return v; }
+ operator T * ()
+ { return v; }
+
+ // Member operators
+ Vec<D,T> &operator += (const Vec<D,T> &x)
+ { for (int i = 0; i < D; i++) v[i] += x[i]; return *this; }
+ Vec<D,T> &operator -= (const Vec<D,T> &x)
+ { for (int i = 0; i < D; i++) v[i] -= x[i]; return *this; }
+ Vec<D,T> &operator *= (const Vec<D,T> &x)
+ { for (int i = 0; i < D; i++) v[i] *= x[i]; return *this; }
+ Vec<D,T> &operator *= (const T &x)
+ { for (int i = 0; i < D; i++) v[i] *= x; return *this; }
+ Vec<D,T> &operator /= (const Vec<D,T> &x)
+ { for (int i = 0; i < D; i++) v[i] /= x[i]; return *this; }
+ Vec<D,T> &operator /= (const T &x)
+ { for (int i = 0; i < D; i++) v[i] /= x; return *this; }
+
+ // Outside of class: + - * / % ^ << >>
+
+ // Some partial compatibility with valarrays and vectors
+ typedef T value_type;
+ size_t size() const
+ { return D; }
+ T sum() const
+ { T total = v[0];
+ for (int i = 1; i < D; i++) total += v[i];
+ return total; }
+ T avg() const
+ { return sum() / D; }
+ T product() const
+ { T total = v[0];
+ for (int i = 1; i < D; i++) total *= v[i];
+ return total; }
+ T min() const
+ { T m = v[0];
+ for (int i = 0; i < D; i++)
+ if (v[i] < m) m = v[i];
+ return m; }
+ T max() const
+ { T m = v[0];
+ for (int i = 1; i < D; i++)
+ if (v[i] > m) m = v[i];
+ return m; }
+ T *begin() { return &(v[0]); }
+ const T *begin() const { return &(v[0]); }
+ T *end() { return begin() + D; }
+ const T *end() const { return begin() + D; }
+ void clear() { for (int i = 0; i < D; i++) v[i] = T(0); }
+ bool empty() const
+ { for (int i = 0; i < D; i++)
+ if (v[i]) return false;
+ return true; }
+};
+
+typedef Vec<3,float> vec;
+typedef Vec<3,float> point;
+typedef Vec<2,float> vec2;
+typedef Vec<3,float> vec3;
+typedef Vec<4,float> vec4;
+typedef Vec<2,int> ivec2;
+typedef Vec<3,int> ivec3;
+typedef Vec<4,int> ivec4;
+
+
+// Nonmember operators that take two Vecs
+template <int D, class T>
+static inline const Vec<D,T> operator + (const Vec<D,T> &v1, const
Vec<D,T> &v2)
+{
+ return Vec<D,T>(v1) += v2;
+}
+
+template <int D, class T>
+static inline const Vec<D,T> operator - (const Vec<D,T> &v1, const
Vec<D,T> &v2)
+{
+ return Vec<D,T>(v1) -= v2;
+}
+
+template <int D, class T>
+static inline const Vec<D,T> operator * (const Vec<D,T> &v1, const
Vec<D,T> &v2)
+{
+ return Vec<D,T>(v1) *= v2;
+}
+
+template <int D, class T>
+static inline const Vec<D,T> operator / (const Vec<D,T> &v1, const
Vec<D,T> &v2)
+{
+ return Vec<D,T>(v1) /= v2;
+}
+
+template <int D, class T>
+static inline const T operator ^ (const Vec<D,T> &v1, const Vec<D,T>
&v2)
+{
+ T sum = v1[0] * v2[0];
+ for (int i = 1; i < D; i++)
+ sum += v1[i] * v2[i];
+ return sum;
+}
+#define DOT ^
+
+template <class T>
+static inline const Vec<3,T> operator % (const Vec<3,T> &v1, const
Vec<3,T> &v2)
+{
+ return Vec<3,T>(v1[1]*v2[2] - v1[2]*v2[1],
+ v1[2]*v2[0] - v1[0]*v2[2],
+ v1[0]*v2[1] - v1[1]*v2[0]);
+}
+#define CROSS %
+
+
+// Component-wise equality and inequality (#include the usual caveats
+// about comparing floats for equality...)
+template <int D, class T>
+static inline bool operator == (const Vec<D,T> &v1, const Vec<D,T>
&v2)
+{
+ for (int i = 0; i < D; i++)
+ if (v1[i] != v2[i])
+ return false;
+ return true;
+}
+
+template <int D, class T>
+static inline bool operator != (const Vec<D,T> &v1, const Vec<D,T>
&v2)
+{
+ for (int i = 0; i < D; i++)
+ if (v1[i] != v2[i])
+ return true;
+ return false;
+}
+
+
+// Unary operators
+template <int D, class T>
+static inline const Vec<D,T> &operator + (const Vec<D,T> &v)
+{
+ return v;
+}
+
+template <int D, class T>
+static inline const Vec<D,T> operator - (const Vec<D,T> &v)
+{
+ Vec<D,T> result(v);
+ for (int i = 0; i < D; i++)
+ result[i] = -result[i];
+ return result;
+}
+
+template <int D, class T>
+static inline bool operator ! (const Vec<D,T> &v)
+{
+ return v.empty();
+}
+
+
+// Vec/scalar operators
+template <int D, class T>
+static inline const Vec<D,T> operator * (const T &x, const Vec<D,T>
&v)
+{
+ Vec<D,T> result(v);
+ for (int i = 0; i < D; i++)
+ result[i] = x * result[i];
+ return result;
+}
+
+template <int D, class T>
+static inline const Vec<D,T> operator * (const Vec<D,T> &v, const T
&x)
+{
+ return Vec<D,T>(v) *= x;
+}
+
+template <int D, class T>
+static inline const Vec<D,T> operator / (const T &x, const Vec<D,T>
&v)
+{
+ Vec<D,T> result(v);
+ for (int i = 0; i < D; i++)
+ result[i] = x / result[i];
+ return result;
+}
+
+template <int D, class T>
+static inline const Vec<D,T> operator / (const Vec<D,T> &v, const T
&x)
+{
+ return Vec<D,T>(v) /= x;
+}
+
+
+// iostream operators
+template <int D, class T>
+static inline std::ostream &operator << (std::ostream &os, const
Vec<D,T> &v)
+
+{
+ os << "(";
+ for (int i = 0; i < D-1; i++)
+ os << v[i] << ", ";
+ return os << v[D-1] << ")";
+}
+
+template <int D, class T>
+static inline std::istream &operator >> (std::istream &is, Vec<D,T>
&v)
+{
+ char c1 = 0, c2 = 0;
+
+ is >> c1;
+ if (c1 == '(' || c1 == '[') {
+ is >> v[0] >> std::ws >> c2;
+ for (int i = 1; i < D; i++) {
+ if (c2 == ',')
+ is >> v[i] >> std::ws >> c2;
+ else
+ is.setstate(std::ios::failbit);
+ }
+ }
+
+ if (c1 == '(' && c2 != ')')
+ is.setstate(std::ios::failbit);
+ else if (c1 == '[' && c2 != ']')
+ is.setstate(std::ios::failbit);
+
+ return is;
+}
+
+
+// Utility functions for square and cube, to go along with sqrt and cbrt
+template <class T>
+static inline T sqr(const T &x)
+{
+ return x*x;
+}
+
+template <class T>
+static inline T cube(const T &x)
+{
+ return x*x*x;
+}
+
+
+// Utility functions based on GLSL
+template <class T>
+static inline T fract(const T &x)
+{
+ return x - floor(x);
+}
+
+template <class T>
+static inline T clamp(const T &x, const T &a, const T &b)
+{
+ return x > a ? x < b ? x : b : a; // returns a on NaN
+}
+
+template <class T, class S>
+static inline T mix(const T &x, const T &y, const S &a)
+{
+ return (S(1)-a) * x + a * y;
+}
+
+template <class T>
+static inline T step(const T &x, const T &a)
+{
+ return x < a ? T(0) : T(1);
+}
+
+template <class T>
+static inline T smoothstep(const T &x, const T &a, const T &b)
+{
+ if (b <= a) return step(x,a);
+ T t = (x - a) / (b - a);
+ return t <= T(0) ? T(0) : t >= T(1) ? T(1) : t * t * (T(3) - T(2) * t);
+}
+
+// Area-weighted triangle face normal
+template <class T>
+static inline T trinorm(const T &v0, const T &v1, const T &v2)
+{
+ return (typename T::value_type) 0.5 * ((v1 - v0) CROSS (v2 - v0));
+}
+
+// Sign of a scalar
+template <class T>
+static inline T sgn(const T &x)
+{
+ return (x < T(0)) ? T(-1) : T(1);
+}
+
+
+// Functions on Vecs
+template <int D, class T>
+static inline const T len2(const Vec<D,T> &v)
+{
+ T l2 = v[0] * v[0];
+ for (int i = 1; i < D; i++)
+ l2 += v[i] * v[i];
+ return l2;
+}
+
+template <int D, class T>
+static inline const T len(const Vec<D,T> &v)
+{
+ return sqrt(len2(v));
+}
+
+template <int D, class T>
+static inline const T dist2(const Vec<D,T> &v1, const Vec<D,T> &v2)
+{
+ T d2 = sqr(v2[0]-v1[0]);
+ for (int i = 1; i < D; i++)
+ d2 += sqr(v2[i]-v1[i]);
+ return d2;
+}
+
+template <int D, class T>
+static inline const T dist(const Vec<D,T> &v1, const Vec<D,T> &v2)
+{
+ return sqrt(dist2(v1,v2));
+}
+
+template <int D, class T>
+static inline Vec<D,T> normalize(Vec<D,T> &v)
+{
+ T l = len(v);
+ if (unlikely(l <= T(0))) {
+ v[0] = T(1);
+ for (int i = 1; i < D; i++)
+ v[i] = T(0);
+ return v;
+ }
+
+ l = T(1) / l;
+ for (int i = 0; i < D; i++)
+ v[i] *= l;
+
+ return v;
+}
+
+template <int D, class T>
+static inline void swap(const Vec<D,T> &v1, const Vec<D,T> &v2)
+{
+ for (int i = 0; i < D; i++)
+ swap(v1[i], v2[i]);
+}
+
+template <int D, class T>
+static inline Vec<D,T> fabs(const Vec<D,T> &v)
+{
+ Vec<D,T> result(v);
+ for (int i = 0; i < D; i++)
+ if (result[i] < T(0))
+ result[i] = -result[i];
+ return result;
+}
+
+#endif
Index: external/trimesh/include/Color.h
--- external/trimesh/include/Color.h (revision 0)
+++ external/trimesh/include/Color.h (revision 0)
@@ -0,0 +1,107 @@
+#ifndef COLOR_H
+#define COLOR_H
+/*
+Szymon Rusinkiewicz
+Princeton University
+
+Color.h
+Random class for encapsulating colors...
+*/
+
+#include "Vec.h"
+#include <cmath>
+#include <algorithm>
+using std::fmod;
+using std::floor;
+using std::min;
+using std::max;
+#ifndef M_PI
+# define M_PI 3.14159265358979323846
+#endif
+
+
+class Color : public Vec<3,float> {
+public:
+ Color()
+ {}
+ Color(const Vec<3,float> &v_) : Vec<3,float>(v_)
+ {}
+ Color(const Vec<3,double> &v_) : Vec<3,float>((float)v_[0],
(float)v_[1], (float)v_[2])
+ {}
+ Color(float r, float g, float b) : Vec<3,float>(r,g,b)
+ {}
+ Color(double r, double g, double b) : Vec<3,float>((float)r, (float)g, (float)b)
+ {}
+ explicit Color(const float *rgb) : Vec<3,float>(rgb[0], rgb[1], rgb[2])
+ {}
+ explicit Color(const double *rgb) : Vec<3,float>((float)rgb[0], (float)rgb[1],
(float)rgb[2])
+ {}
+
+ // Implicit conversion from float would be bad, so we have an
+ // explicit constructor and an assignment statement.
+ explicit Color(float c) : Vec<3,float>(c,c,c)
+ {}
+ explicit Color(double c) : Vec<3,float>((float)c, (float)c, (float)c)
+ {}
+ Color &operator = (float c)
+ { return *this = Color(c); }
+ Color &operator = (double c)
+ { return *this = Color(c); }
+
+ // Assigning from ints divides by 255
+ Color(int r, int g, int b)
+ {
+ const float mult = 1.0f / 255.0f;
+ *this = Color(mult*r, mult*g, mult*b);
+ }
+ explicit Color(const int *rgb)
+ { *this = Color(rgb[0], rgb[1], rgb[2]); }
+ explicit Color(const unsigned char *rgb)
+ { *this = Color(rgb[0], rgb[1], rgb[2]); }
+ explicit Color(int c)
+ { *this = Color(c,c,c); }
+ Color &operator = (int c)
+ { return *this = Color(c); }
+
+ static Color black()
+ { return Color(0.0f, 0.0f, 0.0f); }
+ static Color white()
+ { return Color(1.0f, 1.0f, 1.0f); }
+ static Color red()
+ { return Color(1.0f, 0.0f, 0.0f); }
+ static Color green()
+ { return Color(0.0f, 1.0f, 0.0f); }
+ static Color blue()
+ { return Color(0.0f, 0.0f, 1.0f); }
+ static Color yellow()
+ { return Color(1.0f, 1.0f, 0.0f); }
+ static Color cyan()
+ { return Color(0.0f, 1.0f, 1.0f); }
+ static Color magenta()
+ { return Color(1.0f, 0.0f, 1.0f); }
+ static Color hsv(float h, float s, float v)
+ {
+ // From FvD
+ if (s <= 0.0f)
+ return Color(v,v,v);
+ h = fmod(h, float(2.0f * M_PI));
+ if (h < 0.0)
+ h += (float)(2.0 * M_PI);
+ h /= (float)(M_PI / 3.0);
+ int i = int(floor(h));
+ float f = h - i;
+ float p = v * (1.0f - s);
+ float q = v * (1.0f - (s*f));
+ float t = v * (1.0f - (s*(1.0f-f)));
+ switch(i) {
+ case 0: return Color(v, t, p);
+ case 1: return Color(q, v, p);
+ case 2: return Color(p, v, t);
+ case 3: return Color(p, q, v);
+ case 4: return Color(t, p, v);
+ default: return Color(v, p, q);
+ }
+ }
+};
+
+#endif
Index: external/trimesh/include/KDtree.h
--- external/trimesh/include/KDtree.h (revision 0)
+++ external/trimesh/include/KDtree.h (revision 0)
@@ -0,0 +1,46 @@
+#ifndef KDTREE_H
+#define KDTREE_H
+/*
+Szymon Rusinkiewicz
+Princeton University
+
+KDtree.h
+A K-D tree for points, with limited capabilities (find nearest point to
+a given point, or to a ray).
+*/
+
+#include <vector>
+
+class KDtree {
+private:
+ class Node;
+ Node *root;
+ void build(const float *ptlist, int n);
+
+public:
+ // Compatibility function for closest-compatible-point searches
+ struct CompatFunc
+ {
+ virtual bool operator () (const float *p) const = 0;
+ virtual ~CompatFunc() {} // To make the compiler shut up
+ };
+
+ // Constructor from an array of points
+ KDtree(const float *ptlist, int n)
+ { build(ptlist, n); }
+ // Constructor from a vector of points
+ template <class T> KDtree(const std::vector<T> &v)
+ { build((const float *) &v[0], v.size()); }
+ ~KDtree();
+
+ // The queries: returns closest point to a point or a ray,
+ // provided it's within sqrt(maxdist2) and is compatible
+ const float *closest_to_pt(const float *p,
+ float maxdist2,
+ const CompatFunc *iscompat = NULL) const;
+ const float *closest_to_ray(const float *p, const float *dir,
+ float maxdist2,
+ const CompatFunc *iscompat = NULL) const;
+};
+
+#endif
Index: external/trimesh/include/timestamp.h
--- external/trimesh/include/timestamp.h (revision 0)
+++ external/trimesh/include/timestamp.h (revision 0)
@@ -0,0 +1,69 @@
+#ifndef TIMESTAMP_H
+#define TIMESTAMP_H
+/*
+Szymon Rusinkiewicz
+Princeton University
+
+timestamp.h
+Wrapper around system-specific timestamps.
+*/
+
+
+#ifdef WIN32
+
+# define WIN32_LEAN_AND_MEAN
+# include <limits.h>
+# include <windows.h>
+# define usleep(x) Sleep((x)/1000)
+
+ struct timestamp { LARGE_INTEGER t; };
+
+ static inline double LI2d(const LARGE_INTEGER &li)
+ {
+ // Work around random compiler bugs...
+ double d = *(unsigned *)(&(li.HighPart));
+ d *= 65536.0 * 65536.0;
+ d += *(unsigned *)(&(li.LowPart));
+ return d;
+ }
+
+ static inline float operator - (const timestamp &t1, const timestamp &t2)
+ {
+ static LARGE_INTEGER PerformanceFrequency;
+ static int status = QueryPerformanceFrequency(&PerformanceFrequency);
+ if (status == 0) return 1.0f;
+
+ return float((LI2d(t1.t) - LI2d(t2.t)) / LI2d(PerformanceFrequency));
+ }
+
+ static inline timestamp now()
+ {
+ timestamp t;
+ QueryPerformanceCounter(&t.t);
+ return t;
+ }
+
+#else
+
+# include <sys/time.h>
+# include <unistd.h>
+
+ typedef struct timeval timestamp;
+
+ static inline float operator - (const timestamp &t1, const timestamp &t2)
+ {
+ return (float)(t1.tv_sec - t2.tv_sec) +
+ 1.0e-6f*(t1.tv_usec - t2.tv_usec);
+ }
+
+ static inline timestamp now()
+ {
+ timestamp t;
+ gettimeofday(&t, 0);
+ return t;
+ }
+
+#endif
+
+
+#endif
Index: external/trimesh/include/noise3d.h
--- external/trimesh/include/noise3d.h (revision 0)
+++ external/trimesh/include/noise3d.h (revision 0)
@@ -0,0 +1,127 @@
+#ifndef NOISE3D_H
+#define NOISE3D_H
+/*
+Szymon Rusinkiewicz
+Princeton University
+
+noise3d.h
+A class for 3-D noise functions, including white noise and 1/f noise
+*/
+
+#include <math.h>
+#include <algorithm>
+#include <vector>
+using std::max;
+using std::swap;
+using std::vector;
+
+
+// Quick 'n dirty portable random number generator
+static inline float tinyrnd()
+{
+ static unsigned trand = 0;
+ trand = 1664525u * trand + 1013904223u;
+ return (float) trand / 4294967296.0f;
+}
+
+
+class Noise3D {
+public:
+ int xsize, ysize, zsize;
+ vector<float> r;
+ vector<int> p;
+
+ int coord2index(int x, int y, int z) const
+ {
+ return p[ p[x] + y ] + z;
+ }
+
+
+ Noise3D(int _xsize, int _ysize, int _zsize) :
+ xsize(_xsize), ysize(_ysize), zsize(_zsize)
+ {
+ if (xsize < 2)
+ xsize = 2;
+ if (ysize < 2)
+ ysize = 2;
+ if (zsize < 2)
+ ysize = 2;
+
+ int i;
+ int pxy = max(xsize, ysize);
+ for (i = 0; i < pxy; i++)
+ p.push_back(i);
+ for (i = 0; i < pxy; i++) {
+ int j = int(tinyrnd()*pxy);
+ swap(p[i], p[j]);
+ }
+ for (i = pxy; i < pxy+ysize; i++)
+ p.push_back(p[i-pxy]);
+ for (i = 0; i < pxy + zsize; i++)
+ r.push_back(tinyrnd());
+ }
+
+ virtual float lookup(float x, float y, float z) const
+ {
+ x -= floor(x);
+ y -= floor(y);
+ z -= floor(z);
+
+ int X = int(x*xsize);
+ int Y = int(y*ysize);
+ int Z = int(z*zsize);
+ int X1 = X+1; if (X1 == xsize) X1 = 0;
+ int Y1 = Y+1; if (Y1 == ysize) Y1 = 0;
+ int Z1 = Z+1; if (Z1 == zsize) Z1 = 0;
+
+ float xf = x*xsize - X, xf1 = 1.0-xf;
+ float yf = y*ysize - Y, yf1 = 1.0-yf;
+ float zf = z*zsize - Z, zf1 = 1.0-zf;
+
+ return xf1*(yf1*(zf1*r[coord2index(X , Y , Z )] +
+ zf *r[coord2index(X , Y , Z1)]) +
+ yf *(zf1*r[coord2index(X , Y1, Z )] +
+ zf *r[coord2index(X , Y1, Z1)])) +
+ xf *(yf1*(zf1*r[coord2index(X1, Y , Z )] +
+ zf *r[coord2index(X1, Y , Z1)]) +
+ yf *(zf1*r[coord2index(X1, Y1, Z )] +
+ zf *r[coord2index(X1, Y1, Z1)]));
+ }
+
+ virtual ~Noise3D() {}
+};
+
+
+#define MAGIC_SCALE 1.5707963f
+
+class PerlinNoise3D : public Noise3D {
+ int passes;
+ float correction;
+public:
+ PerlinNoise3D(int _xsize, int _ysize, int _zsize) :
+ Noise3D(_xsize, _ysize, _zsize), correction(0)
+ {
+ passes = int(log((float)xsize)/log(MAGIC_SCALE) + 0.5);
+ passes = max(passes, int(log((float)ysize)/log(MAGIC_SCALE) + 0.5));
+ passes = max(passes, int(log((float)zsize)/log(MAGIC_SCALE) + 0.5));
+ float factor = 1.0;
+ for (int pass = 0 ; pass < passes; pass++, factor *= MAGIC_SCALE)
+ correction += factor*factor;
+ correction = 1.0f / sqrt(correction);
+ }
+
+ virtual float lookup(float x, float y, float z) const
+ {
+ float t = 0;
+ float factor = 1.0;
+ for (int pass = 0 ; pass < passes; pass++, factor *= MAGIC_SCALE) {
+ float r = 1.0f / factor;
+ t += Noise3D::lookup(x*r,y*r,z*r) * factor;
+ }
+
+ return t * correction;
+ }
+};
+
+
+#endif
Index: external/trimesh/include/lineqn.h
--- external/trimesh/include/lineqn.h (revision 0)
+++ external/trimesh/include/lineqn.h (revision 0)
@@ -0,0 +1,358 @@
+#ifndef LINEQN_H
+#define LINEQN_H
+/*
+Szymon Rusinkiewicz
+Princeton University
+
+lineqn.h
+Solution of systems of linear equations and eigenvalue decomposition.
+Some are patterned after the code in Numerical Recipes, but with a bit of
+the fancy C++ template thing happening.
+*/
+
+#include <cmath>
+#include <algorithm>
+using std::sqrt;
+using std::fabs;
+
+#ifndef likely
+# if !defined(__GNUC__) || (__GNUC__ == 2 && __GNUC_MINOR__ < 96)
+# define likely(x) (x)
+# define unlikely(x) (x)
+# else
+# define likely(x) (__builtin_expect((x), 1))
+# define unlikely(x) (__builtin_expect((x), 0))
+# endif
+#endif
+
+
+// LU decomposition
+template <class T, int N>
+static inline bool ludcmp(T a[N][N], int indx[N], T *d = NULL)
+{
+ int i, j, k;
+ T vv[N];
+
+ if (d)
+ *d = 1;
+ for (i = 0; i < N; i++) {
+ T big = 0.0;
+ for (j = 0; j < N; j++) {
+ T tmp = fabs(a[i][j]);
+ if (tmp > big)
+ big = tmp;
+ }
+ if (big == 0.0)
+ return false;
+ vv[i] = 1.0 / big;
+ }
+ for (j = 0; j < N; j++) {
+ for (i = 0; i < j; i++) {
+ T sum = a[i][j];
+ for (k = 0; k < i; k++)
+ sum -= a[i][k]*a[k][j];
+ a[i][j]=sum;
+ }
+ T big = 0.0;
+ int imax = j;
+ for (i = j; i < N; i++) {
+ T sum = a[i][j];
+ for (k = 0; k < j; k++)
+ sum -= a[i][k]*a[k][j];
+ a[i][j] = sum;
+ T tmp = vv[i] * fabs(sum);
+ if (tmp > big) {
+ big = tmp;
+ imax = i;
+ }
+ }
+ if (imax != j) {
+ for (k = 0; k < N; k++)
+ std::swap(a[imax][k], a[j][k]);
+ if (d)
+ *d = -(*d);
+ vv[imax] = vv[j];
+ }
+ indx[j] = imax;
+ if (a[j][j] == 0.0)
+ return false;
+ if (j != N-1) {
+ T tmp = 1.0/(a[j][j]);
+ for (i = j+1; i < N; i++)
+ a[i][j] *= tmp;
+ }
+ }
+ return true;
+}
+
+
+// Backsubstitution after ludcmp
+template <class T, int N>
+static inline void lubksb(T a[N][N], int indx[N], T b[N])
+{
+ int ii = -1, i, j;
+ for (i = 0; i < N; i++) {
+ int ip = indx[i];
+ T sum = b[ip];
+ b[ip] = b[i];
+ if (ii != -1)
+ for (j = ii; j < i; j++)
+ sum -= a[i][j] * b[j];
+ else if (sum)
+ ii = i;
+ b[i] = sum;
+ }
+ for (i = N-1; i >= 0; i--) {
+ T sum = b[i];
+ for (j = i+1; j < N; j++)
+ sum -= a[i][j] * b[j];
+ b[i] = sum / a[i][i];
+ }
+}
+
+
+// Perform LDL^T decomposition of a symmetric positive definite matrix.
+// Like Cholesky, but no square roots. Overwrites lower triangle of matrix.
+template <class T, int N>
+static inline bool ldltdc(T A[N][N], T rdiag[N])
+{
+ T v[N-1];
+ for (int i = 0; i < N; i++) {
+ for (int k = 0; k < i; k++)
+ v[k] = A[i][k] * rdiag[k];
+ for (int j = i; j < N; j++) {
+ T sum = A[i][j];
+ for (int k = 0; k < i; k++)
+ sum -= v[k] * A[j][k];
+ if (i == j) {
+ if (unlikely(sum <= T(0)))
+ return false;
+ rdiag[i] = T(1) / sum;
+ } else {
+ A[j][i] = sum;
+ }
+ }
+ }
+
+ return true;
+}
+
+
+// Solve Ax=B after ldltdc
+template <class T, int N>
+static inline void ldltsl(T A[N][N], T rdiag[N], T B[N], T x[N])
+{
+ int i;
+ for (i = 0; i < N; i++) {
+ T sum = B[i];
+ for (int k = 0; k < i; k++)
+ sum -= A[i][k] * x[k];
+ x[i] = sum * rdiag[i];
+ }
+ for (i = N - 1; i >= 0; i--) {
+ T sum = 0;
+ for (int k = i + 1; k < N; k++)
+ sum += A[k][i] * x[k];
+ x[i] -= sum * rdiag[i];
+ }
+}
+
+
+// Eigenvector decomposition for real, symmetric matrices,
+// a la Bowdler et al. / EISPACK / JAMA
+// Entries of d are eigenvalues, sorted smallest to largest.
+// A changed in-place to have its columns hold the corresponding eigenvectors.
+// Note that A must be completely filled in on input.
+template <class T, int N>
+static inline void eigdc(T A[N][N], T d[N])
+{
+ // Householder
+ T e[N];
+ for (int j = 0; j < N; j++) {
+ d[j] = A[N-1][j];
+ e[j] = 0.0;
+ }
+ for (int i = N-1; i > 0; i--) {
+ T scale = 0.0;
+ for (int k = 0; k < i; k++)
+ scale += std::fabs(d[k]);
+ if (scale == 0.0) {
+ e[i] = d[i-1];
+ for (int j = 0; j < i; j++) {
+ d[j] = A[i-1][j];
+ A[i][j] = A[j][i] = 0.0;
+ }
+ d[i] = 0.0;
+ } else {
+ T h(0);
+ T invscale = T(1.0 / scale);
+ for (int k = 0; k < i; k++) {
+ d[k] *= invscale;
+ h += sqr(d[k]);
+ }
+ T f = d[i-1];
+ T g = (f > 0.0) ? -std::sqrt(h) : std::sqrt(h);
+ e[i] = scale * g;
+ h -= f * g;
+ d[i-1] = f - g;
+ for (int j = 0; j < i; j++)
+ e[j] = 0.0;
+ for (int j = 0; j < i; j++) {
+ f = d[j];
+ A[j][i] = f;
+ g = e[j] + f * A[j][j];
+ for (int k = j+1; k < i; k++) {
+ g += A[k][j] * d[k];
+ e[k] += A[k][j] * f;
+ }
+ e[j] = g;
+ }
+ f = 0.0;
+ T invh = T(1.0 / h);
+ for (int j = 0; j < i; j++) {
+ e[j] *= invh;
+ f += e[j] * d[j];
+ }
+ T hh = f / (h + h);
+ for (int j = 0; j < i; j++)
+ e[j] -= hh * d[j];
+ for (int j = 0; j < i; j++) {
+ f = d[j];
+ g = e[j];
+ for (int k = j; k < i; k++)
+ A[k][j] -= f * e[k] + g * d[k];
+ d[j] = A[i-1][j];
+ A[i][j] = 0.0;
+ }
+ d[i] = h;
+ }
+ }
+
+ for (int i = 0; i < N-1; i++) {
+ A[N-1][i] = A[i][i];
+ A[i][i] = 1.0;
+ T h = d[i+1];
+ if (h != 0.0) {
+ T invh = T(1.0 / h);
+ for (int k = 0; k <= i; k++)
+ d[k] = A[k][i+1] * invh;
+ for (int j = 0; j <= i; j++) {
+ T g = 0.0;
+ for (int k = 0; k <= i; k++)
+ g += A[k][i+1] * A[k][j];
+ for (int k = 0; k <= i; k++)
+ A[k][j] -= g * d[k];
+ }
+ }
+ for (int k = 0; k <= i; k++)
+ A[k][i+1] = 0.0;
+ }
+ for (int j = 0; j < N; j++) {
+ d[j] = A[N-1][j];
+ A[N-1][j] = 0.0;
+ }
+ A[N-1][N-1] = 1.0;
+
+ // QL
+ for (int i = 1; i < N; i++)
+ e[i-1] = e[i];
+ e[N-1] = 0.0;
+ T f = 0.0, tmp = 0.0;
+ const T eps = T(pow(2.0, -52.0));
+ for (int l = 0; l < N; l++) {
+ tmp = std::max(tmp, std::fabs(d[l]) + std::fabs(e[l]));
+ int m = l;
+ while (m < N) {
+ if (std::fabs(e[m]) <= eps * tmp)
+ break;
+ m++;
+ }
+ if (m > l) {
+ do {
+ T g = d[l];
+ T p = (d[l+1] - g) / (e[l] + e[l]);
+ T r = T(hypot(p, 1.0));
+ if (p < 0.0)
+ r = -r;
+ d[l] = e[l] / (p + r);
+ d[l+1] = e[l] * (p + r);
+ T dl1 = d[l+1];
+ T h = g - d[l];
+ for (int i = l+2; i < N; i++)
+ d[i] -= h;
+ f += h;
+ p = d[m];
+ T c = 1.0, c2 = 1.0, c3 = 1.0;
+ T el1 = e[l+1], s = 0.0, s2 = 0.0;
+ for (int i = m - 1; i >= l; i--) {
+ c3 = c2;
+ c2 = c;
+ s2 = s;
+ g = c * e[i];
+ h = c * p;
+ r = T(hypot(p, e[i]));
+ e[i+1] = s * r;
+ s = e[i] / r;
+ c = p / r;
+ p = c * d[i] - s * g;
+ d[i+1] = h + s * (c * g + s * d[i]);
+ for (int k = 0; k < N; k++) {
+ h = A[k][i+1];
+ A[k][i+1] = s * A[k][i] + c * h;
+ A[k][i] = c * A[k][i] - s * h;
+ }
+ }
+ p = -s * s2 * c3 * el1 * e[l] / dl1;
+ e[l] = s * p;
+ d[l] = c * p;
+ } while (std::fabs(e[l]) > eps * tmp);
+ }
+ d[l] += f;
+ e[l] = 0.0;
+ }
+
+ // Sort
+ for (int i = 0; i < N-1; i++) {
+ int k = i;
+ T p = d[i];
+ for (int j = i+1; j < N; j++) {
+ if (d[j] < p) {
+ k = j;
+ p = d[j];
+ }
+ }
+ if (k == i)
+ continue;
+ d[k] = d[i];
+ d[i] = p;
+ for (int j = 0; j < N; j++) {
+ p = A[j][i];
+ A[j][i] = A[j][k];
+ A[j][k] = p;
+ }
+ }
+}
+
+
+// x <- A * d * A' * b
+template <class T, int N>
+static inline void eigmult(T A[N][N],
+ T d[N],
+ T b[N],
+ T x[N])
+{
+ T e[N];
+ for (int i = 0; i < N; i++) {
+ e[i] = 0.0;
+ for (int j = 0; j < N; j++)
+ e[i] += A[j][i] * b[j];
+ e[i] *= d[i];
+ }
+ for (int i = 0; i < N; i++) {
+ x[i] = 0.0;
+ for (int j = 0; j < N; j++)
+ x[i] += A[i][j] * e[j];
+ }
+}
+
+#endif
Index: external/trimesh/include/bsphere.h
--- external/trimesh/include/bsphere.h (revision 0)
+++ external/trimesh/include/bsphere.h (revision 0)
@@ -0,0 +1,273 @@
+#ifndef BSPHERE_H
+#define BSPHERE_H
+/*
+Szymon Rusinkiewicz
+Princeton University
+
+bsphere.h
+Bounding sphere computation, based on the "miniball" package by
+Bernd Gaertner, based on algorithms by Welzl and Gaertner. The
+original code is distributed under the GPL, and is available from
+http://www.inf.ethz.ch/personal/gaertner/miniball.html
+The original copyright notice can be found at the end of this file.
+*/
+
+
+#include "Vec.h"
+#include <list>
+
+
+// Class for a basis of points supporting a bounding sphere
+template<int D, class T>
+class Basis {
+private:
+ int m, s; // size and number of support points
+ T q0[D];
+
+ T z[D+1];
+ T f[D+1];
+ T v[D+1][D];
+ T a[D+1][D];
+
+ T c[D+1][D];
+ T sqr_r[D+1];
+
+ T *current_c; // points to some c[j]
+ T current_sqr_r;
+
+public:
+ const T *center() const { return current_c; }
+ T squared_radius() const { return current_sqr_r; }
+ int size() const { return m; }
+ T excess(const Vec<D,T> &p) const;
+ void reset(); // generates empty sphere with m=s=0
+ bool push(const Vec<D,T> &p);
+ void pop();
+};
+
+
+// Class for hoding and computing the bounding sphere
+template <int D, class T>
+class Miniball {
+public:
+ typedef typename std::list< Vec<D,T> >::iterator It;
+
+private:
+ std::list< Vec<D,T> > L;// STL list keeping the points
+ Basis<D,T> B; // basis keeping the current ball
+ It support_end; // past-the-end iterator of support set
+
+ void move_to_front(It j);
+ T max_excess(It t, It i, It &pivot) const;
+ void mtf_mb(It k);
+ void pivot_mb(It k);
+
+public:
+ void check_in(const Vec<D,T> &p) { L.push_back(p); }
+ template <class I>
+ void check_in(I first, I last) { L.insert(L.end(), first, last); }
+ void build(bool pivoting = true);
+ Vec<D,T> center() const { return Vec<D,T>(B.center()); }
+ T squared_radius() const { return B.squared_radius(); }
+};
+
+
+template <int D, class T>
+T Basis<D,T>::excess(const Vec<D,T> &p) const
+{
+ T e = -current_sqr_r;
+ for (int k = 0; k < D; k++)
+ e += sqr(p[k] - current_c[k]);
+ return e;
+}
+
+
+template <int D, class T>
+void Basis<D,T>::reset()
+{
+ m = s = 0;
+ // we misuse c[0] for the center of the empty sphere
+ for (int j = 0; j < D; j++)
+ c[0][j] = 0;
+ current_c = c[0];
+ current_sqr_r = -1;
+}
+
+
+template <int D, class T>
+bool Basis<D,T>::push(const Vec<D,T> &p)
+{
+ int i, j;
+ const T eps = T(1.0e-13);
+ if (m == 0) {
+ for (i = 0; i < D; i++)
+ q0[i] = p[i];
+ for (i = 0; i < D; i++)
+ c[0][i] = q0[i];
+ sqr_r[0] = 0;
+ } else {
+ // set v_m to Q_m
+ for (i = 0; i < D; i++)
+ v[m][i] = p[i] - q0[i];
+
+ // compute the a_{m,i}, i < m
+ for (i = 1; i < m; i++) {
+ a[m][i] = 0;
+ for (j = 0; j < D; j++)
+ a[m][i] += v[i][j] * v[m][j];
+ a[m][i] *= (T(2) / z[i]);
+ }
+
+ // update v_m to Q_m-\bar{Q}_m
+ for (i = 1; i < m; i++) {
+ for (j = 0; j < D; j++)
+ v[m][j] -= a[m][i] * v[i][j];
+ }
+
+ // compute z_m
+ z[m] = 0;
+ for (j = 0; j < D; j++)
+ z[m] += sqr(v[m][j]);
+ z[m] *= T(2);
+
+ // reject push if z_m too small
+ if (z[m] < eps*current_sqr_r)
+ return false;
+
+ // update c, sqr_r
+ T e = -sqr_r[m-1];
+ for (i = 0; i < D; i++)
+ e += sqr(p[i] - c[m-1][i]);
+ f[m] = e / z[m];
+
+ for (i = 0; i < D; i++)
+ c[m][i] = c[m-1][i] + f[m]*v[m][i];
+ sqr_r[m] = sqr_r[m-1] + e*f[m]*T(0.5);
+ }
+ current_c = c[m];
+ current_sqr_r = sqr_r[m];
+ s = ++m;
+ return true;
+}
+
+
+template <int D, class T>
+void Basis<D,T>::pop()
+{
+ m--;
+}
+
+
+template <int D, class T>
+void Miniball<D,T>::move_to_front(It j)
+{
+ if (support_end == j)
+ support_end++;
+ L.splice(L.begin(), L, j);
+}
+
+
+template <int D, class T>
+T Miniball<D,T>::max_excess(It t, It i, It &pivot) const
+{
+ const T *c = B.center(), sqr_r = B.squared_radius();
+ T e, max_e = 0;
+ for (It k = t; k != i; k++) {
+ const Vec<D,T> &p = *k;
+ e = -sqr_r;
+ for (int j = 0; j < D; j++)
+ e += sqr(p[j] - c[j]);
+ if (e > max_e) {
+ max_e = e;
+ pivot = k;
+ }
+ }
+ return max_e;
+}
+
+
+template <int D, class T>
+void Miniball<D,T>::mtf_mb(It i)
+{
+ support_end = L.begin();
+ if (B.size() == D+1)
+ return;
+ for (It k = L.begin(); k != i; ) {
+ It j = k++;
+ if (B.excess(*j) > 0) {
+ if (B.push(*j)) {
+ mtf_mb(j);
+ B.pop();
+ move_to_front(j);
+ }
+ }
+ }
+}
+
+
+template <int D, class T>
+void Miniball<D,T>::pivot_mb(It i)
+{
+ It t = ++L.begin();
+ mtf_mb(t);
+ T max_e, old_sqr_r = T(0);
+ do {
+ It pivot;
+ max_e = max_excess(t, i, pivot);
+ if (max_e > 0) {
+ t = support_end;
+ if (t == pivot)
+ t++;
+ old_sqr_r = B.squared_radius();
+ B.push(*pivot);
+ mtf_mb(support_end);
+ B.pop();
+ move_to_front(pivot);
+ }
+ } while (max_e > 0 && B.squared_radius() > old_sqr_r);
+}
+
+
+template <int D, class T>
+void Miniball<D,T>::build(bool pivoting /* = true */)
+{
+ B.reset();
+ support_end = L.begin();
+ if (pivoting)
+ pivot_mb(L.end());
+ else
+ mtf_mb(L.end());
+}
+
+
+//
+// Original copyright of miniball code follows:
+//
+// Copright (C) 1999
+//
+// 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., 675 Mass Ave, Cambridge, MA 02139, USA,
+// or download the License terms from
prep.ai.mit.edu/pub/gnu/COPYING-2.0.
+//
+// Contact:
+// --------
+// Bernd Gaertner
+// Institut f. Informatik
+// ETH Zuerich
+// ETH-Zentrum
+// CH-8092 Zuerich, Switzerland
+//
http://www.inf.ethz.ch/personal/gaertner
+//
+
+#endif
Index: external/trimesh/include/mempool.h
--- external/trimesh/include/mempool.h (revision 0)
+++ external/trimesh/include/mempool.h (revision 0)
@@ -0,0 +1,88 @@
+#ifndef MEMPOOL_H
+#define MEMPOOL_H
+/*
+Szymon Rusinkiewicz
+Princeton University
+
+mempool.h
+Replacement memory management for a class using a memory pool.
+
+Sample usage:
+ class MyClass {
+ private:
+ static PoolAlloc memPool;
+ public:
+ void *operator new(size_t n) { return memPool.alloc(n); }
+ void operator delete(void *p, size_t n) { memPool.free(p,n); }
+ // ...
+ };
+
+ PoolAlloc MyClass::memPool(sizeof(MyClass));
+
+Does *no* error checking.
+Make sure sizeof(MyClass) is larger than sizeof(void *).
+Based on the description of the Pool class in _Effective C++_ by Scott Meyers.
+*/
+
+#include <vector>
+#include <algorithm>
+
+#define POOL_MEMBLOCK 4088
+
+
+class PoolAlloc {
+private:
+ size_t itemsize;
+ void *freelist;
+ void grow_freelist()
+ {
+ size_t n = POOL_MEMBLOCK / itemsize;
+ freelist = ::operator new(n * itemsize);
+ for (size_t i = 0; i < n-1; i++)
+ *(void **)((char *)freelist + itemsize*i) =
+ (char *)freelist + itemsize*(i+1);
+ *(void **)((char *)freelist + itemsize*(n-1)) = 0;
+ }
+
+public:
+ PoolAlloc(size_t size) : itemsize(size), freelist(0) {}
+ void *alloc(size_t n)
+ {
+ if (n != itemsize)
+ return ::operator new(n);
+ if (!freelist)
+ grow_freelist();
+ void *next = freelist;
+ freelist = *(void **)next;
+ return next;
+ }
+ void free(void *p, size_t n)
+ {
+ if (!p)
+ return;
+ else if (n != itemsize)
+ ::operator delete(p);
+ else {
+ *(void **)p = freelist;
+ freelist = p;
+ }
+ }
+ void sort_freelist()
+ {
+ if (!freelist)
+ return;
+ std::vector<void *> v;
+ void *p;
+ for (p = freelist; *(void **)p; p = *(void **)p)
+ v.push_back(p);
+ std::sort(v.begin(), v.end());
+ p = freelist = v[0];
+ for (size_t i = 1; i < v.size(); i++) {
+ *(void **)p = v[i];
+ p = *(void **)p;
+ }
+ *(void **)p = NULL;
+ }
+};
+
+#endif
Index: external/trimesh/gluit/glui_button.cc
--- external/trimesh/gluit/glui_button.cc (revision 0)
+++ external/trimesh/gluit/glui_button.cc (revision 0)
@@ -0,0 +1,208 @@
+/****************************************************************************
+
+ GLUI User Interface Toolkit
+ ---------------------------
+
+ glui_button.cpp - GLUI_Button control class
+
+
+ --------------------------------------------------
+
+ Copyright (c) 1998 Paul Rademacher
+
+ This program is freely distributable without licensing fees and is
+ provided without guarantee or warrantee expressed or implied. This
+ program is -not- in the public domain.
+
+*****************************************************************************/
+
+#include "glui.h"
+#include "glui_stdinc.h"
+
+/****************************** GLUI_Button::mouse_down_handler() **********/
+
+int GLUI_Button::mouse_down_handler( int local_x, int local_y )
+{
+ int_val = 1; /** A button always in unpressed before here, so
+ now we invariably set it to 'depressed' **/
+
+ currently_inside = true;
+
+ draw_pressed();
+
+ return false;
+}
+
+
+/****************************** GLUI_Button::mouse_up_handler() **********/
+
+int GLUI_Button::mouse_up_handler( int local_x, int local_y, int inside )
+{
+ set_int_val( 0 ); /** A button always turns off after you press it **/
+
+ draw_unpressed();
+
+ if ( NOT inside ) {
+ }
+ else {
+ /*** Invoke the callback ***/
+ execute_callback();
+
+ /** Tell the main gfx window to update itself **/
+ if( glui )
+ glui->post_update_main_gfx();
+ }
+
+ return false;
+}
+
+
+/****************************** GLUI_Button::mouse_held_down_handler() ******/
+
+int GLUI_Button::mouse_held_down_handler( int local_x, int local_y,
+ int new_inside)
+{
+ if ( NOT new_inside AND currently_inside == true ) {
+ draw_unpressed();
+ }
+ else if ( new_inside AND currently_inside == false ) {
+ draw_pressed();
+ }
+
+ currently_inside = new_inside;
+
+ return false;
+}
+
+
+/****************************** GLUI_Button::key_handler() **********/
+
+int GLUI_Button::key_handler( unsigned char key,int modifiers )
+{
+ return false;
+}
+
+
+/************************************** GLUI_Button::draw_pressed() ******/
+
+void GLUI_Button::draw_pressed( void )
+{
+ int state, orig;
+
+ if ( NOT can_draw() )
+ return;
+
+ orig = set_to_glut_window();
+ state = glui->set_front_draw_buffer();
+
+ glColor3f( 0.0, 0.0, 0.0 );
+ glPushMatrix();
+ translate_to_origin();
+
+ draw_text( 1 );
+
+ glBegin( GL_LINE_LOOP );
+ glVertex2i( 0, 0 ); glVertex2i( w, 0 );
+ glVertex2i( w, h ); glVertex2i( 0, h );
+ glEnd();
+
+ glBegin( GL_LINE_LOOP );
+ glVertex2i( 1, 1 ); glVertex2i( w-1, 1 );
+ glVertex2i( w-1, h-1 ); glVertex2i( 1, h-1 );
+ glEnd();
+
+ glPopMatrix();
+
+ glui->restore_draw_buffer(state);
+ restore_window(orig);
+}
+
+
+/************************************** GLUI_Button::draw_unpressed() ******/
+
+void GLUI_Button::draw_unpressed( void )
+{
+ if ( NOT can_draw() )
+ return;
+
+ translate_and_draw_front();
+}
+
+
+
+
+/********************************************** GLUI_Button::draw() **********/
+
+void GLUI_Button::draw( int x, int y )
+{
+ if ( NOT can_draw() )
+ return;
+
+ if ( glui )
+ glui->draw_raised_box( 0, 0, w, h );
+
+ draw_text( 0 );
+}
+
+
+/**************************************** GLUI_Button::draw_text() **********/
+
+void GLUI_Button::draw_text( int sunken )
+{
+ int string_width, orig;
+
+ if ( NOT can_draw() )
+ return;
+
+ orig = set_to_glut_window();
+
+ glColor3ub( glui->bkgd_color.r, glui->bkgd_color.g, glui->bkgd_color.b );
+ glDisable( GL_CULL_FACE );
+ glBegin( GL_QUADS );
+ glVertex2i( 2, 2 ); glVertex2i( w-2, 2 );
+ glVertex2i( w-2, h-2 ); glVertex2i( 2, h-2 );
+ glEnd();
+
+ glColor3ub( 0,0,0 );
+
+ string_width = _glutBitmapWidthString( glui->font,
+ this->name );
+ if ( NOT sunken ) {
+ draw_name( MAX((w-string_width),0)/2, 13);
+ }
+ else {
+ draw_name( MAX((w-string_width),0)/2 + 1, 13 + 1);
+ }
+
+ if ( active ) {
+ glEnable( GL_LINE_STIPPLE );
+ glLineStipple( 1, 0x5555 );
+
+ glColor3f( 0., 0., 0. );
+
+ glBegin( GL_LINE_LOOP );
+ glVertex2i( 3, 3 ); glVertex2i( w-3, 3 );
+ glVertex2i( w-3, h-3 ); glVertex2i( 3, h-3 );
+ glEnd();
+
+ glDisable( GL_LINE_STIPPLE );
+ }
+
+ restore_window(orig);
+}
+
+
+/************************************** GLUI_Button::update_size() **********/
+
+void GLUI_Button::update_size( void )
+{
+ int text_size;
+
+ if ( NOT glui )
+ return;
+
+ text_size = string_width( name );
+
+ if ( w < text_size + 16 )
+ w = text_size + 16 ;
+}
Index: external/trimesh/gluit/freeglut_menu.c
--- external/trimesh/gluit/freeglut_menu.c (revision 0)
+++ external/trimesh/gluit/freeglut_menu.c (revision 0)
@@ -0,0 +1,949 @@
+/*
+ * freeglut_menu.c
+ *
+ * Pull-down menu creation and handling.
+ *
+ * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
+ * Written by Pawel W. Olszta, <olszta(a)sourceforge.net>
+ * Creation date: Thu Dec 16 1999
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <GL/freeglut.h>
+#include "freeglut_internal.h"
+
+/* -- DEFINITIONS ---------------------------------------------------------- */
+
+/*
+ * FREEGLUT_MENU_FONT can be any freeglut bitmapped font.
+ * (Stroked fonts would not be out of the question, but we'd need to alter
+ * code, since GLUT (hence freeglut) does not quite unify stroked and
+ * bitmapped font handling.)
+ * Old UNIX/X11 GLUT (BSD, UNIX, IRIX, LINUX, HPUX, ...) used a system
+ * font best approximated by an 18-pixel HELVETICA, I think. MS-WINDOWS
+ * GLUT used something closest to the 8x13 fixed-width font. (Old
+ * GLUT apparently uses host-system menus rather than building its own.
+ * freeglut is building its own menus from scratch.)
+ *
+ * FREEGLUT_MENU_HEIGHT gives the height of ONE menu box. This should be
+ * the distances between two adjacent menu entries. It should scale
+ * automatically with the font choice, so you needn't alter it---unless you
+ * use a stroked font.
+ *
+ * FREEGLUT_MENU_BORDER says how many pixels to allow around the edge of a
+ * menu. (It also seems to be the same as the number of pixels used as
+ * a border around *items* to separate them from neighbors. John says
+ * that that wasn't the original intent...if not, perhaps we need another
+ * symbolic constant, FREEGLUT_MENU_ITEM_BORDER, or such.)
+ */
+#if TARGET_HOST_WIN32 || TARGET_HOST_WINCE
+#define FREEGLUT_MENU_FONT GLUT_BITMAP_8_BY_13
+#else
+#define FREEGLUT_MENU_FONT GLUT_BITMAP_HELVETICA_18
+#endif
+
+#define FREEGLUT_MENU_HEIGHT (glutBitmapHeight(FREEGLUT_MENU_FONT) + \
+ FREEGLUT_MENU_BORDER)
+#define FREEGLUT_MENU_BORDER 2
+
+
+/*
+ * These variables are for rendering the freeglut menu items.
+ *
+ * The choices are fore- and background, with and without h for Highlighting.
+ * Old GLUT appeared to be system-dependant for its colors (sigh) so we are
+ * too. These variables should be stuffed into global state and initialized
+ * via the glutInit*() system.
+ */
+#if TARGET_HOST_WIN32 || TARGET_HOST_WINCE
+static float menu_pen_fore [4] = {0.0f, 0.0f, 0.0f, 1.0f};
+static float menu_pen_back [4] = {0.85f, 0.85f, 0.85f, 1.0f};
+static float menu_pen_hfore [4] = {1.0f, 1.0f, 1.0f, 1.0f};
+static float menu_pen_hback [4] = {0.15f, 0.15f, 0.45f, 1.0f};
+#else
+static float menu_pen_fore [4] = {0.0f, 0.0f, 0.0f, 1.0f};
+static float menu_pen_back [4] = {0.70f, 0.70f, 0.70f, 1.0f};
+static float menu_pen_hfore [4] = {0.0f, 0.0f, 0.0f, 1.0f};
+static float menu_pen_hback [4] = {1.0f, 1.0f, 1.0f, 1.0f};
+#endif
+
+/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
+
+/*
+ * Private function to find a menu entry by index
+ */
+static SFG_MenuEntry *fghFindMenuEntry( SFG_Menu* menu, int index )
+{
+ SFG_MenuEntry *entry;
+ int i = 1;
+
+ for( entry = (SFG_MenuEntry *)menu->Entries.First;
+ entry;
+ entry = (SFG_MenuEntry *)entry->Node.Next )
+ {
+ if( i == index )
+ break;
+ ++i;
+ }
+
+ return entry;
+}
+
+/*
+ * Private function to check for the current menu/sub menu activity state
+ */
+static GLboolean fghCheckMenuStatus( SFG_Window* window, SFG_Menu* menu )
+{
+ SFG_MenuEntry* menuEntry;
+ int x, y;
+
+ /*
+ * First of all check any of the active sub menus...
+ */
+ for( menuEntry = (SFG_MenuEntry *)menu->Entries.First;
+ menuEntry;
+ menuEntry = (SFG_MenuEntry *)menuEntry->Node.Next )
+ {
+ if( menuEntry->SubMenu && menuEntry->IsActive )
+ {
+ /*
+ * OK, have the sub-menu checked, too. If it returns GL_TRUE, it
+ * will mean that it caught the mouse cursor and we do not need
+ * to regenerate the activity list, and so our parents do...
+ */
+ GLboolean return_status = fghCheckMenuStatus( window,
+ menuEntry->SubMenu );
+
+ /*
+ * Reactivate the submenu as the checkMenuStatus may have turned
+ * it off if the mouse is in its parent menu entry.
+ */
+ menuEntry->SubMenu->IsActive = GL_TRUE;
+ if ( return_status )
+ return GL_TRUE;
+ }
+ }
+
+ /*
+ * That much about our sub menus, let's get to checking the current menu:
+ */
+ x = window->State.MouseX;
+ y = window->State.MouseY;
+
+ for( menuEntry = (SFG_MenuEntry *)menu->Entries.First;
+ menuEntry;
+ menuEntry = (SFG_MenuEntry *)menuEntry->Node.Next )
+ menuEntry->IsActive = GL_FALSE;
+
+ menu->IsActive = GL_FALSE;
+
+ /*
+ * Check if the mouse cursor is contained within the current menu box
+ */
+ if( ( x >= FREEGLUT_MENU_BORDER ) &&
+ ( x < menu->Width - FREEGLUT_MENU_BORDER ) &&
+ ( y >= FREEGLUT_MENU_BORDER ) &&
+ ( y < menu->Height - FREEGLUT_MENU_BORDER ) &&
+ ( window == menu->Window ) )
+ {
+ int menuID = ( y - FREEGLUT_MENU_BORDER ) / FREEGLUT_MENU_HEIGHT;
+
+ /*
+ * The mouse cursor is somewhere over our box, check it out.
+ */
+ menuEntry = fghFindMenuEntry( menu, menuID + 1 );
+ assert( menuEntry );
+
+ menuEntry->IsActive = GL_TRUE;
+ menuEntry->Ordinal = menuID;
+
+ /*
+ * If this is not the same as the last active menu entry, deactivate
+ * the previous entry. Specifically, if the previous active entry
+ * was a submenu then deactivate it.
+ */
+ if( menu->ActiveEntry && ( menuEntry != menu->ActiveEntry ) )
+ if( menu->ActiveEntry->SubMenu )
+ fgDeactivateSubMenu( menu->ActiveEntry );
+
+ menu->ActiveEntry = menuEntry;
+ menu->IsActive = GL_TRUE;
+
+ /*
+ * OKi, we have marked that entry as active, but it would be also
+ * nice to have its contents updated, in case it's a sub menu.
+ * Also, ignore the return value of the check function:
+ */
+ if( menuEntry->SubMenu )
+ {
+ if ( ! menuEntry->SubMenu->IsActive )
+ {
+ SFG_Window *current_window = fgStructure.Window;
+
+ /*
+ * Set up the initial menu position now...
+ */
+ menuEntry->SubMenu->IsActive = GL_TRUE;
+
+ /*
+ * Set up the initial submenu position now:
+ */
+ menuEntry->SubMenu->X = menu->X + menu->Width;
+ menuEntry->SubMenu->Y = menu->Y +
+ menuEntry->Ordinal * FREEGLUT_MENU_HEIGHT;
+
+ if( menuEntry->SubMenu->X + menuEntry->SubMenu->Width >
+ glutGet( GLUT_SCREEN_WIDTH ) )
+ menuEntry->SubMenu->X = menu->X -
+ menuEntry->SubMenu->Width;
+
+ if( menuEntry->SubMenu->Y + menuEntry->SubMenu->Height >
+ glutGet( GLUT_SCREEN_HEIGHT ) )
+ menuEntry->SubMenu->Y -= ( menuEntry->SubMenu->Height -
+ FREEGLUT_MENU_HEIGHT -
+ 2 * FREEGLUT_MENU_BORDER );
+
+ fgSetWindow( menuEntry->SubMenu->Window );
+ glutPositionWindow( menuEntry->SubMenu->X,
+ menuEntry->SubMenu->Y );
+ glutReshapeWindow( menuEntry->SubMenu->Width,
+ menuEntry->SubMenu->Height );
+ glutPopWindow( );
+ glutShowWindow( );
+ menuEntry->SubMenu->Window->ActiveMenu = menuEntry->SubMenu;
+ fgSetWindow( current_window );
+ }
+
+ fghCheckMenuStatus( window, menuEntry->SubMenu );
+
+ /*
+ * Activate it because its parent entry is active
+ */
+ menuEntry->SubMenu->IsActive = GL_TRUE;
+ }
+
+ /*
+ * Report back that we have caught the menu cursor
+ */
+ return GL_TRUE;
+ }
+
+ /*
+ * Looks like the menu cursor is somewhere else...
+ */
+ return GL_FALSE;
+}
+
+/*
+ * Displays a menu box and all of its submenus (if they are active)
+ */
+static void fghDisplayMenuBox( SFG_Menu* menu )
+{
+ SFG_MenuEntry *menuEntry;
+ int i;
+ int border = FREEGLUT_MENU_BORDER;
+
+ /*
+ * Have the menu box drawn first. The +- values are
+ * here just to make it more nice-looking...
+ */
+ /* a non-black dark version of the below. */
+ glColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
+ glBegin( GL_QUAD_STRIP );
+ glVertex2i( menu->Width , 0 );
+ glVertex2i( menu->Width - border, border);
+ glVertex2i( 0 , 0 );
+ glVertex2i( border, border);
+ glVertex2i( 0 , menu->Height );
+ glVertex2i( border, menu->Height - border);
+ glEnd( );
+
+ /* a non-black dark version of the below. */
+ glColor4f( 0.5f, 0.5f, 0.5f, 1.0f );
+ glBegin( GL_QUAD_STRIP );
+ glVertex2i( 0 , menu->Height );
+ glVertex2i( border, menu->Height - border);
+ glVertex2i( menu->Width , menu->Height );
+ glVertex2i( menu->Width - border, menu->Height - border);
+ glVertex2i( menu->Width , 0 );
+ glVertex2i( menu->Width - border, border);
+ glEnd( );
+
+ glColor4fv( menu_pen_back );
+ glBegin( GL_QUADS );
+ glVertex2i( border, border);
+ glVertex2i( menu->Width - border, border);
+ glVertex2i( menu->Width - border, menu->Height - border);
+ glVertex2i( border, menu->Height - border);
+ glEnd( );
+
+ /*
+ * Check if any of the submenus is currently active...
+ */
+ for( menuEntry = (SFG_MenuEntry *)menu->Entries.First;
+ menuEntry;
+ menuEntry = (SFG_MenuEntry *)menuEntry->Node.Next )
+ {
+ /*
+ * Has the menu been marked as active, maybe?
+ */
+ if( menuEntry->IsActive )
+ {
+ /*
+ * That's truly right, and we need to have it highlighted.
+ * There is an assumption that mouse cursor didn't move
+ * since the last check of menu activity state:
+ */
+ int menuID = menuEntry->Ordinal;
+
+ /*
+ * So have the highlight drawn...
+ */
+ glColor4fv( menu_pen_hback );
+ glBegin( GL_QUADS );
+ glVertex2i( border,
+ (menuID + 0)*FREEGLUT_MENU_HEIGHT + border );
+ glVertex2i( menu->Width - border,
+ (menuID + 0)*FREEGLUT_MENU_HEIGHT + border );
+ glVertex2i( menu->Width - border,
+ (menuID + 1)*FREEGLUT_MENU_HEIGHT + border );
+ glVertex2i( border,
+ (menuID + 1)*FREEGLUT_MENU_HEIGHT + border );
+ glEnd( );
+ }
+ }
+
+ /*
+ * Print the menu entries now...
+ */
+
+ glColor4fv( menu_pen_fore );
+
+ for( menuEntry = (SFG_MenuEntry *)menu->Entries.First, i = 0;
+ menuEntry;
+ menuEntry = (SFG_MenuEntry *)menuEntry->Node.Next, ++i )
+ {
+ /*
+ * If the menu entry is active, set the color to white
+ */
+ if( menuEntry->IsActive )
+ glColor4fv( menu_pen_hfore );
+
+ /*
+ * Move the raster into position...
+ */
+ /* Try to center the text - JCJ 31 July 2003*/
+ glRasterPos2i(
+ 2 * border,
+ ( i + 1 )*FREEGLUT_MENU_HEIGHT -
+ ( int )( FREEGLUT_MENU_HEIGHT*0.3 - border )
+ );
+
+ /*
+ * Have the label drawn, character after character:
+ */
+ glutBitmapString( FREEGLUT_MENU_FONT,
+ (unsigned char *)menuEntry->Text);
+
+ /*
+ * If it's a submenu, draw a right arrow
+ */
+ if( menuEntry->SubMenu )
+ {
+ int width = glutBitmapWidth( FREEGLUT_MENU_FONT, '_' );
+ int x_base = menu->Width - 2 - width;
+ int y_base = i*FREEGLUT_MENU_HEIGHT + border;
+ glBegin( GL_TRIANGLES );
+ glVertex2i( x_base, y_base + 2*border);
+ glVertex2i( menu->Width - 2, y_base +
+ ( FREEGLUT_MENU_HEIGHT + border) / 2 );
+ glVertex2i( x_base, y_base + FREEGLUT_MENU_HEIGHT - border );
+ glEnd( );
+ }
+
+ /*
+ * If the menu entry is active, reset the color
+ */
+ if( menuEntry->IsActive )
+ glColor4fv( menu_pen_fore );
+ }
+
+ /*
+ * Now we are ready to check if any of our children needs to be redrawn:
+ */
+ for( menuEntry = ( SFG_MenuEntry * )menu->Entries.First;
+ menuEntry;
+ menuEntry = ( SFG_MenuEntry * )menuEntry->Node.Next )
+ {
+ /*
+ * Is that an active sub menu by any case?
+ */
+ if( menuEntry->SubMenu && menuEntry->IsActive )
+ {
+ /*
+ * Yeah, indeed. Have it redrawn now:
+ */
+ fgSetWindow( menuEntry->SubMenu->Window );
+ fghDisplayMenuBox( menuEntry->SubMenu );
+ fgSetWindow( menu->Window );
+ }
+ }
+}
+
+/*
+ * Private static function to set the parent window of a submenu and all
+ * of its submenus
+ */
+static void fghSetSubmenuParentWindow( SFG_Window *window, SFG_Menu *menu )
+{
+ SFG_MenuEntry *menuEntry;
+
+ menu->ParentWindow = window;
+
+ for( menuEntry = ( SFG_MenuEntry * )menu->Entries.First;
+ menuEntry;
+ menuEntry = ( SFG_MenuEntry * )menuEntry->Node.Next )
+ if( menuEntry->SubMenu )
+ fghSetSubmenuParentWindow( window, menuEntry->SubMenu );
+}
+
+
+/*
+ * Displays the currently active menu for the current window
+ */
+void fgDisplayMenu( void )
+{
+ SFG_Window* window = fgStructure.Window;
+ SFG_Menu* menu = NULL;
+
+ freeglut_assert_window;
+
+ /*
+ * Check if there is an active menu attached to this window...
+ */
+ menu = window->ActiveMenu;
+ freeglut_return_if_fail( menu );
+
+ fgSetWindow( menu->Window );
+
+ glPushAttrib( GL_DEPTH_BUFFER_BIT | GL_TEXTURE_BIT | GL_LIGHTING_BIT |
+ GL_POLYGON_BIT );
+
+ glDisable( GL_DEPTH_TEST );
+ glDisable( GL_TEXTURE_2D );
+ glDisable( GL_LIGHTING );
+ glDisable( GL_CULL_FACE );
+
+ glMatrixMode( GL_PROJECTION );
+ glPushMatrix( );
+ glLoadIdentity( );
+ glOrtho(
+ 0, glutGet( GLUT_WINDOW_WIDTH ),
+ glutGet( GLUT_WINDOW_HEIGHT ), 0,
+ -1, 1
+ );
+
+ glMatrixMode( GL_MODELVIEW );
+ glPushMatrix( );
+ glLoadIdentity( );
+
+ fghCheckMenuStatus( window, menu );
+ fghDisplayMenuBox( menu );
+
+ glPopAttrib( );
+
+ glMatrixMode( GL_PROJECTION );
+ glPopMatrix( );
+ glMatrixMode( GL_MODELVIEW );
+ glPopMatrix( );
+
+ glutSwapBuffers( );
+
+ fgSetWindow ( window );
+}
+
+/*
+ * Activates a menu pointed by the function argument
+ */
+void fgActivateMenu( SFG_Window* window, int button )
+{
+ /*
+ * We'll be referencing this menu a lot, so remember its address:
+ */
+ SFG_Menu* menu = window->Menu[ button ];
+
+ /*
+ * Mark the menu as active, so that it gets displayed:
+ */
+ window->ActiveMenu = menu;
+ menu->IsActive = GL_TRUE;
+ fgState.ActiveMenus++;
+
+ /*
+ * Set up the initial menu position now:
+ */
+ menu->X = window->State.MouseX + glutGet( GLUT_WINDOW_X );
+ menu->Y = window->State.MouseY + glutGet( GLUT_WINDOW_Y );
+
+ if( menu->X + menu->Width > glutGet ( GLUT_SCREEN_WIDTH ) )
+ menu->X -=menu->Width;
+
+ if( menu->Y + menu->Height > glutGet ( GLUT_SCREEN_HEIGHT ) )
+ menu->Y -=menu->Height;
+
+ fgSetWindow( menu->Window );
+ glutPositionWindow( menu->X, menu->Y );
+ glutReshapeWindow( menu->Width, menu->Height );
+ glutPopWindow( );
+ glutShowWindow( );
+ menu->Window->ActiveMenu = menu;
+}
+
+/*
+ * Check whether an active menu absorbs a mouse click
+ */
+GLboolean fgCheckActiveMenu ( SFG_Window *window, SFG_Menu *menu )
+{
+ /*
+ * Near as I can tell, this is the active menu behaviour:
+ * - Down-click any button outside the menu, menu active:
+ * deactivate the menu
+ * - Down-click any button inside the menu, menu active:
+ * select the menu entry and deactivate the menu
+ * - Up-click the menu button outside the menu, menu active:
+ * nothing happens
+ * - Up-click the menu button inside the menu, menu active:
+ * select the menu entry and deactivate the menu
+ * Since menus can have submenus, we need to check this recursively.
+ */
+ return fghCheckMenuStatus( window, menu );
+}
+
+/*
+ * Function to check for menu entry selection on menu deactivation
+ */
+void fgExecuteMenuCallback( SFG_Menu* menu )
+{
+ SFG_MenuEntry *menuEntry;
+
+ /*
+ * First of all check any of the active sub menus...
+ */
+ for( menuEntry = (SFG_MenuEntry *)menu->Entries.First;
+ menuEntry;
+ menuEntry = (SFG_MenuEntry *)menuEntry->Node.Next)
+ {
+ if( menuEntry->IsActive )
+ {
+ if( menuEntry->SubMenu )
+ fgExecuteMenuCallback( menuEntry->SubMenu );
+ else
+ if( menu->Callback )
+ menu->Callback( menuEntry->ID );
+ return;
+ }
+ }
+}
+
+/*
+ * Deactivates a menu pointed by the function argument.
+ */
+void fgDeactivateMenu( SFG_Window *window )
+{
+ SFG_Window *current_window = fgStructure.Window;
+
+ /*
+ * Check if there is an active menu attached to this window...
+ */
+ SFG_Menu* menu = window->ActiveMenu;
+ SFG_MenuEntry *menuEntry;
+
+ /*
+ * Did we find an active window?
+ */
+ freeglut_return_if_fail( menu );
+
+ /*
+ * Hide the present menu's window
+ */
+ fgSetWindow( menu->Window );
+ glutHideWindow( );
+
+ /*
+ * Forget about having that menu active anymore, now:
+ */
+ menu->Window->ActiveMenu = NULL;
+ menu->ParentWindow->ActiveMenu = NULL;
+ menu->IsActive = GL_FALSE;
+
+ fgState.ActiveMenus--;
+
+ /*
+ * Hide all submenu windows, and the root menu's window.
+ */
+ for ( menuEntry = ( SFG_MenuEntry * )menu->Entries.First;
+ menuEntry;
+ menuEntry = ( SFG_MenuEntry * )menuEntry->Node.Next )
+ {
+ /*
+ * Is that an active submenu by any case?
+ */
+ if( menuEntry->SubMenu )
+ fgDeactivateSubMenu( menuEntry );
+ }
+
+ fgSetWindow( current_window );
+}
+
+/*
+ * Deactivates a menu pointed by the function argument.
+ */
+void fgDeactivateSubMenu( SFG_MenuEntry *menuEntry )
+{
+ SFG_Window *current_window = fgStructure.Window;
+ SFG_MenuEntry *subMenuIter;
+ /*
+ * Hide the present menu's window
+ */
+ fgSetWindow( menuEntry->SubMenu->Window );
+ glutHideWindow( );
+
+ /*
+ * Forget about having that menu active anymore, now:
+ */
+ menuEntry->SubMenu->Window->ActiveMenu = NULL;
+ menuEntry->SubMenu->IsActive = GL_FALSE;
+
+ /*
+ * Hide all submenu windows, and the root menu's window.
+ */
+ for ( subMenuIter = (SFG_MenuEntry *)menuEntry->SubMenu->Entries.First;
+ subMenuIter;
+ subMenuIter = (SFG_MenuEntry *)subMenuIter->Node.Next )
+ {
+ /*
+ * Is that an active submenu by any case?
+ */
+ if( subMenuIter->SubMenu )
+ fgDeactivateSubMenu( subMenuIter );
+ }
+
+ fgSetWindow( current_window );
+}
+
+/*
+ * Recalculates current menu's box size
+ */
+void fghCalculateMenuBoxSize( void )
+{
+ SFG_MenuEntry* menuEntry;
+ int width = 0, height = 0;
+
+ /*
+ * Make sure there is a current menu set
+ */
+ freeglut_assert_ready;
+ freeglut_return_if_fail( fgStructure.Menu );
+
+ /*
+ * The menu's box size depends on the menu entries:
+ */
+ for( menuEntry = ( SFG_MenuEntry * )fgStructure.Menu->Entries.First;
+ menuEntry;
+ menuEntry = ( SFG_MenuEntry * )menuEntry->Node.Next )
+ {
+ /*
+ * Update the menu entry's width value
+ */
+ menuEntry->Width = glutBitmapLength(
+ FREEGLUT_MENU_FONT,
+ (unsigned char *)menuEntry->Text
+ );
+
+ /*
+ * If the entry is a submenu, then it needs to be wider to
+ * accomodate the arrow. JCJ 31 July 2003
+ */
+ if (menuEntry->SubMenu )
+ menuEntry->Width += glutBitmapLength(
+ FREEGLUT_MENU_FONT,
+ (unsigned char *)"_"
+ );
+
+ /*
+ * Check if it's the biggest we've found
+ */
+ if( menuEntry->Width > width )
+ width = menuEntry->Width;
+
+ height += FREEGLUT_MENU_HEIGHT;
+ }
+
+ /*
+ * Store the menu's box size now:
+ */
+ fgStructure.Menu->Height = height + 2 * FREEGLUT_MENU_BORDER;
+ fgStructure.Menu->Width = width + 4 * FREEGLUT_MENU_BORDER;
+}
+
+
+/* -- INTERFACE FUNCTIONS -------------------------------------------------- */
+
+/*
+ * Creates a new menu object, adding it to the freeglut structure
+ */
+int FGAPIENTRY glutCreateMenu( void(* callback)( int ) )
+{
+ /*
+ * The menu object creation code resides in freeglut_structure.c
+ */
+ return fgCreateMenu( callback )->ID;
+}
+
+/*
+ * Destroys a menu object, removing all references to it
+ */
+void FGAPIENTRY glutDestroyMenu( int menuID )
+{
+ SFG_Menu* menu = fgMenuByID( menuID );
+
+ freeglut_assert_ready;
+ freeglut_return_if_fail( menu );
+
+ /*
+ * The menu object destruction code resides in freeglut_structure.c
+ */
+ fgDestroyMenu( menu );
+}
+
+/*
+ * Returns the ID number of the currently active menu
+ */
+int FGAPIENTRY glutGetMenu( void )
+{
+ freeglut_assert_ready;
+
+ if( fgStructure.Menu )
+ return fgStructure.Menu->ID;
+
+ return 0;
+}
+
+/*
+ * Sets the current menu given its menu ID
+ */
+void FGAPIENTRY glutSetMenu( int menuID )
+{
+ SFG_Menu* menu = fgMenuByID( menuID );
+
+ freeglut_assert_ready;
+ freeglut_return_if_fail( menu );
+
+ fgStructure.Menu = menu;
+}
+
+/*
+ * Adds a menu entry to the bottom of the current menu
+ */
+void FGAPIENTRY glutAddMenuEntry( const char* label, int value )
+{
+ SFG_MenuEntry* menuEntry =
+ (SFG_MenuEntry *)calloc( sizeof(SFG_MenuEntry), 1 );
+
+ freeglut_assert_ready;
+ freeglut_return_if_fail( fgStructure.Menu );
+
+ menuEntry->Text = strdup( label );
+ menuEntry->ID = value;
+
+ /*
+ * Have the new menu entry attached to the current menu
+ */
+ fgListAppend( &fgStructure.Menu->Entries, &menuEntry->Node );
+
+ fghCalculateMenuBoxSize( );
+}
+
+/*
+ * Add a sub menu to the bottom of the current menu
+ */
+void FGAPIENTRY glutAddSubMenu( const char *label, int subMenuID )
+{
+ SFG_MenuEntry *menuEntry =
+ ( SFG_MenuEntry * )calloc( sizeof( SFG_MenuEntry ), 1 );
+ SFG_Menu *subMenu = fgMenuByID( subMenuID );
+
+ freeglut_assert_ready;
+ freeglut_return_if_fail( fgStructure.Menu );
+ freeglut_return_if_fail( subMenu );
+
+ menuEntry->Text = strdup( label );
+ menuEntry->SubMenu = subMenu;
+ menuEntry->ID = -1;
+
+ /*
+ * Make the submenu's parent window be the menu's parent window
+ */
+ fghSetSubmenuParentWindow( fgStructure.Menu->ParentWindow, subMenu );
+
+ fgListAppend( &fgStructure.Menu->Entries, &menuEntry->Node );
+ fghCalculateMenuBoxSize( );
+}
+
+/*
+ * Changes the specified menu item in the current menu into a menu entry
+ */
+void FGAPIENTRY glutChangeToMenuEntry( int item, const char* label, int value )
+{
+ SFG_MenuEntry* menuEntry = NULL;
+
+ freeglut_assert_ready;
+ freeglut_return_if_fail( fgStructure.Menu );
+
+ /*
+ * Get n-th menu entry in the current menu, starting from one:
+ */
+ menuEntry = fghFindMenuEntry( fgStructure.Menu, item );
+
+ freeglut_return_if_fail( menuEntry );
+
+ /*
+ * We want it to become a normal menu entry, so:
+ */
+ if( menuEntry->Text )
+ free( menuEntry->Text );
+
+ menuEntry->Text = strdup( label );
+ menuEntry->ID = value;
+ menuEntry->SubMenu = NULL;
+ fghCalculateMenuBoxSize( );
+}
+
+/*
+ * Changes the specified menu item in the current menu into a sub-menu trigger.
+ */
+void FGAPIENTRY glutChangeToSubMenu( int item, const char* label,
+ int subMenuID )
+{
+ SFG_Menu* subMenu = fgMenuByID( subMenuID );
+ SFG_MenuEntry* menuEntry = NULL;
+
+ freeglut_assert_ready;
+ freeglut_return_if_fail( fgStructure.Menu );
+ freeglut_return_if_fail( subMenu );
+
+ /*
+ * Get n-th menu entry in the current menu, starting from one:
+ */
+ menuEntry = fghFindMenuEntry( fgStructure.Menu, item );
+
+ freeglut_return_if_fail( menuEntry );
+
+ /*
+ * We want it to become a sub menu entry, so:
+ */
+ if( menuEntry->Text )
+ free( menuEntry->Text );
+
+ menuEntry->Text = strdup( label );
+ menuEntry->SubMenu = subMenu;
+ menuEntry->ID = -1;
+ fghCalculateMenuBoxSize( );
+}
+
+/*
+ * Removes the specified menu item from the current menu
+ */
+void FGAPIENTRY glutRemoveMenuItem( int item )
+{
+ SFG_MenuEntry* menuEntry;
+
+ freeglut_assert_ready;
+ freeglut_return_if_fail( fgStructure.Menu );
+
+ /*
+ * Get n-th menu entry in the current menu, starting from one:
+ */
+ menuEntry = fghFindMenuEntry( fgStructure.Menu, item );
+
+ freeglut_return_if_fail( menuEntry );
+
+ fgListRemove( &fgStructure.Menu->Entries, &menuEntry->Node );
+ if ( menuEntry->Text )
+ free( menuEntry->Text );
+
+ free( menuEntry );
+ fghCalculateMenuBoxSize( );
+}
+
+/*
+ * Attaches a menu to the current window
+ */
+void FGAPIENTRY glutAttachMenu( int button )
+{
+ freeglut_assert_ready;
+
+ freeglut_return_if_fail( fgStructure.Window );
+ freeglut_return_if_fail( fgStructure.Menu );
+
+ freeglut_return_if_fail( button >= 0 );
+ freeglut_return_if_fail( button < FREEGLUT_MAX_MENUS );
+
+ fgStructure.Window->Menu[ button ] = fgStructure.Menu;
+
+ /*
+ * Make the parent window of the menu (and all submenus) the current window
+ */
+ fghSetSubmenuParentWindow( fgStructure.Window, fgStructure.Menu );
+}
+
+/*
+ * Detaches a menu from the current window
+ */
+void FGAPIENTRY glutDetachMenu( int button )
+{
+ freeglut_assert_ready;
+
+ freeglut_return_if_fail( fgStructure.Window );
+ freeglut_return_if_fail( fgStructure.Menu );
+
+ freeglut_return_if_fail( button >= 0 );
+ freeglut_return_if_fail( button < FREEGLUT_MAX_MENUS );
+
+ fgStructure.Window->Menu[ button ] = NULL;
+}
+
+/*
+ * A.Donev: Set and retrieve the menu's user data
+ */
+void* FGAPIENTRY glutGetMenuData( void )
+{
+ return fgStructure.Menu->UserData;
+}
+
+void FGAPIENTRY glutSetMenuData(void* data)
+{
+ fgStructure.Menu->UserData=data;
+}
+
+/*** END OF FILE ***/
Index: external/trimesh/gluit/glui_spinner.cc
--- external/trimesh/gluit/glui_spinner.cc (revision 0)
+++ external/trimesh/gluit/glui_spinner.cc (revision 0)
@@ -0,0 +1,579 @@
+/****************************************************************************
+
+ GLUI User Interface Toolkit
+ ---------------------------
+
+ glui_spinner.cpp - GLUI_Spinner class
+
+
+ notes:
+ spinner does not explicitly keep track of the current value - this is all
+ handled by the underlying edittext control
+ -> thus, spinner->sync_live() has no meaning, nor spinner->output_live
+ -> BUT, edittext will alter this spinner's float_val and int_val,
+ so that spinner->get/set will work
+
+
+ --------------------------------------------------
+
+ Copyright (c) 1998 Paul Rademacher
+
+ This program is freely distributable without licensing fees and is
+ provided without guarantee or warrantee expressed or implied. This
+ program is -not- in the public domain.
+
+*****************************************************************************/
+
+
+#include "glui.h"
+#include "glui_stdinc.h"
+#include <math.h>
+
+/*static int __debug=0; */
+
+#define GLUI_SPINNER_GROWTH_STEPS 800
+#define GLUI_SPINNER_MIN_GROWTH_STEPS 100
+#define GLUI_SPINNER_CALLBACK_INTERVAL 1
+
+
+/****************************** spinner_edittext_callback() ******************/
+/* This function is not used anymore. It has been replaced by directly */
+/* Including an optional pointer to a spinner from an edittext box */
+
+void spinner_edittext_callback( int id )
+{
+ GLUI_Spinner *spinner;
+
+ putchar( '.' ); flushout;
+
+ spinner = (GLUI_Spinner*) id;
+
+ if ( NOT spinner )
+ return;
+
+ spinner->do_callbacks();
+}
+
+
+/****************************** GLUI_Spinner::mouse_down_handler() **********/
+
+int GLUI_Spinner::mouse_down_handler( int local_x, int local_y )
+{
+ this->state = find_arrow( local_x, local_y );
+
+ /* printf( "spinner: mouse down : %d/%d arrow:%d\n", local_x, local_y,
+ find_arrow( local_x, local_y ));
+ */
+
+ if ( state != GLUI_SPINNER_STATE_UP AND state != GLUI_SPINNER_STATE_DOWN )
+ return true;
+
+ reset_growth();
+ if ( can_draw() )
+ draw_arrows();
+
+ /*** ints and floats behave a bit differently. When you click on
+ an int spinner, you expect the value to immediately go up by 1, whereas
+ for a float it'll go up only by a fractional amount. Therefore, we
+ go ahead and increment by one for int spinners ***/
+ if ( data_type == GLUI_SPINNER_INT ) {
+ if ( state == GLUI_SPINNER_STATE_UP )
+ edittext->set_float_val( edittext->float_val + 1.0 );
+ else if ( state == GLUI_SPINNER_STATE_DOWN )
+ edittext->set_float_val( edittext->float_val - .9 );
+ }
+
+ do_click();
+
+ return false;
+}
+
+
+/******************************** GLUI_Spinner::mouse_up_handler() **********/
+
+int GLUI_Spinner::mouse_up_handler( int local_x, int local_y, int inside )
+{
+ state = GLUI_SPINNER_STATE_NONE;
+
+ /* printf("spinner: mouse up : %d/%d inside:
%d\n",local_x,local_y,inside); */
+
+ /*glutSetCursor( GLUT_CURSOR_INHERIT ); */
+ glutSetCursor( GLUT_CURSOR_LEFT_ARROW );
+
+ draw_arrows();
+
+ /* do_callbacks(); --- stub */
+ /* if ( callback ) */
+ /* callback( this->user_id ); */
+
+ return false;
+}
+
+
+/***************************** GLUI_Spinner::mouse_held_down_handler() ******/
+
+int GLUI_Spinner::mouse_held_down_handler( int local_x, int local_y,
+ int new_inside)
+{
+ int new_state;
+
+ if ( state == GLUI_SPINNER_STATE_NONE )
+ return false;
+
+ /* printf("spinner: mouse held: %d/%d inside: %d\n",local_x,local_y,
+ new_inside);
+ */
+
+ if ( state == GLUI_SPINNER_STATE_BOTH ) { /* dragging? */
+ do_drag( local_x, local_y );
+ }
+ else { /* not dragging */
+ new_state = find_arrow( local_x, local_y );
+
+ if ( new_state == state ) {
+ /** Still in same arrow **/
+ do_click();
+ }
+ else {
+ if ( new_inside OR 1) {
+ /** The state changed, but we're still inside - that
+ means we moved off the arrow: begin dragging **/
+ state = GLUI_SPINNER_STATE_BOTH;
+ }
+ else {
+ /*** Here check y of mouse position to determine whether to
+ drag ***/
+
+ /* ... */
+ }
+ }
+
+ /*** We switched to up/down dragging ***/
+ if ( state == GLUI_SPINNER_STATE_BOTH ) {
+ glutSetCursor( GLUT_CURSOR_UP_DOWN );
+ last_x = local_x;
+ last_y = local_y;
+
+ /** If the spinner has limits, we reset the growth value, since
+ reset_growth() will compute a new growth value for dragging
+ vs. clicking. If the spinner has no limits, then we just let the
+ growth remain at whatever the user has incremented it up to **/
+ if ( edittext->has_limits != GLUI_LIMIT_NONE )
+ reset_growth();
+ }
+
+ if ( can_draw() )
+ draw_arrows();
+ }
+
+ return false;
+}
+
+
+/****************************** GLUI_Spinner::key_handler() **********/
+
+int GLUI_Spinner::key_handler( unsigned char key,int modifiers )
+{
+
+
+ return true;
+}
+
+
+/****************************** GLUI_Spinner::draw() **********/
+
+void GLUI_Spinner::draw( int x, int y )
+{
+ int orig;
+
+ if ( NOT can_draw() )
+ return;
+
+ orig = set_to_glut_window();
+
+ if ( enabled ) {
+ /*** Draw the up arrow either pressed or unrpessed ***/
+ if ( state == GLUI_SPINNER_STATE_UP OR state == GLUI_SPINNER_STATE_BOTH )
+ glui->std_bitmaps.draw( GLUI_STDBITMAP_SPINNER_UP_ON,
+ w-GLUI_SPINNER_ARROW_WIDTH-1,
+ GLUI_SPINNER_ARROW_Y);
+ else
+ glui->std_bitmaps.draw( GLUI_STDBITMAP_SPINNER_UP_OFF,
+ w-GLUI_SPINNER_ARROW_WIDTH-1,
+ GLUI_SPINNER_ARROW_Y);
+
+ /*** Draw the down arrow either pressed or unrpessed ***/
+ if (state == GLUI_SPINNER_STATE_DOWN OR state == GLUI_SPINNER_STATE_BOTH)
+ glui->std_bitmaps.draw( GLUI_STDBITMAP_SPINNER_DOWN_ON,
+ w-GLUI_SPINNER_ARROW_WIDTH-1,
+ GLUI_SPINNER_ARROW_HEIGHT+GLUI_SPINNER_ARROW_Y);
+ else
+ glui->std_bitmaps.draw( GLUI_STDBITMAP_SPINNER_DOWN_OFF,
+ w-GLUI_SPINNER_ARROW_WIDTH-1,
+ GLUI_SPINNER_ARROW_HEIGHT+GLUI_SPINNER_ARROW_Y);
+ }
+ else { /**** The spinner is disabled ****/
+ glui->std_bitmaps.draw( GLUI_STDBITMAP_SPINNER_UP_DIS,
+ w-GLUI_SPINNER_ARROW_WIDTH-1,
+ GLUI_SPINNER_ARROW_Y);
+ glui->std_bitmaps.draw( GLUI_STDBITMAP_SPINNER_DOWN_DIS,
+ w-GLUI_SPINNER_ARROW_WIDTH-1,
+ GLUI_SPINNER_ARROW_HEIGHT+GLUI_SPINNER_ARROW_Y);
+ }
+
+ if ( active ) {
+ glColor3ub( 0, 0, 0 );
+ glEnable( GL_LINE_STIPPLE );
+ glLineStipple( 1, 0x5555 );
+ }
+ else {
+ glColor3ub( glui->bkgd_color.r,glui->bkgd_color.g,glui->bkgd_color.b );
+ }
+
+ glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
+ glDisable( GL_CULL_FACE );
+ glBegin( GL_QUADS );
+ glVertex2i( w-GLUI_SPINNER_ARROW_WIDTH-2, 0 );
+ glVertex2i( w, 0 );
+ glVertex2i( w, h );
+ glVertex2i( w-GLUI_SPINNER_ARROW_WIDTH-2, h );
+ glEnd();
+ glDisable( GL_LINE_STIPPLE );
+ glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
+
+ restore_window( orig );
+}
+
+
+
+
+
+/********************************* GLUI_Spinner::special_handler() **********/
+
+int GLUI_Spinner::special_handler( int key,int modifiers )
+{
+ if ( key == GLUT_KEY_UP ) { /** Simulate a click in the up arrow **/
+ mouse_down_handler( x_abs + w - GLUI_SPINNER_ARROW_WIDTH + 1,
+ y_abs + GLUI_SPINNER_ARROW_Y+1 );
+ mouse_up_handler( x_abs + w - GLUI_SPINNER_ARROW_WIDTH + 1,
+ y_abs + GLUI_SPINNER_ARROW_Y+1, true );
+ }
+ else if ( key == GLUT_KEY_DOWN ) { /** Simulate a click in the up arrow **/
+ mouse_down_handler(x_abs + w - GLUI_SPINNER_ARROW_WIDTH + 1,
+ y_abs+GLUI_SPINNER_ARROW_Y+1+GLUI_SPINNER_ARROW_HEIGHT);
+ mouse_up_handler( x_abs + w - GLUI_SPINNER_ARROW_WIDTH + 1,
+ y_abs+GLUI_SPINNER_ARROW_Y+1 +GLUI_SPINNER_ARROW_HEIGHT,
+ true );
+ }
+ else if ( key == GLUT_KEY_HOME ) { /** Set value to limit top -
+ or increment by 10 **/
+ }
+ else if ( key == GLUT_KEY_END ) {
+ }
+
+ return true;
+}
+
+
+/******************************* GLUI_Spinner::set_float_val() ************/
+
+void GLUI_Spinner::set_float_val( float new_val )
+{
+ if ( NOT edittext )
+ return;
+
+ edittext->set_float_val( new_val );
+}
+
+
+/********************************** GLUI_Spinner::set_int_val() ************/
+
+void GLUI_Spinner::set_int_val( int new_val )
+{
+ if ( NOT edittext )
+ return;
+
+ edittext->set_int_val( new_val );
+}
+
+
+/************************************ GLUI_Spinner::update_size() **********/
+
+void GLUI_Spinner::update_size( void )
+{
+ /*edittext->w = this->w - GLUI_SPINNER_ARROW_WIDTH-3; */
+ this->w = edittext->w + GLUI_SPINNER_ARROW_WIDTH + 3;
+}
+
+
+/************************************ GLUI_Spinner::find_arrow() ************/
+
+int GLUI_Spinner::find_arrow( int local_x, int local_y )
+{
+ local_x -= x_abs;
+ local_y -= y_abs;
+
+ if ( local_x >= (w - GLUI_SPINNER_ARROW_WIDTH) AND
+ local_x <= w ) {
+
+ if ( local_y >= GLUI_SPINNER_ARROW_Y AND
+ local_y <= (GLUI_SPINNER_ARROW_Y+GLUI_SPINNER_ARROW_HEIGHT) )
+ return GLUI_SPINNER_STATE_UP;
+
+ if ( local_y >= GLUI_SPINNER_ARROW_Y+GLUI_SPINNER_ARROW_HEIGHT AND
+ local_y <= (GLUI_SPINNER_ARROW_Y+GLUI_SPINNER_ARROW_HEIGHT*2) )
+ return GLUI_SPINNER_STATE_DOWN;
+
+ }
+
+ return GLUI_SPINNER_STATE_NONE;
+}
+
+
+/****************************** GLUI_Spinner::draw_arrows() **********/
+
+void GLUI_Spinner::draw_arrows( void )
+{
+ if ( NOT can_draw() )
+ return;
+
+ translate_and_draw_front();
+}
+
+
+/***************************************** GLUI_Spinner::do_click() **********/
+
+void GLUI_Spinner::do_click( void )
+{
+ int direction = 0;
+ float incr;
+ float modifier_factor;
+
+ if ( state == GLUI_SPINNER_STATE_UP )
+ direction = +1;
+ else if ( state == GLUI_SPINNER_STATE_DOWN )
+ direction = -1;
+
+ increase_growth();
+
+ modifier_factor = 1.0;
+ if ( glui ) {
+ if ( glui->curr_modifiers & GLUT_ACTIVE_SHIFT )
+ modifier_factor = 100.0f;
+ else if ( glui->curr_modifiers & GLUT_ACTIVE_CTRL )
+ modifier_factor = .01f;
+ }
+
+ if ( this->data_type == GLUI_SPINNER_FLOAT OR 1) {
+ incr = growth * direction * modifier_factor * user_speed;
+ edittext->set_float_val( edittext->float_val + incr );
+ /** Remember, edittext mirrors the float and int values ***/
+ }
+
+ /*** Now update live variable and do callback. We don't want
+ to do the callback on each iteration of this function, just on every
+ i^th iteration, where i is given by GLUI_SPINNER_CALLBACK_INTERVAL ****/
+ callback_count++;
+ if ( (callback_count % GLUI_SPINNER_CALLBACK_INTERVAL ) == 0 )
+ do_callbacks();
+}
+
+
+/***************************************** GLUI_Spinner::do_drag() **********/
+
+void GLUI_Spinner::do_drag( int x, int y )
+{
+ int delta_y;
+ float incr, modifier_factor;
+ /* int delta_x; */
+
+ modifier_factor = 1.0f;
+ if ( glui ) {
+ if ( glui->curr_modifiers & GLUT_ACTIVE_SHIFT )
+ modifier_factor = 100.0f;
+ else if ( glui->curr_modifiers & GLUT_ACTIVE_CTRL )
+ modifier_factor = .01f;
+ }
+
+ /* delta_x = x - last_x; */
+ delta_y = -(y - last_y);
+
+ if ( this->data_type == GLUI_SPINNER_FLOAT OR 1 ) {
+ incr = growth * delta_y * modifier_factor * user_speed;
+ edittext->set_float_val( edittext->float_val + incr );
+ /** Remember, edittext mirrors the float and int values ***/
+ }
+
+ last_x = x;
+ last_y = y;
+
+ /*** Now update live variable and do callback. We don't want
+ to do the callback on each iteration of this function, just on every
+ i^th iteration, where i is given by GLUI_SPINNER_CALLBACK_INTERVAL ****/
+
+ callback_count++;
+ if ( (callback_count % GLUI_SPINNER_CALLBACK_INTERVAL ) == 0 )
+ do_callbacks();
+}
+
+
+/***************************************** GLUI_Spinner::needs_idle() ******/
+
+int GLUI_Spinner::needs_idle( void )
+{
+ if (state == GLUI_SPINNER_STATE_UP OR state == GLUI_SPINNER_STATE_DOWN ) {
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+/***************************************** GLUI_Spinner::idle() **********/
+
+void GLUI_Spinner::idle( void )
+{
+ if ( NOT needs_idle() )
+ return;
+ else
+ do_click();
+}
+
+
+/************************************ GLUI_Spinner::do_callbacks() **********/
+
+void GLUI_Spinner::do_callbacks( void )
+{
+ /*** This is not necessary, b/c edittext automatically updates us ***/
+ if ( NOT edittext )
+ return;
+ this->float_val = edittext->float_val;
+ this->int_val = edittext->int_val;
+ /* *******************************************/
+
+ if ( NOT first_callback ) {
+ if ( data_type == GLUI_SPINNER_INT AND int_val == last_int_val ) {
+ return;
+ }
+
+ if ( data_type == GLUI_SPINNER_FLOAT AND float_val == last_float_val ) {
+ return;
+ }
+ }
+
+ this->execute_callback();
+
+ last_int_val = int_val;
+ last_float_val = float_val;
+ first_callback = false;
+}
+
+
+/********************************* GLUI_Spinner::set_float_limits() *********/
+
+void GLUI_Spinner::set_float_limits( float low, float high, int limit_type )
+{
+ if ( NOT edittext )
+ return;
+
+ edittext->set_float_limits( low, high, limit_type );
+}
+
+
+/*********************************** GLUI_Spinner::set_int_limits() *********/
+
+void GLUI_Spinner::set_int_limits( int low, int high, int limit_type )
+{
+ if ( NOT edittext )
+ return;
+
+ edittext->set_int_limits( low, high, limit_type );
+}
+
+
+/*********************************** GLUI_Spinner:reset_growth() *************/
+
+void GLUI_Spinner::reset_growth( void )
+{
+ float lo, hi;
+
+ if ( edittext->has_limits == GLUI_LIMIT_NONE ) {
+ if ( data_type == GLUI_SPINNER_FLOAT )
+ growth = sqrt(ABS(edittext->float_val)) * .05f;
+ else if ( data_type == GLUI_SPINNER_INT )
+ growth = .4f;
+ }
+ else {
+ if ( data_type == GLUI_SPINNER_FLOAT ) {
+ lo = edittext->float_low;
+ hi = edittext->float_high;
+ growth = (hi-lo) / GLUI_SPINNER_GROWTH_STEPS;
+ }
+ else if ( data_type == GLUI_SPINNER_INT ) {
+ lo = (float) edittext->int_low;
+ hi = (float) edittext->int_high;
+
+ growth = (hi-lo) / GLUI_SPINNER_GROWTH_STEPS;
+ }
+ }
+
+ if ( growth == 0.0f )
+ growth = .001f;
+}
+
+
+/******************************* GLUI_Spinner:increase_growth() *************/
+
+void GLUI_Spinner::increase_growth( void )
+{
+ float hi = 0.0,lo = 0.0;
+
+ if ( data_type == GLUI_SPINNER_FLOAT ) {
+ lo = edittext->float_low;
+ hi = edittext->float_high;
+ }
+ else if ( data_type == GLUI_SPINNER_INT ) {
+ lo = (float) edittext->int_low;
+ hi = (float) edittext->int_high;
+ }
+
+ if ( growth < (hi-lo) / GLUI_SPINNER_MIN_GROWTH_STEPS )
+ growth *= growth_exp;
+
+ /* printf( "growth: %f\n", growth ); */
+}
+
+
+/*************************************** GLUI_Spinner:get_text() *************/
+
+char *GLUI_Spinner::get_text( void )
+{
+ if (edittext)
+ return edittext->text;
+ else
+ return "";
+}
+
+
+/********************************** GLUI_Spinner:get_float_val() *************/
+
+float GLUI_Spinner::get_float_val( void )
+{
+ if (edittext)
+ return edittext->float_val;
+ else
+ return 0.0f;
+}
+
+
+/********************************** GLUI_Spinner:get_int_val() *************/
+
+int GLUI_Spinner::get_int_val( void )
+{
+ if (edittext)
+ return edittext->int_val;
+ else
+ return 0;
+}
+
+
Index: external/trimesh/gluit/freeglut_window.c
--- external/trimesh/gluit/freeglut_window.c (revision 0)
+++ external/trimesh/gluit/freeglut_window.c (revision 0)
@@ -0,0 +1,1092 @@
+/*
+ * freeglut_window.c
+ *
+ * Window management methods.
+ *
+ * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
+ * Written by Pawel W. Olszta, <olszta(a)sourceforge.net>
+ * Creation date: Fri Dec 3 1999
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <GL/freeglut.h>
+#include "freeglut_internal.h"
+
+#if TARGET_HOST_WINCE
+#include <aygshell.h>
+#pragma comment( lib, "Aygshell.lib" )
+
+wchar_t* wstr_from_str(const char* str)
+{
+ int i,len=strlen(str);
+ wchar_t* wstr = (wchar_t*)malloc(2*len+2);
+ for(i=0; i<len; i++)
+ wstr[i] = str[i];
+ wstr[len] = 0;
+ return wstr;
+}
+
+
+#endif /* TARGET_HOST_WINCE */
+
+/*
+ * TODO BEFORE THE STABLE RELEASE:
+ *
+ * fgChooseVisual() -- OK, but what about glutInitDisplayString()?
+ * fgSetupPixelFormat -- ignores the display mode settings
+ * fgOpenWindow() -- check the Win32 version, -iconic handling!
+ * fgCloseWindow() -- check the Win32 version
+ * glutCreateWindow() -- Check when default position and size is {-1,-1}
+ * glutCreateSubWindow() -- Check when default position and size is {-1,-1}
+ * glutDestroyWindow() -- check the Win32 version
+ * glutSetWindow() -- check the Win32 version
+ * glutGetWindow() -- OK
+ * glutSetWindowTitle() -- check the Win32 version
+ * glutSetIconTitle() -- check the Win32 version
+ * glutShowWindow() -- check the Win32 version
+ * glutHideWindow() -- check the Win32 version
+ * glutIconifyWindow() -- check the Win32 version
+ * glutReshapeWindow() -- check the Win32 version
+ * glutPositionWindow() -- check the Win32 version
+ * glutPushWindow() -- check the Win32 version
+ * glutPopWindow() -- check the Win32 version
+ */
+
+/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
+
+/*
+ * Chooses a visual basing on the current display mode settings
+ */
+#if TARGET_HOST_UNIX_X11
+
+XVisualInfo* fgChooseVisual( void )
+{
+#define BUFFER_SIZES 6
+ int bufferSize[BUFFER_SIZES] = { 16, 12, 8, 4, 2, 1 };
+ GLboolean wantIndexedMode = GL_FALSE;
+ int attributes[ 32 ];
+ int where = 0;
+
+ /*
+ * First we have to process the display mode settings...
+ */
+/*
+ * Why is there a semi-colon in this #define? The code
+ * that uses the macro seems to always add more semicolons...
+ */
+#define ATTRIB(a) attributes[where++]=a;
+#define ATTRIB_VAL(a,v) {ATTRIB(a); ATTRIB(v);}
+
+ if( fgState.DisplayMode & GLUT_INDEX )
+ {
+ ATTRIB_VAL( GLX_BUFFER_SIZE, 8 );
+ wantIndexedMode = GL_TRUE;
+ }
+ else
+ {
+ ATTRIB( GLX_RGBA );
+ ATTRIB_VAL( GLX_RED_SIZE, 1 );
+ ATTRIB_VAL( GLX_GREEN_SIZE, 1 );
+ ATTRIB_VAL( GLX_BLUE_SIZE, 1 );
+ if( fgState.DisplayMode & GLUT_ALPHA )
+ ATTRIB_VAL( GLX_ALPHA_SIZE, 1 );
+ }
+
+ if( fgState.DisplayMode & GLUT_DOUBLE )
+ ATTRIB( GLX_DOUBLEBUFFER );
+
+ if( fgState.DisplayMode & GLUT_STEREO )
+ ATTRIB( GLX_STEREO );
+
+ if( fgState.DisplayMode & GLUT_DEPTH )
+ ATTRIB_VAL( GLX_DEPTH_SIZE, 1 );
+
+ if( fgState.DisplayMode & GLUT_STENCIL )
+ ATTRIB_VAL( GLX_STENCIL_SIZE, 1 );
+
+ if( fgState.DisplayMode & GLUT_ACCUM )
+ {
+ ATTRIB_VAL( GLX_ACCUM_RED_SIZE, 1 );
+ ATTRIB_VAL( GLX_ACCUM_GREEN_SIZE, 1 );
+ ATTRIB_VAL( GLX_ACCUM_BLUE_SIZE, 1 );
+ if( fgState.DisplayMode & GLUT_ALPHA )
+ ATTRIB_VAL( GLX_ACCUM_ALPHA_SIZE, 1 );
+ }
+
+ /*
+ * Push a null at the end of the list
+ */
+ ATTRIB( None );
+
+ if( ! wantIndexedMode )
+ return glXChooseVisual( fgDisplay.Display, fgDisplay.Screen,
+ attributes );
+ else
+ {
+ XVisualInfo* visualInfo;
+ int i;
+
+ /*
+ * In indexed mode, we need to check how many bits of depth can we
+ * achieve. We do this by trying each possibility from the list
+ * given in the {bufferSize} array. If we match, we return to caller.
+ */
+ for( i=0; i<BUFFER_SIZES; i++ )
+ {
+ attributes[ 1 ] = bufferSize[ i ];
+ visualInfo = glXChooseVisual( fgDisplay.Display, fgDisplay.Screen,
+ attributes );
+ if( visualInfo != NULL )
+ return visualInfo;
+ }
+ return NULL;
+ }
+}
+#endif
+
+/*
+ * Setup the pixel format for a Win32 window
+ */
+#if TARGET_HOST_WIN32
+GLboolean fgSetupPixelFormat( SFG_Window* window, GLboolean checkOnly,
+ unsigned char layer_type )
+{
+#if TARGET_HOST_WINCE
+ return GL_TRUE;
+#else
+ PIXELFORMATDESCRIPTOR* ppfd, pfd;
+ int flags, pixelformat;
+
+ freeglut_return_val_if_fail( window != NULL, 0 );
+ flags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
+ if( fgState.DisplayMode & GLUT_DOUBLE )
+ flags |= PFD_DOUBLEBUFFER;
+
+#if defined(_MSC_VER)
+#pragma message( "fgSetupPixelFormat(): there is still some work to do here!"
)
+#endif
+
+ /*
+ * Specify which pixel format do we opt for...
+ */
+ pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
+ pfd.nVersion = 1;
+ pfd.dwFlags = flags;
+ pfd.iPixelType = PFD_TYPE_RGBA;
+ pfd.cColorBits = 24;
+ pfd.cRedBits = 0;
+ pfd.cRedShift = 0;
+ pfd.cGreenBits = 0;
+ pfd.cGreenShift = 0;
+ pfd.cBlueBits = 0;
+ pfd.cBlueShift = 0;
+ pfd.cAlphaBits = 0;
+ pfd.cAlphaShift = 0;
+ pfd.cAccumBits = 0;
+ pfd.cAccumRedBits = 0;
+ pfd.cAccumGreenBits = 0;
+ pfd.cAccumBlueBits = 0;
+ pfd.cAccumAlphaBits = 0;
+#if 0
+ pfd.cDepthBits = 32;
+ pfd.cStencilBits = 0;
+#else
+ pfd.cDepthBits = 24;
+ pfd.cStencilBits = 8;
+#endif
+ pfd.cAuxBuffers = 0;
+ pfd.iLayerType = layer_type;
+ pfd.bReserved = 0;
+ pfd.dwLayerMask = 0;
+ pfd.dwVisibleMask = 0;
+ pfd.dwDamageMask = 0;
+
+ pfd.cColorBits = (BYTE) GetDeviceCaps( window->Window.Device, BITSPIXEL );
+ ppfd = &pfd;
+
+ pixelformat = ChoosePixelFormat( window->Window.Device, ppfd );
+ if( pixelformat == 0 )
+ return GL_FALSE;
+
+ if( checkOnly )
+ return GL_TRUE;
+ return SetPixelFormat( window->Window.Device, pixelformat, ppfd );
+#endif /* TARGET_HOST_WINCE */
+}
+#endif
+
+/*
+ * Sets the OpenGL context and the fgStructure "Current Window" pointer to
+ * the window structure passed in.
+ */
+void fgSetWindow ( SFG_Window *window )
+{
+#if TARGET_HOST_UNIX_X11
+ if ( window )
+ glXMakeCurrent(
+ fgDisplay.Display,
+ window->Window.Handle,
+ window->Window.Context
+ );
+#elif TARGET_HOST_WIN32 || TARGET_HOST_WINCE
+ if( fgStructure.Window )
+ ReleaseDC( fgStructure.Window->Window.Handle,
+ fgStructure.Window->Window.Device );
+
+ if ( window )
+ {
+ window->Window.Device = GetDC( window->Window.Handle );
+ wglMakeCurrent(
+ window->Window.Device,
+ window->Window.Context
+ );
+ }
+#endif
+ fgStructure.Window = window;
+}
+
+
+/*
+ * Opens a window. Requires a SFG_Window object created and attached
+ * to the freeglut structure. OpenGL context is created here.
+ */
+void fgOpenWindow( SFG_Window* window, const char* title,
+ int x, int y, int w, int h,
+ GLboolean gameMode, GLboolean isSubWindow )
+{
+#if TARGET_HOST_UNIX_X11
+ XSetWindowAttributes winAttr;
+ XTextProperty textProperty;
+ XSizeHints sizeHints;
+ XWMHints wmHints;
+ unsigned long mask;
+
+ freeglut_assert_ready;
+
+ /*
+ * XXX fgChooseVisual() is a common part of all three.
+ * XXX With a little thought, we should be able to greatly
+ * XXX simplify this.
+ */
+ if( !window->IsMenu )
+ window->Window.VisualInfo = fgChooseVisual( );
+ else if( fgStructure.MenuContext )
+ window->Window.VisualInfo = fgChooseVisual( );
+ else
+ {
+ /* XXX Why are menus double- and depth-buffered? */
+ unsigned int current_DisplayMode = fgState.DisplayMode ;
+ fgState.DisplayMode = GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH ;
+ window->Window.VisualInfo = fgChooseVisual( );
+ fgState.DisplayMode = current_DisplayMode ;
+ }
+
+ if( ! window->Window.VisualInfo )
+ {
+ /*
+ * The "fgChooseVisual" returned a null meaning that the visual
+ * context is not available.
+ * Try a couple of variations to see if they will work.
+ */
+ if( !( fgState.DisplayMode & GLUT_DOUBLE ) )
+ {
+ fgState.DisplayMode |= GLUT_DOUBLE ;
+ window->Window.VisualInfo = fgChooseVisual( );
+ fgState.DisplayMode &= ~GLUT_DOUBLE;
+ }
+
+ /*
+ * GLUT also checks for multi-sampling, but I don't see that
+ * anywhere else in FREEGLUT so I won't bother with it for the moment.
+ */
+ }
+
+ /*
+ * XXX This seems to be abusing an assert() for error-checking.
+ * XXX It is possible that the visual simply can't be found,
+ * XXX in which case we should print an error and return a 0
+ * XXX for the window id, I think.
+ */
+ assert( window->Window.VisualInfo != NULL );
+
+
+ /*
+ * XXX HINT: the masks should be updated when adding/removing callbacks.
+ * XXX This might speed up message processing. Is that true?
+ * XXX
+ * XXX A: Not appreciably, but it WILL make it easier to debug.
+ * XXX Try tracing old GLUT and try tracing freeglut. Old GLUT
+ * XXX turns off events that it doesn't need and is a whole lot
+ * XXX more pleasant to trace. (Think mouse-motion! Tons of
+ * XXX ``bonus'' GUI events stream in.)
+ */
+ winAttr.event_mask =
+ StructureNotifyMask | SubstructureNotifyMask | ExposureMask |
+ ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyRelease |
+ VisibilityChangeMask | EnterWindowMask | LeaveWindowMask |
+ PointerMotionMask | ButtonMotionMask;
+ winAttr.background_pixmap = None;
+ winAttr.background_pixel = 0;
+ winAttr.border_pixel = 0;
+
+ winAttr.colormap = XCreateColormap(
+ fgDisplay.Display, fgDisplay.RootWindow,
+ window->Window.VisualInfo->visual, AllocNone
+ );
+
+ mask = CWBackPixmap | CWBorderPixel | CWColormap | CWEventMask;
+
+ if( window->IsMenu )
+ {
+ winAttr.override_redirect = True;
+ mask |= CWOverrideRedirect;
+ }
+
+ window->Window.Handle = XCreateWindow(
+ fgDisplay.Display,
+ window->Parent == NULL ? fgDisplay.RootWindow :
+ window->Parent->Window.Handle,
+ x, y, w, h, 0,
+ window->Window.VisualInfo->depth, InputOutput,
+ window->Window.VisualInfo->visual, mask,
+ &winAttr
+ );
+
+ /*
+ * The GLX context creation, possibly trying the direct context rendering
+ * or else use the current context if the user has so specified
+ */
+ if( window->IsMenu )
+ {
+ /*
+ * If there isn't already an OpenGL rendering context for menu
+ * windows, make one
+ */
+ if( !fgStructure.MenuContext )
+ {
+ fgStructure.MenuContext =
+ (SFG_MenuContext *)malloc( sizeof(SFG_MenuContext) );
+ fgStructure.MenuContext->VisualInfo = window->Window.VisualInfo;
+ fgStructure.MenuContext->Context = glXCreateContext(
+ fgDisplay.Display, fgStructure.MenuContext->VisualInfo,
+ NULL, ( fgState.DirectContext != GLUT_FORCE_INDIRECT_CONTEXT )
+ );
+ }
+
+ /* window->Window.Context = fgStructure.MenuContext->Context; */
+ window->Window.Context = glXCreateContext(
+ fgDisplay.Display, window->Window.VisualInfo,
+ NULL, ( fgState.DirectContext != GLUT_FORCE_INDIRECT_CONTEXT )
+ );
+ }
+ else if( fgState.UseCurrentContext )
+ {
+ window->Window.Context = glXGetCurrentContext( );
+
+ if( ! window->Window.Context )
+ window->Window.Context = glXCreateContext(
+ fgDisplay.Display, window->Window.VisualInfo,
+ NULL, ( fgState.DirectContext != GLUT_FORCE_INDIRECT_CONTEXT )
+ );
+ }
+ else
+ window->Window.Context = glXCreateContext(
+ fgDisplay.Display, window->Window.VisualInfo,
+ NULL, ( fgState.DirectContext != GLUT_FORCE_INDIRECT_CONTEXT )
+ );
+
+ if( !glXIsDirect( fgDisplay.Display, window->Window.Context ) )
+ {
+ if( fgState.DirectContext == GLUT_FORCE_DIRECT_CONTEXT )
+ fgError( "Unable to force direct context rendering for window
'%s'",
+ title );
+ else if( fgState.DirectContext == GLUT_TRY_DIRECT_CONTEXT )
+ fgWarning( "Unable to create direct context rendering for window
'%s'\nThis may hurt performance.",
+ title );
+ }
+
+ glXMakeCurrent(
+ fgDisplay.Display,
+ window->Window.Handle,
+ window->Window.Context
+ );
+
+ /*
+ * XXX Assume the new window is visible by default
+ * XXX Is this a safe assumption?
+ */
+ window->State.Visible = GL_TRUE;
+
+ sizeHints.flags = 0;
+ if ( fgState.Position.Use )
+ sizeHints.flags |= USPosition;
+ if ( fgState.Size.Use )
+ sizeHints.flags |= USSize;
+
+ /*
+ * Fill in the size hints values now (the x, y, width and height
+ * settings are obsolote, are there any more WMs that support them?)
+ * Unless the X servers actually stop supporting these, we should
+ * continue to fill them in. It is *not* our place to tell the user
+ * that they should replace a window manager that they like, and which
+ * works, just because *we* think that it's not "modern" enough.
+ */
+#if TARGET_HOST_WINCE
+ sizeHints.x = 0;
+ sizeHints.y = 0;
+ sizeHints.width = 320;
+ sizeHints.height = 240;
+#else
+ sizeHints.x = x;
+ sizeHints.y = y;
+ sizeHints.width = w;
+ sizeHints.height = h;
+#endif /* TARGET_HOST_WINCE */
+
+ wmHints.flags = StateHint;
+ wmHints.initial_state = fgState.ForceIconic ? IconicState : NormalState;
+ /*
+ * Prepare the window and iconified window names...
+ */
+ XStringListToTextProperty( (char **) &title, 1, &textProperty );
+
+ XSetWMProperties(
+ fgDisplay.Display,
+ window->Window.Handle,
+ &textProperty,
+ &textProperty,
+ 0,
+ 0,
+ &sizeHints,
+ &wmHints,
+ NULL
+ );
+
+ XSetWMProtocols( fgDisplay.Display, window->Window.Handle,
+ &fgDisplay.DeleteWindow, 1 );
+
+ XMapWindow( fgDisplay.Display, window->Window.Handle );
+
+#elif TARGET_HOST_WIN32 || TARGET_HOST_WINCE
+
+ WNDCLASS wc;
+ DWORD flags;
+ DWORD exFlags = 0;
+ ATOM atom;
+
+ freeglut_assert_ready;
+
+ /*
+ * Grab the window class we have registered on glutInit():
+ */
+ atom = GetClassInfo( fgDisplay.Instance, _T("FREEGLUT"), &wc );
+ assert( atom != 0 );
+
+ if( gameMode )
+ {
+ assert( window->Parent == NULL );
+
+ /*
+ * Set the window creation flags appropriately to make the window
+ * entirely visible:
+ */
+ flags = WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE;
+ }
+ else
+ {
+#if !TARGET_HOST_WINCE
+ if ( ( ! isSubWindow ) && ( ! window->IsMenu ) )
+ {
+ /*
+ * Update the window dimensions, taking account of window
+ * decorations. "freeglut" is to create the window with the
+ * outside of its border at (x,y) and with dimensions (w,h).
+ */
+ w += (GetSystemMetrics( SM_CXSIZEFRAME ) )*2;
+ h += (GetSystemMetrics( SM_CYSIZEFRAME ) )*2 +
+ GetSystemMetrics( SM_CYCAPTION );
+ }
+#endif /* TARGET_HOST_WINCE */
+
+ if( ! fgState.Position.Use )
+ {
+ x = CW_USEDEFAULT;
+ y = CW_USEDEFAULT;
+ }
+ if( ! fgState.Size.Use )
+ {
+ w = CW_USEDEFAULT;
+ h = CW_USEDEFAULT;
+ }
+
+ /*
+ * There's a small difference between creating the top, child and
+ * game mode windows
+ */
+ flags = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE;
+
+ if ( window->IsMenu )
+ {
+ flags |= WS_POPUP;
+ exFlags |= WS_EX_TOOLWINDOW;
+ }
+#if !TARGET_HOST_WINCE
+ else if( window->Parent == NULL )
+ flags |= WS_OVERLAPPEDWINDOW;
+#endif
+ else
+ flags |= WS_CHILD;
+ }
+
+#if TARGET_HOST_WINCE
+ {
+ wchar_t* wstr = wstr_from_str(title);
+
+ window->Window.Handle = CreateWindow(
+ _T("FREEGLUT"),
+ wstr,
+ WS_VISIBLE | WS_POPUP,
+ 0,0, 240,320,
+ NULL,
+ NULL,
+ fgDisplay.Instance,
+ (LPVOID) window
+ );
+
+ free(wstr);
+
+ SHFullScreen(window->Window.Handle, SHFS_HIDESTARTICON);
+ SHFullScreen(window->Window.Handle, SHFS_HIDESIPBUTTON);
+ SHFullScreen(window->Window.Handle, SHFS_HIDETASKBAR);
+ MoveWindow(window->Window.Handle, 0, 0, 240, 320, TRUE);
+ ShowWindow(window->Window.Handle, SW_SHOW);
+ UpdateWindow(window->Window.Handle);
+ }
+#else
+ window->Window.Handle = CreateWindowEx(
+ exFlags,
+ "FREEGLUT",
+ title,
+ flags,
+ x, y, w, h,
+ (HWND) window->Parent == NULL ? NULL : window->Parent->Window.Handle,
+ (HMENU) NULL,
+ fgDisplay.Instance,
+ (LPVOID) window
+ );
+#endif /* TARGET_HOST_WINCE */
+
+ if( !( window->Window.Handle ) )
+ fgError( "Failed to create a window (%s)!", title );
+
+#if TARGET_HOST_WINCE
+ ShowWindow( window->Window.Handle, SW_SHOW );
+#else
+ ShowWindow( window->Window.Handle,
+ fgState.ForceIconic ? SW_SHOWMINIMIZED : SW_SHOW );
+#endif /* TARGET_HOST_WINCE */
+
+ UpdateWindow( window->Window.Handle );
+ ShowCursor( TRUE ); /* XXX Old comments say "hide cusror"! */
+
+#endif
+
+ fgSetWindow( window );
+
+ window->Window.DoubleBuffered =
+ ( fgState.DisplayMode & GLUT_DOUBLE ) ? 1 : 0;
+
+ if ( ! window->Window.DoubleBuffered )
+ {
+ glDrawBuffer ( GL_FRONT );
+ glReadBuffer ( GL_FRONT );
+ }
+}
+
+/*
+ * Closes a window, destroying the frame and OpenGL context
+ */
+void fgCloseWindow( SFG_Window* window )
+{
+ freeglut_assert_ready;
+
+#if TARGET_HOST_UNIX_X11
+
+ glXDestroyContext( fgDisplay.Display, window->Window.Context );
+ XDestroyWindow( fgDisplay.Display, window->Window.Handle );
+ XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */
+
+#elif TARGET_HOST_WIN32 || TARGET_HOST_WINCE
+
+ /*
+ * Make sure we don't close a window with current context active
+ */
+ if( fgStructure.Window == window )
+ wglMakeCurrent( NULL, NULL );
+
+ /*
+ * Step through the list of windows. If the rendering context
+ * is not being used by another window, then we delete it.
+ */
+ {
+ int used = FALSE ;
+ SFG_Window *iter ;
+
+ for( iter = (SFG_Window *)fgStructure.Windows.First;
+ iter;
+ iter = (SFG_Window *)iter->Node.Next )
+ {
+ if( ( iter->Window.Context == window->Window.Context ) &&
+ ( iter != window ) )
+ used = TRUE;
+ }
+
+ if( ! used )
+ wglDeleteContext( window->Window.Context );
+ }
+
+ DestroyWindow( window->Window.Handle );
+#endif
+}
+
+
+/* -- INTERFACE FUNCTIONS -------------------------------------------------- */
+
+/*
+ * Creates a new top-level freeglut window
+ */
+int FGAPIENTRY glutCreateWindow( const char* title )
+{
+ return fgCreateWindow( NULL, title, fgState.Position.X, fgState.Position.Y,
+ fgState.Size.X, fgState.Size.Y, GL_FALSE,
+ GL_FALSE )->ID;
+}
+
+/*
+ * This function creates a sub window.
+ */
+int FGAPIENTRY glutCreateSubWindow( int parentID, int x, int y, int w, int h )
+{
+ int ret = 0;
+
+ SFG_Window* window = NULL;
+ SFG_Window* parent = NULL;
+
+ freeglut_assert_ready;
+ parent = fgWindowByID( parentID );
+ freeglut_return_val_if_fail( parent != NULL, 0 );
+ window = fgCreateWindow( parent, "", x, y, w, h, GL_FALSE, GL_FALSE );
+ ret = window->ID;
+
+ return ret;
+}
+
+/*
+ * Destroys a window and all of its subwindows
+ */
+void FGAPIENTRY glutDestroyWindow( int windowID )
+{
+ SFG_Window* window = fgWindowByID( windowID );
+ freeglut_return_if_fail( window != NULL );
+ {
+ fgExecutionState ExecState = fgState.ExecState;
+ fgAddToWindowDestroyList( window );
+ fgState.ExecState = ExecState;
+ }
+}
+
+/*
+ * This function selects the current window
+ */
+void FGAPIENTRY glutSetWindow( int ID )
+{
+ SFG_Window* window = NULL;
+
+ freeglut_assert_ready;
+ if( fgStructure.Window != NULL )
+ if( fgStructure.Window->ID == ID )
+ return;
+
+ window = fgWindowByID( ID );
+ if( window == NULL )
+ {
+ fgWarning( "glutSetWindow(): window ID %i not found!", ID );
+ return;
+ }
+
+ fgSetWindow( window );
+}
+
+/*
+ * This function returns the ID number of the current window, 0 if none exists
+ */
+int FGAPIENTRY glutGetWindow( void )
+{
+ freeglut_assert_ready;
+ if( fgStructure.Window == NULL )
+ return 0;
+ return fgStructure.Window->ID;
+}
+
+/*
+ * This function makes the current window visible
+ */
+void FGAPIENTRY glutShowWindow( void )
+{
+ freeglut_assert_ready;
+ freeglut_assert_window;
+
+#if TARGET_HOST_UNIX_X11
+
+ XMapWindow( fgDisplay.Display, fgStructure.Window->Window.Handle );
+ XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */
+
+#elif TARGET_HOST_WIN32 || TARGET_HOST_WINCE
+
+ ShowWindow( fgStructure.Window->Window.Handle, SW_SHOW );
+
+#endif
+
+ fgStructure.Window->State.Redisplay = GL_TRUE;
+}
+
+/*
+ * This function hides the current window
+ */
+void FGAPIENTRY glutHideWindow( void )
+{
+ freeglut_assert_ready;
+ freeglut_assert_window;
+
+#if TARGET_HOST_UNIX_X11
+
+ if( fgStructure.Window->Parent == NULL )
+ XWithdrawWindow( fgDisplay.Display,
+ fgStructure.Window->Window.Handle,
+ fgDisplay.Screen );
+ else
+ XUnmapWindow( fgDisplay.Display,
+ fgStructure.Window->Window.Handle );
+ XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */
+
+#elif TARGET_HOST_WIN32 || TARGET_HOST_WINCE
+
+ ShowWindow( fgStructure.Window->Window.Handle, SW_HIDE );
+
+#endif
+
+ fgStructure.Window->State.Redisplay = GL_FALSE;
+}
+
+/*
+ * Iconify the current window (top-level windows only)
+ */
+void FGAPIENTRY glutIconifyWindow( void )
+{
+ freeglut_assert_ready;
+ freeglut_assert_window;
+
+ fgStructure.Window->State.Visible = GL_FALSE;
+#if TARGET_HOST_UNIX_X11
+
+ XIconifyWindow( fgDisplay.Display, fgStructure.Window->Window.Handle,
+ fgDisplay.Screen );
+ XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */
+
+#elif TARGET_HOST_WIN32 || TARGET_HOST_WINCE
+
+ ShowWindow( fgStructure.Window->Window.Handle, SW_MINIMIZE );
+
+#endif
+
+ fgStructure.Window->State.Redisplay = GL_FALSE;
+}
+
+/*
+ * Set the current window's title
+ */
+void FGAPIENTRY glutSetWindowTitle( const char* title )
+{
+ freeglut_assert_ready;
+ freeglut_assert_window;
+ if( ! fgStructure.Window->Parent )
+ {
+#if TARGET_HOST_UNIX_X11
+
+ XTextProperty text;
+
+ text.value = (unsigned char *) title;
+ text.encoding = XA_STRING;
+ text.format = 8;
+ text.nitems = strlen( title );
+
+ XSetWMName(
+ fgDisplay.Display,
+ fgStructure.Window->Window.Handle,
+ &text
+ );
+
+ XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */
+
+#elif TARGET_HOST_WIN32
+
+ SetWindowText( fgStructure.Window->Window.Handle, title );
+
+#elif TARGET_HOST_WINCE
+ {
+ wchar_t* wstr = wstr_from_str(title);
+
+ SetWindowText( fgStructure.Window->Window.Handle, wstr );
+
+ free(wstr);
+ }
+#endif
+ }
+}
+
+/*
+ * Set the current window's iconified title
+ */
+void FGAPIENTRY glutSetIconTitle( const char* title )
+{
+ freeglut_assert_ready;
+ freeglut_assert_window;
+
+ if( ! fgStructure.Window->Parent )
+ {
+#if TARGET_HOST_UNIX_X11
+
+ XTextProperty text;
+
+ text.value = (unsigned char *) title;
+ text.encoding = XA_STRING;
+ text.format = 8;
+ text.nitems = strlen( title );
+
+ XSetWMIconName(
+ fgDisplay.Display,
+ fgStructure.Window->Window.Handle,
+ &text
+ );
+
+ XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */
+
+#elif TARGET_HOST_WIN32
+
+ SetWindowText( fgStructure.Window->Window.Handle, title );
+
+#elif TARGET_HOST_WINCE
+ {
+ wchar_t* wstr = wstr_from_str(title);
+
+ SetWindowText( fgStructure.Window->Window.Handle, wstr );
+
+ free(wstr);
+ }
+#endif
+ }
+}
+
+/*
+ * Change the current window's size
+ */
+void FGAPIENTRY glutReshapeWindow( int width, int height )
+{
+ freeglut_assert_ready;
+ freeglut_assert_window;
+
+ fgStructure.Window->State.NeedToResize = GL_TRUE;
+ fgStructure.Window->State.Width = width ;
+ fgStructure.Window->State.Height = height;
+}
+
+/*
+ * Change the current window's position
+ */
+void FGAPIENTRY glutPositionWindow( int x, int y )
+{
+ freeglut_assert_ready;
+ freeglut_assert_window;
+
+#if TARGET_HOST_UNIX_X11
+
+ XMoveWindow( fgDisplay.Display, fgStructure.Window->Window.Handle,
+ x, y );
+ XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */
+
+#elif TARGET_HOST_WIN32 || TARGET_HOST_WINCE
+
+ {
+ RECT winRect;
+
+ GetWindowRect( fgStructure.Window->Window.Handle, &winRect );
+ MoveWindow(
+ fgStructure.Window->Window.Handle,
+ x,
+ y,
+ winRect.right - winRect.left,
+ winRect.bottom - winRect.top,
+ TRUE
+ );
+ }
+
+#endif
+}
+
+/*
+ * Lowers the current window (by Z order change)
+ */
+void FGAPIENTRY glutPushWindow( void )
+{
+ freeglut_assert_ready;
+ freeglut_assert_window;
+
+#if TARGET_HOST_UNIX_X11
+
+ XLowerWindow( fgDisplay.Display, fgStructure.Window->Window.Handle );
+
+#elif TARGET_HOST_WIN32 || TARGET_HOST_WINCE
+
+ SetWindowPos(
+ fgStructure.Window->Window.Handle,
+ HWND_BOTTOM,
+ 0, 0, 0, 0,
+ SWP_NOSIZE | SWP_NOMOVE
+ );
+
+#endif
+}
+
+/*
+ * Raises the current window (by Z order change)
+ */
+void FGAPIENTRY glutPopWindow( void )
+{
+ freeglut_assert_ready;
+ freeglut_assert_window;
+
+#if TARGET_HOST_UNIX_X11
+
+ XRaiseWindow( fgDisplay.Display, fgStructure.Window->Window.Handle );
+
+#elif TARGET_HOST_WIN32 || TARGET_HOST_WINCE
+
+ SetWindowPos(
+ fgStructure.Window->Window.Handle,
+ HWND_TOP,
+ 0, 0, 0, 0,
+ SWP_NOSIZE | SWP_NOMOVE
+ );
+
+#endif
+}
+
+/*
+ * Resize the current window so that it fits the whole screen
+ */
+void FGAPIENTRY glutFullScreen( void )
+{
+ freeglut_assert_ready;
+ freeglut_assert_window;
+
+ {
+#if TARGET_HOST_UNIX_X11
+ int x, y;
+ Window w;
+
+ XMoveResizeWindow(
+ fgDisplay.Display,
+ fgStructure.Window->Window.Handle,
+ 0, 0,
+ fgDisplay.ScreenWidth,
+ fgDisplay.ScreenHeight
+ );
+
+ XFlush( fgDisplay.Display ); /* This is needed */
+
+ XTranslateCoordinates(
+ fgDisplay.Display,
+ fgStructure.Window->Window.Handle,
+ fgDisplay.RootWindow,
+ 0, 0, &x, &y, &w
+ );
+
+ if (x || y)
+ {
+ XMoveWindow(
+ fgDisplay.Display,
+ fgStructure.Window->Window.Handle,
+ -x, -y
+ );
+ XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */
+ }
+#elif TARGET_HOST_WIN32
+ RECT rect;
+
+ /* For fullscreen mode, force the top-left corner to 0,0
+ * and adjust the window rectangle so that the client area
+ * covers the whole screen.
+ */
+
+ rect.left = 0;
+ rect.top = 0;
+ rect.right = fgDisplay.ScreenWidth;
+ rect.bottom = fgDisplay.ScreenHeight;
+
+ AdjustWindowRect ( &rect, WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS |
+ WS_CLIPCHILDREN, FALSE );
+
+ /*
+ * SWP_NOACTIVATE Do not activate the window
+ * SWP_NOOWNERZORDER Do not change position in z-order
+ * SWP_NOSENDCHANGING Supress WM_WINDOWPOSCHANGING message
+ * SWP_NOZORDER Retains the current Z order (ignore 2nd param)
+ */
+
+ SetWindowPos( fgStructure.Window->Window.Handle,
+ HWND_TOP,
+ rect.left,
+ rect.top,
+ rect.right - rect.left,
+ rect.bottom - rect.top,
+ SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING |
+ SWP_NOZORDER
+ );
+#endif
+ }
+}
+
+/*
+ * A.Donev: Set and retrieve the window's user data
+ */
+void* FGAPIENTRY glutGetWindowData( void )
+{
+ return fgStructure.Window->UserData;
+}
+
+void FGAPIENTRY glutSetWindowData(void* data)
+{
+ fgStructure.Window->UserData = data;
+}
+
+/*** END OF FILE ***/
Index: external/trimesh/gluit/glui_img_spinup_0.c
--- external/trimesh/gluit/glui_img_spinup_0.c (revision 0)
+++ external/trimesh/gluit/glui_img_spinup_0.c (revision 0)
@@ -0,0 +1,24 @@
+
+
+int glui_img_spinup_0[] = { 12, 8, /* width, height */
+ 255,255,255, 127,127,127, 127,127,127, 127,127,127, 127,127,127,
+ 127,127,127, 127,127,127, 127,127,127, 127,127,127, 127,127,127,
+ 127,127,127, 0, 0, 0, 255,255,255, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 127,127,127, 0, 0, 0, 255,255,255,
+ 191,191,191, 191,191,191, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 127,127,127, 191,191,191, 127,127,127,
+ 0, 0, 0, 255,255,255, 191,191,191, 191,191,191, 191,191,191,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 127,127,127, 191,191,191,
+ 191,191,191, 127,127,127, 0, 0, 0, 255,255,255, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 0, 0, 0, 127,127,127,
+ 191,191,191, 191,191,191, 191,191,191, 127,127,127, 0, 0, 0,
+ 255,255,255, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 127,127,127, 0, 0, 0, 255,255,255, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 0, 0, 0, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255,
+};
Index: external/trimesh/gluit/glui_quaternion.h
--- external/trimesh/gluit/glui_quaternion.h (revision 0)
+++ external/trimesh/gluit/glui_quaternion.h (revision 0)
@@ -0,0 +1,97 @@
+/**************************************************************************
+
+ quaternion.h
+
+ A quaternion class
+
+ ---------------------------------------------------------------------
+
+ Feb 1998, Paul Rademacher (rademach(a)cs.unc.edu)
+
+**************************************************************************/
+
+#ifndef _QUATERNION_H_
+#define _QUATERNION_H_
+
+#include "glui_algebra3.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+
+/* this line defines a new type: pointer to a function which returns a */
+/* float and takes as argument a float */
+typedef float (*V_FCT_PTR)(float);
+
+
+/****************************************************************
+* Quaternion *
+****************************************************************/
+
+class quat
+{
+ /*protected: */
+public:
+
+ vec3 v; /* vector component */
+ float s; /* scalar component */
+
+ /*public: */
+
+ /* Constructors */
+
+ quat(void);
+ quat(const float x, const float y, const float z, const float w);
+ quat( vec3 v, float s );
+ quat( float s, vec3 v );
+ quat(const float *d ); /* copy from four-element float array */
+ quat(const double *f ); /* copy from four-element double array */
+ quat(const quat &q ); /* copy from other quat */
+
+ /* Assignment operators */
+
+ quat &operator = ( const quat &v ); /* assignment of a quat */
+ quat &operator += ( const quat &v ); /* incrementation by a quat */
+ quat &operator -= ( const quat &v ); /* decrementation by a quat */
+ quat &operator *= ( const float d ); /* multiplication by a constant */
+ quat &operator /= ( const float d ); /* division by a constant */
+ float &operator [] ( int i); /* indexing */
+
+ /* special functions */
+
+ float length(void); /* length of a quat */
+ float length2(void); /* squared length of a quat */
+ quat &normalize(void); /* normalize a quat */
+ quat &apply(V_FCT_PTR fct); /* apply a func. to each component */
+ void set( float x, float y, float z ); /* set quat */
+ void set( vec3 v, float s ); /* set quat */
+ void print( FILE *file, char *name ); /* print quat to a file */
+ vec3 xform( const vec3 &v ); /* q*v*q-1 */
+ mat4 to_mat4( void );
+ void set_angle( float f ); /* set rot angle (degrees) */
+ void scale_angle( float f ); /* scale rot angle (degrees) */
+ float get_angle( void ); /* set rot angle (degrees) */
+ vec3 get_axis( void ); /* get axis */
+
+ /* friends */
+
+ friend quat operator - (const quat &v); /* -q1 */
+ friend quat operator + (const quat &a, const quat &b); /* q1 + q2 */
+ friend quat operator - (const quat &a, const quat &b); /* q1 - q2 */
+ friend quat operator * (const quat &a, const float d); /* q1 * 3.0 */
+ friend quat operator * (const float d, const quat &a); /* 3.0 * q1 */
+ friend quat operator * (const quat &a, const quat &b); /* q1 * q2 */
+ friend quat operator / (const quat &a, const float d); /* q1 / 3.0 */
+ friend int operator == (const quat &a, const quat &b); /* q1 == q2 ? */
+ friend int operator != (const quat &a, const quat &b); /* q1 != q2 ? */
+ friend void swap(quat &a, quat &b); /* swap q1 &q2
*/
+ /*friend quat min(const quat &a, const quat &b); -- min(q1, q2) */
+ /*friend quat max(const quat &a, const quat &b); -- max(q1, q2) */
+ friend quat prod(const quat &a, const quat &b); /* term by term mult */
+ };
+
+/* Utility functions */
+
+quat quat_identity( void ); /* Returns quaternion identity element */
+quat quat_slerp( quat from, quat to, float t );
+
+#endif
Index: external/trimesh/gluit/glui_edittext.cc
--- external/trimesh/gluit/glui_edittext.cc (revision 0)
+++ external/trimesh/gluit/glui_edittext.cc (revision 0)
@@ -0,0 +1,1045 @@
+/****************************************************************************
+
+ GLUI User Interface Toolkit
+ ---------------------------
+
+ glui_edittext.cpp - GLUI_EditText control class
+
+
+ --------------------------------------------------
+
+ Copyright (c) 1998 Paul Rademacher
+
+ This program is freely distributable without licensing fees and is
+ provided without guarantee or warrantee expressed or implied. This
+ program is -not- in the public domain.
+
+*****************************************************************************/
+
+#include "glui.h"
+#include "glui_stdinc.h"
+
+/****************************** GLUI_EditText::mouse_down_handler() **********/
+
+int GLUI_EditText::mouse_down_handler( int local_x, int local_y )
+{
+ int tmp_insertion_pt;
+
+ if ( debug ) dump( stdout, "-> MOUSE DOWN" );
+
+ tmp_insertion_pt = find_insertion_pt( local_x, local_y );
+ if ( tmp_insertion_pt == -1 ) {
+ if ( glui )
+ glui->disactivate_current_control( );
+ return false;
+ }
+
+ insertion_pt = tmp_insertion_pt;
+
+ sel_start = sel_end = insertion_pt;
+
+ if ( can_draw())
+ update_and_draw_text();
+
+ if ( debug ) dump( stdout, "<- MOUSE UP" );
+
+ return true;
+}
+
+
+/******************************** GLUI_EditText::mouse_up_handler() **********/
+
+int GLUI_EditText::mouse_up_handler( int local_x, int local_y, int inside )
+{
+ return false;
+}
+
+
+/***************************** GLUI_EditText::mouse_held_down_handler() ******/
+
+int GLUI_EditText::mouse_held_down_handler( int local_x, int local_y,
+ int new_inside)
+{
+ int tmp_pt;
+
+ if ( NOT new_inside )
+ return false;
+
+ if ( debug ) dump( stdout, "-> HELD DOWN" );
+
+ tmp_pt = find_insertion_pt( local_x, local_y );
+
+ if ( tmp_pt == -1 AND sel_end != 0 ) { /* moved mouse past left edge */
+ special_handler( GLUT_KEY_LEFT, GLUT_ACTIVE_SHIFT );
+ }
+ else if ( tmp_pt == substring_end+1 AND sel_end != (int) strlen(text)) {
+ /* moved mouse past right edge */
+ special_handler( GLUT_KEY_RIGHT, GLUT_ACTIVE_SHIFT );
+ }
+ else if ( tmp_pt != -1 AND tmp_pt != sel_end ) {
+ sel_end = insertion_pt = tmp_pt;
+
+ update_and_draw_text();
+ }
+
+ if ( debug )
+ dump( stdout, "<- HELD DOWN" );
+
+ return false;
+}
+
+
+/****************************** GLUI_EditText::key_handler() **********/
+
+int GLUI_EditText::key_handler( unsigned char key,int modifiers )
+{
+ int i, regular_key;
+ /* int has_selection; */
+
+ if ( NOT glui )
+ return false;
+
+ if ( debug )
+ dump( stdout, "-> KEY HANDLER" );
+
+ regular_key = false;
+ /* has_selection = (sel_start != sel_end); */
+
+ if ( key == 21 AND (modifiers & GLUT_ACTIVE_CTRL )!=0) { /* DEL all text */
+ /** This one (key==21) may not port!! */
+
+ insertion_pt = -1;
+ text[0] = '\0';
+ sel_start = sel_end = -1;
+ }
+ else if ( key == 13 ) { /* RETURN */
+ /* glui->disactivate_current_control(); */
+ disactivate(); /** Force callbacks, etc **/
+ activate(GLUI_ACTIVATE_TAB); /** Reselect all text **/
+ translate_and_draw_front();
+ return true;
+ }
+ else if ( key == 27 ) { /* ESCAPE */
+ glui->disactivate_current_control();
+ return true;
+ }
+ else if ( key == 8 ) { /* BACKSPACE */
+ if ( sel_start == sel_end ) { /* no selection */
+ if ( insertion_pt > 0 ) {
+ /*** See if we're deleting a period in a float data-type box ***/
+ if ( data_type == GLUI_EDITTEXT_FLOAT AND text[insertion_pt-1]=='.' )
+ num_periods--;
+
+ /*** Shift over string first ***/
+ insertion_pt--;
+ for( i=insertion_pt; i< (int)strlen( text ); i++ )
+ text[i] = text[i+1];
+ }
+ }
+ else { /* There is a selection */
+ clear_substring( MIN(sel_start,sel_end), MAX(sel_start,sel_end ));
+ insertion_pt = MIN(sel_start,sel_end);
+ sel_start = sel_end = insertion_pt;
+ }
+ }
+ else { /* Regular key */
+ regular_key = true;
+
+ /** Check if we only accept numbers **/
+ if (data_type == GLUI_EDITTEXT_FLOAT ) {
+ if ( (key < '0' OR key > '9') AND key != '.' AND key
!= '-' )
+ return true;
+
+ if ( key == '-' ) { /* User typed a '-' */
+
+ /* If user has first character selected, then '-' is allowed */
+ if ( NOT ( MIN(sel_start,sel_end) == 0 AND
+ MAX(sel_start,sel_end) > 0 ) ) {
+
+ /* User does not have 1st char selected */
+ if (insertion_pt != 0 OR text[0] == '-' ) {
+ return true; /* Can only place negative at beginning of text,
+ and only one of them */
+ }
+ }
+ }
+
+ if ( key == '.' ) {
+ /*printf( "PERIOD: %d\n", num_periods ); */
+
+ if ( num_periods > 0 ) {
+ /** We're trying to type a period, but the text already contains
+ a period. Check whether the period is contained within
+ is current selection (thus it will be safely replaced) **/
+
+ int period_found = false;
+ if ( sel_start != sel_end ) {
+ for( i=MIN(sel_end,sel_start); i<MAX(sel_start,sel_end); i++ ) {
+ /* printf( "%c ", text[i] ); */
+ if ( text[i] == '.' ) {
+ period_found = true;
+ break;
+ }
+ }
+ }
+
+ /* printf( "found: %d num: %d\n", period_found, num_periods );
*/
+
+ if ( NOT period_found )
+ return true;
+ }
+ }
+ }
+ else if (data_type == GLUI_EDITTEXT_INT)
+ {
+ if ( (key < '0' OR key > '9') AND key != '-' )
+ return true;
+
+ if ( key == '-' ) { /* User typed a '-' */
+
+ /* If user has first character selected, then '-' is allowed */
+ if ( NOT ( MIN(sel_start,sel_end) == 0 AND
+ MAX(sel_start,sel_end) > 0 ) ) {
+
+ /* User does not have 1st char selected */
+ if (insertion_pt != 0 OR text[0] == '-' ) {
+ return true; /* Can only place negative at beginning of text,
+ and only one of them */
+ }
+ }
+ }
+ }
+
+ /** This is just to get rid of warnings - the flag regular_key is
+ set if the key was not a backspace, return, whatever. But I
+ believe if we're here, we know it was a regular key anyway */
+ if ( regular_key ) {
+ }
+
+ /**** If there's a current selection, erase it ******/
+ if ( sel_start != sel_end ) {
+ clear_substring( MIN(sel_start,sel_end), MAX(sel_start,sel_end ));
+ insertion_pt = MIN(sel_start,sel_end);
+ sel_start = sel_end = insertion_pt;
+ }
+
+ /******** check whether we have space ******/
+ if ( (unsigned int)strlen( text ) + 2 >= sizeof( GLUI_String ))
+ return false;
+
+ /******** We insert the character into the string ***/
+
+ /*** Shift over string first ***/
+ for( i=(int)strlen( text ); i >= insertion_pt; i-- )
+ text[i+1] = text[i];
+
+ /******** Now insert the character ********/
+ text[insertion_pt] = key;
+
+ /******** Move the insertion point and substring_end one over ******/
+ insertion_pt++;
+ substring_end++;
+
+ sel_start = sel_end = insertion_pt;
+ }
+
+ /******** Now redraw text ***********/
+ /* Hack to prevent text box from being cleared first **/
+ /** int substring_change = update_substring_bounds();
+ draw_text_only =
+ (NOT substring_change AND NOT has_selection AND regular_key );
+ */
+
+ draw_text_only = false; /** Well, hack is not yet working **/
+ update_and_draw_text();
+ draw_text_only = false;
+
+
+ if ( debug )
+ dump( stdout, "<- KEY HANDLER" );
+
+ /*** Now look to see if this string has a period ***/
+ num_periods = 0;
+ for( i=0; i<(int)strlen(text); i++ )
+ if ( text[i] == '.' )
+ num_periods++;
+
+ return true;
+}
+
+
+/****************************** GLUI_EditText::activate() **********/
+
+void GLUI_EditText::activate( int how )
+{
+ if ( debug )
+ dump( stdout, "-> ACTIVATE" );
+
+ active = true;
+
+ if ( how == GLUI_ACTIVATE_MOUSE )
+ return; /* Don't select everything if activated with mouse */
+
+ strcpy( orig_text, text );
+
+ sel_start = 0;
+ sel_end = (int)strlen(text);
+ insertion_pt = 0;
+
+ if ( debug )
+ dump( stdout, "<- ACTIVATE" );
+}
+
+
+/****************************** GLUI_EditText::disactivate() **********/
+
+void GLUI_EditText::disactivate( void )
+{
+ int new_int_val;
+ float new_float_val;
+
+ active = false;
+
+ if ( NOT glui )
+ return;
+
+ if ( debug )
+ dump( stdout, "-> DISACTIVATE" );
+
+ sel_start = sel_end = insertion_pt = -1;
+
+ /***** Retrieve the current value from the text *****/
+ /***** The live variable will be updated by set_text() ****/
+ if ( data_type == GLUI_EDITTEXT_FLOAT ) {
+ if ( text[0] == '\0' ) /* zero-length string - make it "0.0" */
+ strcpy( text, "0.0" );
+
+ new_float_val = atof( text );
+
+ set_float_val( new_float_val );
+ }
+ else if ( data_type == GLUI_EDITTEXT_INT ) {
+ if ( text[0] == '\0' ) /* zero-length string - make it "0" */
+ strcpy( text, "0" );
+
+ new_int_val = atoi( text );
+
+ set_int_val( new_int_val );
+ }
+ else
+ if ( data_type == GLUI_EDITTEXT_TEXT ) {
+ set_text(text); /* This will force callbacks and gfx refresh */
+ }
+
+ update_substring_bounds();
+
+ /******** redraw text without insertion point ***********/
+ translate_and_draw_front();
+
+ /***** Now do callbacks if value changed ******/
+ if ( strcmp( orig_text, text ) != 0 ) {
+ this->execute_callback();
+
+ if ( 0 ) {
+ /* THE CODE BELOW IS FROM WHEN SPINNER ALSO MAINTAINED CALLBACKS */
+ if ( spinner == NULL ) { /** Are we independent of a spinner? **/
+ if ( callback ) {
+ callback( this->user_id );
+ }
+ }
+ else { /* We're attached to a spinner */
+ spinner->do_callbacks(); /* Let the spinner do the callback stuff */
+ }
+ }
+ }
+
+ if ( debug )
+ dump( stdout, "<- DISACTIVATE" );
+}
+
+/****************************** GLUI_EditText::draw() **********/
+
+void GLUI_EditText::draw( int x, int y )
+{
+ int orig;
+ int name_x;
+
+ if ( NOT can_draw() )
+ return;
+
+ orig = set_to_glut_window();
+
+ name_x = MAX(text_x_offset - string_width(this->name) - 3,0);
+ draw_name( name_x , 13);
+
+ glBegin( GL_LINES );
+ glColor3f( .5, .5, .5 );
+ glVertex2i( text_x_offset, 0 ); glVertex2i( w, 0 );
+ glVertex2i( text_x_offset, 0 ); glVertex2i( text_x_offset, h );
+
+ glColor3f( 1., 1., 1. );
+ glVertex2i( text_x_offset, h ); glVertex2i( w, h );
+ glVertex2i( w, h ); glVertex2i( w, 0 );
+
+ if ( enabled )
+ glColor3f( 0., 0., 0. );
+ else
+ glColor3f( .25, .25, .25 );
+ glVertex2i( text_x_offset+1, 1 ); glVertex2i( w-1, 1 );
+ glVertex2i( text_x_offset+1, 1 ); glVertex2i( text_x_offset+1, h-1 );
+
+ glColor3f( .75, .75, .75 );
+ glVertex2i( text_x_offset+1, h-1 ); glVertex2i( w-1, h-1 );
+ glVertex2i( w-1, h-1 ); glVertex2i( w-1, 1 );
+ glEnd();
+
+ /** Find where to draw the text **/
+ update_substring_bounds();
+ draw_text(0,0);
+
+ draw_insertion_pt();
+
+ restore_window(orig);
+}
+
+
+
+/************************** GLUI_EditText::update_substring_bounds() *********/
+
+int GLUI_EditText::update_substring_bounds( void )
+{
+ int box_width;
+ int text_len = (int)strlen(text);
+ int old_start, old_end;
+
+ old_start = substring_start;
+ old_end = substring_end;
+
+ /*** Calculate the width of the usable area of the edit box ***/
+ box_width = MAX( this->w - this->text_x_offset
+ - 4 /* 2 * the two-line box border */
+ - 2 * GLUI_EDITTEXT_BOXINNERMARGINX, 0 );
+
+ CLAMP( substring_end, 0, MAX(text_len-1,0) );
+ CLAMP( substring_start, 0, MAX(text_len-1,0) );
+
+ if ( debug ) dump( stdout, "-> UPDATE SS" );
+
+ if ( insertion_pt >= 0 AND
+ insertion_pt < substring_start ) { /* cursor moved left */
+ substring_start = insertion_pt;
+
+ while ( substring_width( substring_start, substring_end ) > box_width )
+ substring_end--;
+ }
+ else if ( insertion_pt > substring_end ) { /* cursor moved right */
+ substring_end = insertion_pt-1;
+
+ while ( substring_width( substring_start, substring_end ) > box_width )
+ substring_start++;
+ }
+ else { /* cursor is within old substring bounds */
+ if ( last_insertion_pt > insertion_pt ) { /* cursor moved left */
+ }
+ else {
+ while ( substring_width( substring_start, substring_end ) > box_width )
+ substring_end--;
+
+ while(substring_width( substring_start, substring_end+1 ) <= box_width
+ AND substring_end < text_len-1 )
+ substring_end++;
+ }
+ }
+
+ while ( substring_width( substring_start, substring_end ) > box_width )
+ substring_end--;
+
+ last_insertion_pt = insertion_pt;
+
+ /*** No selection if not enabled ***/
+ if ( NOT enabled ) {
+ sel_start = sel_end = 0;
+ }
+
+ if ( debug ) dump( stdout, "<- UPDATE SS" );
+
+ if ( substring_start == old_start AND substring_end == old_end )
+ return false; /*** bounds did not change ***/
+ else
+ return true; /*** bounds did change ***/
+}
+
+
+/********************************* GLUI_EditText::update_x_offsets() *********/
+
+void GLUI_EditText::update_x_offsets( void )
+{
+}
+
+
+/********************************* GLUI_EditText::draw_text() ****************/
+
+void GLUI_EditText::draw_text( int x, int y )
+{
+ int text_x, i, sel_lo, sel_hi;
+ int orig;
+
+ if ( NOT can_draw() )
+ return;
+
+ if ( debug ) dump( stdout, "-> DRAW_TEXT" );
+
+ orig = set_to_glut_window();
+
+ if ( NOT draw_text_only ) {
+ if ( enabled )
+ glColor3f( 1., 1., 1. );
+ else
+ set_to_bkgd_color();
+ glDisable( GL_CULL_FACE );
+ glBegin( GL_QUADS );
+ glVertex2i( text_x_offset+2, 2 ); glVertex2i( w-2, 2 );
+ glVertex2i( w-2, h-2 ); glVertex2i( text_x_offset+2, h-2 );
+ glEnd();
+ }
+
+ /** Find where to draw the text **/
+
+ text_x = text_x_offset + 2 + GLUI_EDITTEXT_BOXINNERMARGINX;
+
+ /*printf( "text_x: %d substr_width: %d start/end: %d/%d\n",
+ text_x, substring_width( substring_start, substring_end ),
+ substring_start, substring_end );
+ */
+ /** Find lower and upper selection bounds **/
+ sel_lo = MIN(sel_start, sel_end );
+ sel_hi = MAX(sel_start, sel_end );
+
+ int sel_x_start, sel_x_end, delta;
+
+ /** Draw selection area dark **/
+ if ( sel_start != sel_end ) {
+ sel_x_start = text_x;
+ sel_x_end = text_x;
+ for( i=substring_start; i<=substring_end; i++ ) {
+ delta = char_width( text[i] );
+
+ if ( i < sel_lo ) {
+ sel_x_start += delta;
+ sel_x_end += delta;
+ }
+ else if ( i < sel_hi ) {
+ sel_x_end += delta;
+ }
+ }
+
+ glColor3f( 0.0f, 0.0f, .6f );
+ glBegin( GL_QUADS );
+ glVertex2i( sel_x_start, 2 ); glVertex2i( sel_x_end, 2 );
+ glVertex2i( sel_x_end, h-2 ); glVertex2i( sel_x_start, h-2 );
+ glEnd();
+ }
+
+
+ if ( sel_start == sel_end ) { /* No current selection */
+ if ( enabled )
+ glColor3b( 0, 0, 0 );
+ else
+ glColor3b( 32, 32, 32 );
+
+ glRasterPos2i( text_x, 13);
+ for( i=substring_start; i<=substring_end; i++ ) {
+ glutBitmapCharacter( get_font(), this->text[i] );
+ }
+ }
+ else { /* There is a selection */
+ int x = text_x;
+ for( i=substring_start; i<=substring_end; i++ ) {
+ if ( IN_BOUNDS( i, sel_lo, sel_hi-1)) { /* This character is selected */
+ glColor3f( 1., 1., 1. );
+ glRasterPos2i( x, 13);
+ glutBitmapCharacter( get_font(), this->text[i] );
+ }
+ else {
+ glColor3f( 0., 0., 0. );
+ glRasterPos2i( x, 13);
+ glutBitmapCharacter( get_font(), this->text[i] );
+ }
+
+ x += char_width( text[i] );
+ }
+ }
+
+ restore_window( orig );
+
+ if ( debug ) dump( stdout, "<- DRAW_TEXT" );
+}
+
+
+/******************************** GLUI_EditText::find_insertion_pt() *********/
+/* This function returns the character numer *before which* the insertion */
+/* point goes */
+
+int GLUI_EditText::find_insertion_pt( int x, int y )
+{
+ int curr_x, i;
+
+ /*** See if we clicked outside box ***/
+ if ( x < this->x_abs + text_x_offset )
+ return -1;
+
+ /* We move from right to left, looking to see if the mouse was clicked
+ to the right of the ith character */
+
+ curr_x = this->x_abs + text_x_offset
+ + substring_width( substring_start, substring_end )
+ + 2 /* The edittext box has a 2-pixel margin */
+ + GLUI_EDITTEXT_BOXINNERMARGINX; /** plus this many pixels blank space
+ between the text and the box **/
+
+ /*** See if we clicked in an empty box ***/
+ if ( (int)strlen( text ) == 0 )
+ return 0;
+
+ /** find mouse click in text **/
+ for( i=substring_end; i>=substring_start; i-- ) {
+ curr_x -= char_width( text[i] );
+
+ if ( x > curr_x ) {
+ /* printf( "-> %d\n", i ); */
+
+ return i+1;
+ }
+ }
+
+ return 0;
+
+ /* Well, the mouse wasn't after any of the characters...see if it's
+ before the beginning of the substring */
+ if ( 0 ) {
+ if ( x > (x_abs + text_x_offset + 2 ) )
+ return substring_start;
+
+ return -1; /* Nothing found */
+ }
+}
+
+
+/******************************** GLUI_EditText::draw_insertion_pt() *********/
+
+void GLUI_EditText::draw_insertion_pt( void )
+{
+ int curr_x, i;
+
+ if ( NOT can_draw() )
+ return;
+
+ /*** Don't draw insertion pt if control is disabled ***/
+ if ( NOT enabled )
+ return;
+
+ if ( debug ) dump( stdout, "-> DRAW_INS_PT" );
+
+ if ( sel_start != sel_end OR insertion_pt < 0 ) {
+ return; /* Don't draw insertion point if there is a current selection */
+ }
+
+ /* printf( "insertion pt: %d\n", insertion_pt ); */
+
+ curr_x = this->x_abs + text_x_offset
+ + substring_width( substring_start, substring_end )
+ + 2 /* The edittext box has a 2-pixel margin */
+ + GLUI_EDITTEXT_BOXINNERMARGINX; /** plus this many pixels blank space
+ between the text and the box **/
+
+ for( i=substring_end; i>=insertion_pt; i-- ) {
+ curr_x -= char_width( text[i] );
+ }
+
+ glColor3f( 0.0, 0.0, 0.0 );
+ glBegin( GL_LINE_LOOP );
+ /***
+ glVertex2i( curr_x, y_abs + 4 );
+ glVertex2i( curr_x, y_abs + 4 );
+ glVertex2i( curr_x, y_abs + h - 3 );
+ glVertex2i( curr_x, y_abs + h - 3 );
+ ***/
+ curr_x -= x_abs;
+ glVertex2i( curr_x, 0 + 4 );
+ glVertex2i( curr_x, 0 + 4 );
+ glVertex2i( curr_x, 0 + h - 3 );
+ glVertex2i( curr_x, 0 + h - 3 );
+ glEnd();
+
+ if ( debug ) dump( stdout, "-> DRAW_INS_PT" );
+}
+
+
+
+/******************************** GLUI_EditText::substring_width() *********/
+
+int GLUI_EditText::substring_width( int start, int end )
+{
+ int i, width;
+
+ width = 0;
+
+ for( i=start; i<=end; i++ )
+ width += char_width( text[i] );
+
+ return width;
+}
+
+
+/***************************** GLUI_EditText::update_and_draw_text() ********/
+
+void GLUI_EditText::update_and_draw_text( void )
+{
+ if ( NOT can_draw() )
+ return;
+
+ update_substring_bounds();
+ /* printf( "ss: %d/%d\n", substring_start, substring_end );
*/
+
+ translate_and_draw_front();
+}
+
+
+/********************************* GLUI_EditText::special_handler() **********/
+
+int GLUI_EditText::special_handler( int key,int modifiers )
+{
+ if ( NOT glui )
+ return false;
+
+ if ( debug )
+ printf( "SPECIAL:%d - mod:%d subs:%d/%d ins:%d sel:%d/%d\n",
+ key, modifiers, substring_start, substring_end,insertion_pt,
+ sel_start, sel_end );
+
+ if ( key == GLUT_KEY_LEFT ) {
+ if ( (modifiers & GLUT_ACTIVE_CTRL) != 0 ) {
+ insertion_pt = find_word_break( insertion_pt, -1 );
+ }
+ else {
+ insertion_pt--;
+ }
+ }
+ else if ( key == GLUT_KEY_RIGHT ) {
+ if ( (modifiers & GLUT_ACTIVE_CTRL) != 0 ) {
+ insertion_pt = find_word_break( insertion_pt, +1 );
+ }
+ else {
+ insertion_pt++;
+ }
+ }
+ else if ( key == GLUT_KEY_HOME ) {
+ insertion_pt = 0;
+ }
+ else if ( key == GLUT_KEY_END ) {
+ insertion_pt = (int)strlen( text );
+ }
+
+ /*** Update selection if shift key is down ***/
+ if ( (modifiers & GLUT_ACTIVE_SHIFT ) != 0 )
+ sel_end = insertion_pt;
+ else
+ sel_start = sel_end = insertion_pt;
+
+
+ CLAMP( insertion_pt, 0, (int)strlen( text )); /* Make sure insertion_pt
+ is in bounds */
+ CLAMP( sel_start, 0, (int)strlen( text )); /* Make sure insertion_pt
+ is in bounds */
+ CLAMP( sel_end, 0, (int)strlen( text )); /* Make sure insertion_pt
+ is in bounds */
+
+ /******** Now redraw text ***********/
+ if ( can_draw())
+ update_and_draw_text();
+
+ return true;
+}
+
+
+/****************************** GLUI_EditText::find_word_break() **********/
+/* It looks either left or right (depending on value of 'direction' */
+/* for the beginning of the next 'word', where word are characters */
+/* separated by one of the following tokens: " :-.," */
+/* If there is no next word in the specified direction, this returns */
+/* the beginning of 'text', or the very end. */
+
+int GLUI_EditText::find_word_break( int start, int direction )
+{
+ int i, j;
+ char *breaks = " :-.,";
+ int num_break_chars = (int)strlen(breaks), text_len = (int)strlen(text);
+ int new_pt;
+
+ /** If we're moving left, we have to start two back, in case we're either
+ already at the beginning of a word, or on a separating token.
+ Otherwise, this function would just return the word we're already at **/
+ if ( direction == -1 ) {
+ start -= 2;
+ }
+
+ /***** Iterate over text in the specified direction *****/
+ for ( i=start; i >= 0 AND i < text_len; i += direction ) {
+
+ /** For each character in text, iterate over list of separating tokens **/
+ for( j=0; j<num_break_chars; j++ ) {
+ if ( text[i] == breaks[j] ) {
+
+ /** character 'i' is a separating token, so we return i+1 **/
+ new_pt = i + 1;
+
+ CLAMP( new_pt, 0, text_len );
+
+ return new_pt;
+ }
+ }
+ }
+
+ if ( direction > 0 ) /* Return the end of string */
+ return text_len;
+ else /* Return the beginning of the text */
+ return 0;
+}
+
+
+/********************************** GLUI_EditText::clear_substring() ********/
+
+void GLUI_EditText::clear_substring( int start, int end )
+{
+ int i, leftover;
+
+ /*
+ printf( "clearing: %d-%d '", start,end);
+ for(i=start;i<end;i++ )
+ putchar(text[i]);
+ printf( "'\n" ); flushout;
+ */
+ /*** See if we're deleting a period in a float data-type box ***/
+ if ( data_type == GLUI_EDITTEXT_FLOAT ) {
+ for( i=start; i<end; i++ )
+ if ( text[i] == '.' )
+ num_periods = 0;
+ }
+
+ /*** Shift over string ***/
+ leftover = (int)strlen(text) - (end);
+
+ /* printf( "leftover: %d - ", leftover ); */
+
+ for( i=0; i<leftover+1; i++ )
+ text[start+i] = text[end+i];
+
+ /* printf( "final string: '%s'\n", text ); */
+}
+
+
+
+/************************************ GLUI_EditText::update_size() **********/
+
+void GLUI_EditText::update_size( void )
+{
+ int text_size, delta;
+
+ if ( NOT glui )
+ return;
+
+ text_size = string_width( name );
+
+ delta = 0;
+ if ( text_x_offset < text_size +2 )
+ delta = text_size+2-text_x_offset;
+
+ text_x_offset += delta;
+ /* w += delta; */
+
+ if ( data_type == GLUI_EDITTEXT_TEXT OR
+ data_type == GLUI_EDITTEXT_FLOAT) {
+ if ( w < text_x_offset + GLUI_EDITTEXT_MIN_TEXT_WIDTH )
+ w = text_x_offset + GLUI_EDITTEXT_MIN_TEXT_WIDTH;
+ }
+ else if ( data_type == GLUI_EDITTEXT_INT ) {
+ if ( w < text_x_offset + GLUI_EDITTEXT_MIN_INT_WIDTH )
+ w = text_x_offset + GLUI_EDITTEXT_MIN_INT_WIDTH;
+ }
+}
+
+
+/****************************** GLUI_EditText::set_text() **********/
+
+void GLUI_EditText::set_text( char *new_text )
+{
+ strncpy(text,new_text,sizeof(GLUI_String));
+ substring_start = 0;
+ substring_end = (int)strlen( text ) - 1;
+ insertion_pt = -1;
+ sel_start = 0;
+ sel_end = 0;
+
+ if ( can_draw() )
+ update_and_draw_text();
+
+ /** Update the spinner, if we have one **/
+ if ( spinner ) {
+ spinner->float_val = this->float_val;
+ spinner->int_val = this->int_val;
+ }
+
+ /*** Now update the live variable ***/
+ output_live(true);
+}
+
+
+/******************************* GLUI_EditText::set_float_val() ************/
+
+void GLUI_EditText::set_float_val( float new_val )
+{
+ if ( has_limits == GLUI_LIMIT_CLAMP ) {
+ /*** Clamp the new value to the existing limits ***/
+
+ CLAMP( new_val, float_low, float_high );
+ }
+ else if ( has_limits == GLUI_LIMIT_WRAP ) {
+ /*** Clamp the value cyclically to the limits - that is, if the
+ value exceeds the max, set it the the minimum, and conversely ***/
+
+ if ( new_val < float_low )
+ new_val = float_high;
+ if ( new_val > float_high )
+ new_val = float_low;
+ }
+
+ float_val = new_val;
+ int_val = (int) new_val; /* Mirror the value as an int, too */
+
+ set_numeric_text();
+}
+
+
+/********************************** GLUI_EditText::set_int_val() ************/
+
+void GLUI_EditText::set_int_val( int new_val )
+{
+ if ( has_limits == GLUI_LIMIT_CLAMP ) {
+ /*** Clamp the new value to the existing limits ***/
+
+ CLAMP( new_val, int_low, int_high );
+ }
+ else if ( has_limits == GLUI_LIMIT_WRAP ) {
+ /*** Clamp the value cyclically to the limits - that is, if the
+ value exceeds the max, set it the the minimum, and conversely ***/
+
+ if ( new_val < int_low )
+ new_val = int_high;
+ if ( new_val > int_high )
+ new_val = int_low;
+ }
+
+ int_val = new_val;
+ float_val = (float) new_val; /* We mirror the value as a float, too */
+
+ set_numeric_text();
+}
+
+
+/********************************* GLUI_EditText::set_float_limits() *********/
+
+void GLUI_EditText::set_float_limits( float low, float high, int limit_type )
+{
+ has_limits = limit_type;
+ float_low = low;
+ float_high = high;
+
+ if ( NOT IN_BOUNDS( float_val, float_low, float_high ))
+ set_float_val( float_low );
+
+ int_low = (int) float_low;
+ int_high = (int) float_high;
+}
+
+
+/*********************************** GLUI_EditText::set_int_limits() *********/
+
+void GLUI_EditText::set_int_limits( int low, int high, int limit_type )
+{
+ has_limits = limit_type;
+ int_low = low;
+ int_high = high;
+
+ if ( NOT IN_BOUNDS( int_val, int_low, int_high ))
+ set_int_val( int_low );
+
+ float_low = (float) int_low;
+ float_high = (float) int_high;
+}
+
+
+/************************************ GLUI_EditText::set_numeric_text() ******/
+
+void GLUI_EditText::set_numeric_text( void )
+{
+ char buf_float[200], buf_int[200];
+ int i, text_len;
+
+ if ( data_type == GLUI_EDITTEXT_FLOAT ) {
+ sprintf( buf_float, "%#g", float_val );
+
+ num_periods = 0;
+ text_len = (int)strlen( buf_float );
+ for ( i=0; i<text_len; i++ )
+ if ( buf_float[i] == '.' )
+ num_periods++;
+
+ /* Now remove trailing zeros */
+ if ( num_periods > 0 ) {
+ text_len = (int)strlen( buf_float );
+ for ( i=text_len-1; i>0; i-- ) {
+ if ( buf_float[i] == '0' AND buf_float[i-1] != '.' )
+ buf_float[i] = '\0';
+ else
+ break;
+ }
+ }
+
+ set_text( buf_float );
+ }
+ else {
+ sprintf( buf_int, "%d", int_val );
+
+ set_text( buf_int );
+ }
+
+}
+
+
+/*************************************** GLUI_EditText::dump() **************/
+
+void GLUI_EditText::dump( FILE *out, char *name )
+{
+ fprintf( out,
+ "%s (edittext@%p): ins_pt:%d subs:%d/%d sel:%d/%d len:%d\n",
+ name, this,
+ insertion_pt, substring_start, substring_end, sel_start, sel_end,
+ (int)strlen( text ));
+}
+
+
+/**************************************** GLUI_EditText::mouse_over() ********/
+
+int GLUI_EditText::mouse_over( int state, int x, int y )
+{
+ if ( state ) {
+ /* curr_cursor = GLUT_CURSOR_TEXT; */
+ glutSetCursor( GLUT_CURSOR_TEXT );
+ }
+ else {
+ /* printf( "OUT\n" ); */
+ glutSetCursor( GLUT_CURSOR_LEFT_ARROW );
+ }
+
+ return true;
+}
Index: external/trimesh/gluit/freeglut_internal.h
--- external/trimesh/gluit/freeglut_internal.h (revision 0)
+++ external/trimesh/gluit/freeglut_internal.h (revision 0)
@@ -0,0 +1,854 @@
+/*
+ * freeglut_internal.h
+ *
+ * The freeglut library private include file.
+ *
+ * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
+ * Written by Pawel W. Olszta, <olszta(a)sourceforge.net>
+ * Creation date: Thu Dec 2 1999
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef FREEGLUT_INTERNAL_H
+#define FREEGLUT_INTERNAL_H
+
+/* XXX Update these for each release! */
+#define VERSION_MAJOR 2
+#define VERSION_MINOR 2
+#define VERSION_PATCH 0
+
+/*
+ * Freeglut is meant to be available under all Unix/X11 and Win32 platforms.
+ */
+#if defined(_WIN32_WCE)
+# define TARGET_HOST_UNIX_X11 0
+# define TARGET_HOST_WIN32 0
+# define TARGET_HOST_WINCE 1
+#elif defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__)
+# define TARGET_HOST_UNIX_X11 0
+# define TARGET_HOST_WIN32 1
+# define TARGET_HOST_WINCE 0
+#else
+# define TARGET_HOST_UNIX_X11 1
+# define TARGET_HOST_WIN32 0
+# define TARGET_HOST_WINCE 0
+#endif
+
+#define FREEGLUT_MAX_MENUS 3
+
+/*
+ * Somehow all Win32 include headers depend on this one:
+ */
+#if TARGET_HOST_WIN32
+#include <windows.h>
+#include <windowsx.h>
+#include <mmsystem.h>
+#include <tchar.h>
+#endif
+
+#if defined(_MSC_VER)
+#define strdup _strdup
+#endif
+
+/*
+ * Those files should be available on every platform.
+ */
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <stdarg.h>
+#if TARGET_HOST_UNIX_X11
+#include <unistd.h>
+#include <sys/time.h>
+#endif
+
+/*
+ * The system-dependant include files should go here:
+ */
+#if TARGET_HOST_UNIX_X11
+ #include <GL/glx.h>
+ #include <X11/Xlib.h>
+ #include <X11/Xatom.h>
+ #include <X11/keysym.h>
+
+ #ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H
+ #include <X11/extensions/xf86vmode.h>
+ #endif
+#endif
+
+/*
+ * Microsoft VisualC++ 5.0's <math.h> does not define the PI
+ */
+#ifndef M_PI
+# define M_PI 3.14159265358979323846
+#endif
+
+#ifndef TRUE
+# define TRUE 1
+#endif
+
+#ifndef FALSE
+# define FALSE 0
+#endif
+
+/* -- GLOBAL TYPE DEFINITIONS ---------------------------------------------- */
+
+/*
+ * Freeglut callbacks type definitions
+ */
+typedef void (* FGCBDisplay )( void );
+typedef void (* FGCBReshape )( int, int );
+typedef void (* FGCBVisibility )( int );
+typedef void (* FGCBKeyboard )( unsigned char, int, int );
+typedef void (* FGCBSpecial )( int, int, int );
+typedef void (* FGCBMouse )( int, int, int, int );
+typedef void (* FGCBMouseWheel )( int, int, int, int );
+typedef void (* FGCBMotion )( int, int );
+typedef void (* FGCBPassive )( int, int );
+typedef void (* FGCBEntry )( int );
+typedef void (* FGCBWindowStatus )( int );
+typedef void (* FGCBSelect )( int, int, int );
+typedef void (* FGCBJoystick )( unsigned int, int, int, int );
+typedef void (* FGCBKeyboardUp )( unsigned char, int, int );
+typedef void (* FGCBSpecialUp )( int, int, int );
+typedef void (* FGCBOverlayDisplay)( void );
+typedef void (* FGCBSpaceMotion )( int, int, int );
+typedef void (* FGCBSpaceRotation )( int, int, int );
+typedef void (* FGCBSpaceButton )( int, int );
+typedef void (* FGCBDials )( int, int );
+typedef void (* FGCBButtonBox )( int, int );
+typedef void (* FGCBTabletMotion )( int, int );
+typedef void (* FGCBTabletButton )( int, int, int, int );
+typedef void (* FGCBDestroy )( void );
+
+/*
+ * The global callbacks type definitions
+ */
+typedef void (* FGCBIdle )( void );
+typedef void (* FGCBTimer )( int );
+typedef void (* FGCBMenuState )( int );
+typedef void (* FGCBMenuStatus )( int, int, int );
+
+/*
+ * The callback used when creating/using menus
+ */
+typedef void (* FGCBMenu )( int );
+
+
+/*
+ * A list structure
+ */
+typedef struct tagSFG_List SFG_List;
+struct tagSFG_List
+{
+ void *First;
+ void *Last;
+};
+
+/*
+ * A list node structure
+ */
+typedef struct tagSFG_Node SFG_Node;
+struct tagSFG_Node
+{
+ void *Next;
+ void *Prev;
+};
+
+/*
+ * A helper structure holding two ints and a boolean
+ */
+typedef struct tagSFG_XYUse SFG_XYUse;
+struct tagSFG_XYUse
+{
+ GLint X, Y; /* The two integers... */
+ GLboolean Use; /* ...and a single boolean. */
+};
+
+/*
+ * A helper structure holding a timeval and a boolean
+ */
+typedef struct tagSFG_Time SFG_Time;
+struct tagSFG_Time
+{
+#ifdef WIN32
+ DWORD Value;
+#else
+ struct timeval Value;
+#endif
+ GLboolean Set;
+};
+
+/*
+ * An enumeration containing the state of the GLUT execution:
+ * initializing, running, or stopping
+ */
+typedef enum
+{
+ GLUT_EXEC_STATE_INIT,
+ GLUT_EXEC_STATE_RUNNING,
+ GLUT_EXEC_STATE_STOP
+} fgExecutionState ;
+
+/*
+ * This structure holds different freeglut settings
+ */
+typedef struct tagSFG_State SFG_State;
+struct tagSFG_State
+{
+ SFG_XYUse Position; /* The default windows' position */
+ SFG_XYUse Size; /* The default windows' size */
+ unsigned int DisplayMode; /* Display mode for new windows */
+
+ GLboolean Initialised; /* freeglut has been initialised */
+
+ int DirectContext; /* Direct rendering state */
+
+ GLboolean ForceIconic; /* New top windows are iconified */
+ GLboolean UseCurrentContext; /* New windows share with current */
+
+ GLboolean GLDebugSwitch; /* OpenGL state debugging switch */
+ GLboolean XSyncSwitch; /* X11 sync protocol switch */
+
+ int KeyRepeat; /* Global key repeat mode. */
+ int Modifiers; /* Current ALT/SHIFT/CTRL state */
+
+ GLuint FPSInterval; /* Interval between FPS printfs */
+ GLuint SwapCount; /* Count of glutSwapBuffer calls */
+ GLuint SwapTime; /* Time of last SwapBuffers */
+
+ SFG_Time Time; /* Time that glutInit was called */
+ SFG_List Timers; /* The freeglut timer hooks */
+ SFG_List FreeTimers; /* The unused timer hooks */
+
+ FGCBIdle IdleCallback; /* The global idle callback */
+
+ int ActiveMenus; /* Num. of currently active menus */
+ FGCBMenuState MenuStateCallback; /* Menu callbacks are global */
+ FGCBMenuStatus MenuStatusCallback;
+
+ SFG_XYUse GameModeSize; /* Game mode screen's dimensions */
+ int GameModeDepth; /* The pixel depth for game mode */
+ int GameModeRefresh; /* The refresh rate for game mode */
+
+ int ActionOnWindowClose; /* Action when user closes window */
+
+ fgExecutionState ExecState; /* Used for GLUT termination */
+ char *ProgramName; /* Name of the invoking program */
+};
+
+/*
+ * The structure used by display initialization in freeglut_init.c
+ */
+typedef struct tagSFG_Display SFG_Display;
+struct tagSFG_Display
+{
+#if TARGET_HOST_UNIX_X11
+ Display* Display; /* The display we are being run in. */
+ int Screen; /* The screen we are about to use. */
+ Window RootWindow; /* The screen's root window. */
+ int Connection; /* The display's connection number */
+ Atom DeleteWindow; /* The window deletion atom */
+
+#ifdef X_XF86VidModeGetModeLine
+ /*
+ * XF86VidMode may be compilable even if it fails at runtime. Therefore,
+ * the validity of the VidMode has to be tracked
+ */
+ int DisplayModeValid; /* Flag that indicates runtime status*/
+ XF86VidModeModeLine DisplayMode; /* Current screen's display settings */
+ int DisplayModeClock; /* The display mode's refresh rate */
+ int DisplayViewPortX; /* saved X location of the viewport */
+ int DisplayViewPortY; /* saved Y location of the viewport */
+ int DisplayPointerX; /* saved X location of the pointer */
+ int DisplayPointerY; /* saved Y location of the pointer */
+
+#endif
+
+#elif TARGET_HOST_WIN32 || TARGET_HOST_WINCE
+ HINSTANCE Instance; /* The application's instance */
+ DEVMODE DisplayMode; /* Desktop's display settings */
+
+#endif
+
+ int ScreenWidth; /* The screen's width in pixels */
+ int ScreenHeight; /* The screen's height in pixels */
+ int ScreenWidthMM; /* The screen's width in milimeters */
+ int ScreenHeightMM; /* The screen's height in milimeters */
+};
+
+
+/*
+ * The user can create any number of timer hooks
+ */
+typedef struct tagSFG_Timer SFG_Timer;
+struct tagSFG_Timer
+{
+ SFG_Node Node;
+ int ID; /* The timer ID integer */
+ FGCBTimer Callback; /* The timer callback */
+ long TriggerTime; /* The timer trigger time */
+};
+
+/*
+ * Make "freeglut" window handle and context types so that we don't need
so
+ * much conditionally-compiled code later in the library.
+ */
+#if TARGET_HOST_UNIX_X11
+
+typedef Window SFG_WindowHandleType ;
+typedef GLXContext SFG_WindowContextType ;
+
+#elif TARGET_HOST_WIN32 || TARGET_HOST_WINCE
+
+typedef HWND SFG_WindowHandleType ;
+typedef HGLRC SFG_WindowContextType ;
+
+#endif
+
+/*
+ * A window and its OpenGL context. The contents of this structure
+ * are highly dependant on the target operating system we aim at...
+ */
+typedef struct tagSFG_Context SFG_Context;
+struct tagSFG_Context
+{
+ SFG_WindowHandleType Handle; /* The window's handle */
+ SFG_WindowContextType Context; /* The window's OpenGL/WGL context */
+
+#if TARGET_HOST_UNIX_X11
+ XVisualInfo* VisualInfo; /* The window's visual information */
+ Pixmap Pixmap; /* Used for offscreen rendering */
+ /* GLXPixmap GLXPixMap; */ /* Used for offscreen rendering */
+#elif TARGET_HOST_WIN32 || TARGET_HOST_WINCE
+ HDC Device; /* The window's device context */
+#endif
+
+ int DoubleBuffered; /* Treat the window as double-buffered */
+};
+
+/*
+ * Window's state description. This structure should be kept portable.
+ */
+typedef struct tagSFG_WindowState SFG_WindowState;
+struct tagSFG_WindowState
+{
+ int Width; /* Window's width in pixels */
+ int Height; /* The same about the height */
+ int OldWidth; /* Window width from before a resize */
+ int OldHeight; /* " height " " "
" */
+
+ GLboolean Redisplay; /* Do we have to redisplay? */
+ GLboolean Visible; /* Is the window visible now */
+
+ int Cursor; /* The currently selected cursor */
+
+ long JoystickPollRate; /* The joystick polling rate */
+ long JoystickLastPoll; /* When the last poll happened */
+
+ int MouseX, MouseY; /* The most recent mouse position */
+
+ GLboolean IgnoreKeyRepeat; /* Whether to ignore key repeat. */
+ GLboolean KeyRepeating; /* Currently in repeat mode */
+
+ GLboolean IsGameMode; /* Is this the game mode window? */
+ GLboolean NeedToResize; /* Do we need to resize the window? */
+};
+
+
+/*
+ * SET_WCB() is used as:
+ *
+ * SET_WCB( window, Visibility, func );
+ *
+ * ...where {window} is the freeglut window to set the callback,
+ * {Visibility} is the window-specific callback to set,
+ * {func} is a function-pointer.
+ *
+ * Originally, {FETCH_WCB( ... ) = func} was rather sloppily used,
+ * but this can cause warnings because the FETCH_WCB() macro type-
+ * casts its result, and a type-cast value shouldn't be an lvalue.
+ *
+ * The {if( FETCH_WCB( ... ) != func )} test is to do type-checking
+ * and for no other reason. Since it's hidden in the macro, the
+ * ugliness is felt to be rather benign.
+ */
+#define SET_WCB(window,cbname,func) \
+do \
+{ \
+ if( FETCH_WCB( window, cbname ) != func ) \
+ (((window).CallBacks[CB_ ## cbname]) = (void *) func); \
+} while( 0 ) \
+
+/*
+ * FETCH_WCB() is used as:
+ *
+ * FETCH_WCB( window, Visibility );
+ *
+ * ...where {window} is the freeglut window to fetch the callback from,
+ * {Visibility} is the window-specific callback to fetch.
+ *
+ * The result is correctly type-cast to the callback function pointer
+ * type.
+ */
+#define FETCH_WCB(window,cbname) \
+ ((FGCB ## cbname)((window).CallBacks[CB_ ## cbname]))
+
+/*
+ * INVOKE_WCB() is used as:
+ *
+ * INVOKE_WCB( window, Visibility, ( status ) );
+ *
+ * ...where {window} is the freeglut window,
+ * {Visibility} is the window-specific callback,
+ * {(status)} is the parameter list.
+ *
+ * The callback is invoked as:
+ *
+ * callback( status );
+ *
+ * ...so the parentheses are REQUIRED in the {arg_list}.
+ *
+ * NOTE that it does a sanity-check and also sets the
+ * current window.
+ *
+ */
+#define INVOKE_WCB(window,cbname,arg_list) \
+do \
+{ \
+ if( FETCH_WCB( window, cbname ) ) \
+ { \
+ fgSetWindow( &window ); \
+ FETCH_WCB( window, cbname ) arg_list; \
+ } \
+} while( 0 )
+
+/*
+ * The window callbacks the user can supply us with. Should be kept portable.
+ *
+ * This enumeration provides the freeglut CallBack numbers.
+ * The symbolic constants are indices into a window's array of
+ * function callbacks. The names are formed by splicing a common
+ * prefix onto the callback's base name. (This was originally
+ * done so that an early stage of development could live side-by-
+ * side with the old callback code. The old callback code used
+ * the bare callback's name as a structure member, so I used a
+ * prefix for the array index name.)
+ *
+ * XXX For consistancy, perhaps the prefix should match the
+ * XXX FETCH* and INVOKE* macro suffices. I.e., WCB_, rather than
+ * XXX CB_.
+ */
+enum
+{
+ CB_Display,
+ CB_Reshape,
+ CB_Keyboard,
+ CB_KeyboardUp,
+ CB_Special,
+ CB_SpecialUp,
+ CB_Mouse,
+ CB_MouseWheel,
+ CB_Motion,
+ CB_Passive,
+ CB_Entry,
+ CB_Visibility,
+ CB_WindowStatus,
+ CB_Joystick,
+ CB_Destroy,
+
+ /* Presently ignored */
+ CB_Select,
+ CB_OverlayDisplay,
+ CB_SpaceMotion,
+ CB_SpaceRotation,
+ CB_SpaceButton,
+ CB_Dials,
+ CB_ButtonBox,
+ CB_TabletMotion,
+ CB_TabletButton,
+
+ /* Always make this the LAST one */
+ TOTAL_CALLBACKS
+};
+
+
+/*
+ * This structure holds the OpenGL rendering context for all the menu windows
+ */
+typedef struct tagSFG_MenuContext SFG_MenuContext;
+struct tagSFG_MenuContext
+{
+#if TARGET_HOST_UNIX_X11
+ XVisualInfo* VisualInfo; /* The window's visual information */
+#endif
+
+ SFG_WindowContextType Context; /* The menu window's WGL context */
+};
+
+/*
+ * This structure describes a menu
+ */
+typedef struct tagSFG_Window SFG_Window;
+typedef struct tagSFG_MenuEntry SFG_MenuEntry;
+typedef struct tagSFG_Menu SFG_Menu;
+struct tagSFG_Menu
+{
+ SFG_Node Node;
+ void *UserData; /* User data passed back at callback */
+ int ID; /* The global menu ID */
+ SFG_List Entries; /* The menu entries list */
+ FGCBMenu Callback; /* The menu callback */
+ FGCBDestroy Destroy; /* Destruction callback */
+ GLboolean IsActive; /* Is the menu selected? */
+ int Width; /* Menu box width in pixels */
+ int Height; /* Menu box height in pixels */
+ int X, Y; /* Menu box raster position */
+
+ SFG_MenuEntry *ActiveEntry; /* Currently active entry in the menu */
+ SFG_Window *Window; /* Window for menu */
+ SFG_Window *ParentWindow; /* Window in which the menu is defined */
+};
+
+/*
+ * This is a menu entry
+ */
+struct tagSFG_MenuEntry
+{
+ SFG_Node Node;
+ int ID; /* The menu entry ID (local) */
+ int Ordinal; /* The menu's ordinal number */
+ char* Text; /* The text to be displayed */
+ SFG_Menu* SubMenu; /* Optional sub-menu tree */
+ GLboolean IsActive; /* Is the entry highlighted? */
+ int Width; /* Label's width in pixels */
+};
+
+/*
+ * A window, making part of freeglut windows hierarchy.
+ * Should be kept portable.
+ */
+struct tagSFG_Window
+{
+ SFG_Node Node;
+ int ID; /* Window's ID number */
+
+ SFG_Context Window; /* Window and OpenGL context */
+ SFG_WindowState State; /* The window state */
+ void *CallBacks[ TOTAL_CALLBACKS ]; /* Array of window callbacks */
+ void *UserData ; /* For use by user */
+
+ SFG_Menu* Menu[ FREEGLUT_MAX_MENUS ]; /* Menus appended to window */
+ SFG_Menu* ActiveMenu; /* The window's active menu */
+
+ SFG_Window* Parent; /* The parent to this window */
+ SFG_List Children; /* The subwindows d.l. list */
+
+ GLboolean IsMenu; /* Set to 1 if we are a menu */
+};
+
+
+/*
+ * A linked list structure of windows
+ */
+typedef struct tagSFG_WindowList SFG_WindowList ;
+struct tagSFG_WindowList
+{
+ SFG_Node node;
+ SFG_Window *window ;
+};
+
+/*
+ * This holds information about all the windows, menus etc.
+ */
+typedef struct tagSFG_Structure SFG_Structure;
+struct tagSFG_Structure
+{
+ SFG_List Windows; /* The global windows list */
+ SFG_List Menus; /* The global menus list */
+ SFG_List WindowsToDestroy;
+
+ SFG_Window* Window; /* The currently active win. */
+ SFG_Menu* Menu; /* Same, but menu... */
+
+ SFG_MenuContext* MenuContext; /* OpenGL rendering context for menus */
+
+ SFG_Window* GameMode; /* The game mode window */
+
+ int WindowID; /* The new current window ID */
+ int MenuID; /* The new current menu ID */
+};
+
+/*
+ * This structure is used for the enumeration purposes.
+ * You can easily extend its functionalities by declaring
+ * a structure containing enumerator's contents and custom
+ * data, then casting its pointer to (SFG_Enumerator *).
+ */
+typedef struct tagSFG_Enumerator SFG_Enumerator;
+struct tagSFG_Enumerator
+{
+ GLboolean found; /* Used to terminate search */
+ void* data; /* Custom data pointer */
+};
+typedef void (* FGCBenumerator )( SFG_Window *, SFG_Enumerator * );
+
+/*
+ * The bitmap font structure
+ */
+typedef struct tagSFG_Font SFG_Font;
+struct tagSFG_Font
+{
+ char* Name; /* The source font name */
+ int Quantity; /* Number of chars in font */
+ int Height; /* Height of the characters */
+ const GLubyte** Characters; /* The characters mapping */
+
+ float xorig, yorig; /* Relative origin of the character */
+};
+
+/*
+ * The stroke font structures
+ */
+
+typedef struct tagSFG_StrokeVertex SFG_StrokeVertex;
+struct tagSFG_StrokeVertex
+{
+ GLfloat X, Y;
+};
+
+typedef struct tagSFG_StrokeStrip SFG_StrokeStrip;
+struct tagSFG_StrokeStrip
+{
+ int Number;
+ const SFG_StrokeVertex* Vertices;
+};
+
+typedef struct tagSFG_StrokeChar SFG_StrokeChar;
+struct tagSFG_StrokeChar
+{
+ GLfloat Right;
+ int Number;
+ const SFG_StrokeStrip* Strips;
+};
+
+typedef struct tagSFG_StrokeFont SFG_StrokeFont;
+struct tagSFG_StrokeFont
+{
+ char* Name; /* The source font name */
+ int Quantity; /* Number of chars in font */
+ GLfloat Height; /* Height of the characters */
+ const SFG_StrokeChar** Characters; /* The characters mapping */
+};
+
+/* -- GLOBAL VARIABLES EXPORTS --------------------------------------------- */
+
+/*
+ * Freeglut display related stuff (initialized once per session)
+ */
+extern SFG_Display fgDisplay;
+
+/*
+ * Freeglut internal structure
+ */
+extern SFG_Structure fgStructure;
+
+/*
+ * The current freeglut settings
+ */
+extern SFG_State fgState;
+
+
+/* -- PRIVATE FUNCTION DECLARATIONS ---------------------------------------- */
+
+/*
+ * A call to this function makes us sure that the Display and Structure
+ * subsystems have been properly initialized and are ready to be used
+ */
+#define freeglut_assert_ready assert( fgState.Initialised );
+
+/*
+ * Following definitions are somewhat similiar to GLib's,
+ * but do not generate any log messages:
+ */
+#define freeglut_return_if_fail( expr ) \
+ if( !(expr) ) \
+ return;
+#define freeglut_return_val_if_fail( expr, val ) \
+ if( !(expr) ) \
+ return val ;
+
+/*
+ * A call to those macros assures us that there is a current
+ * window and menu set, respectively:
+ */
+#define freeglut_assert_window assert( fgStructure.Window != NULL );
+#define freeglut_assert_menu assert( fgStructure.Menu != NULL );
+
+/*
+ * The initialize and deinitialize functions get called on glutInit()
+ * and glutMainLoop() end respectively. They should create/clean up
+ * everything inside of the freeglut
+ */
+void fgInitialize( const char* displayName );
+void fgDeinitialize( void );
+
+/*
+ * Those two functions are used to create/destroy the freeglut internal
+ * structures. This actually happens when calling glutInit() and when
+ * quitting the glutMainLoop() (which actually happens, when all windows
+ * have been closed).
+ */
+void fgCreateStructure( void );
+void fgDestroyStructure( void );
+
+/*
+ * A helper function to check if a display mode is possible to use
+ */
+#if TARGET_HOST_UNIX_X11
+XVisualInfo* fgChooseVisual( void );
+#endif
+
+/*
+ * The window procedure for Win32 events handling
+ */
+#if TARGET_HOST_WIN32 || TARGET_HOST_WINCE
+LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg,
+ WPARAM wParam, LPARAM lParam );
+GLboolean fgSetupPixelFormat( SFG_Window* window, GLboolean checkOnly,
+ unsigned char layer_type );
+#endif
+
+/*
+ * Window creation, opening, closing and destruction.
+ * Also CallBack clearing/initialization.
+ * Defined in freeglut_structure.c, freeglut_window.c.
+ */
+SFG_Window* fgCreateWindow( SFG_Window* parent, const char* title,
+ int x, int y, int w, int h,
+ GLboolean gameMode, GLboolean isMenu );
+void fgSetWindow ( SFG_Window *window );
+void fgOpenWindow( SFG_Window* window, const char* title,
+ int x, int y, int w, int h, GLboolean gameMode,
+ GLboolean isSubWindow );
+void fgCloseWindow( SFG_Window* window );
+void fgAddToWindowDestroyList ( SFG_Window* window );
+void fgCloseWindows ();
+void fgDestroyWindow( SFG_Window* window );
+void fgClearCallBacks( SFG_Window *window );
+
+/*
+ * Menu creation and destruction. Defined in freeglut_structure.c
+ */
+SFG_Menu* fgCreateMenu( FGCBMenu menuCallback );
+void fgDestroyMenu( SFG_Menu* menu );
+
+/*
+ * Joystick device management functions, defined in freeglut_joystick.c
+ */
+void fgJoystickInit( int ident );
+void fgJoystickClose( void );
+void fgJoystickPollWindow( SFG_Window* window );
+
+/*
+ * Helper function to enumerate through all registered windows
+ * and one to enumerate all of a window's subwindows...
+ *
+ * The GFunc callback for those functions will be defined as:
+ *
+ * void enumCallback( gpointer window, gpointer enumerator );
+ *
+ * where window is the enumerated (sub)window pointer (SFG_Window *),
+ * and userData is the a custom user-supplied pointer. Functions
+ * are defined and exported from freeglut_structure.c file.
+ */
+void fgEnumWindows( FGCBenumerator enumCallback, SFG_Enumerator* enumerator );
+void fgEnumSubWindows( SFG_Window* window, FGCBenumerator enumCallback,
+ SFG_Enumerator* enumerator );
+
+/*
+ * fgWindowByHandle returns a (SFG_Window *) value pointing to the
+ * first window in the queue matching the specified window handle.
+ * The function is defined in freeglut_structure.c file.
+ */
+SFG_Window* fgWindowByHandle( SFG_WindowHandleType hWindow );
+
+/*
+ * This function is similiar to the previous one, except it is
+ * looking for a specified (sub)window identifier. The function
+ * is defined in freeglut_structure.c file.
+ */
+SFG_Window* fgWindowByID( int windowID );
+
+/*
+ * Looks up a menu given its ID. This is easier than fgWindowByXXX
+ * as all menus are placed in a single doubly linked list...
+ */
+SFG_Menu* fgMenuByID( int menuID );
+
+/*
+ * The menu activation and deactivation the code. This is the meat
+ * of the menu user interface handling code...
+ */
+void fgActivateMenu( SFG_Window* window, int button );
+void fgExecuteMenuCallback( SFG_Menu* menu );
+GLboolean fgCheckActiveMenu ( SFG_Window *window, SFG_Menu *menu );
+void fgDeactivateMenu( SFG_Window *window );
+void fgDeactivateSubMenu( SFG_MenuEntry *menuEntry );
+
+/*
+ * This function gets called just before the buffers swap, so that
+ * freeglut can display the pull-down menus via OpenGL. The function
+ * is defined in freeglut_menu.c file.
+ */
+void fgDisplayMenu( void );
+
+/*
+ * Display the mouse cursor using OpenGL calls. The function
+ * is defined in freeglut_cursor.c file.
+ */
+void fgDisplayCursor( void );
+
+/*
+ * Elapsed time as per glutGet(GLUT_ELAPSED_TIME).
+ */
+long fgElapsedTime( void );
+
+/*
+ * List functions
+ */
+void fgListInit(SFG_List *list);
+void fgListAppend(SFG_List *list, SFG_Node *node);
+void fgListRemove(SFG_List *list, SFG_Node *node);
+int fgListLength(SFG_List *list);
+void fgListInsert(SFG_List *list, SFG_Node *next, SFG_Node *node);
+
+/*
+ * Error Messages functions
+ */
+void fgError( const char *fmt, ... );
+void fgWarning( const char *fmt, ... );
+
+#endif /* FREEGLUT_INTERNAL_H */
+
+/*** END OF FILE ***/
Index: external/trimesh/gluit/glui_statictext.cc
--- external/trimesh/gluit/glui_statictext.cc (revision 0)
+++ external/trimesh/gluit/glui_statictext.cc (revision 0)
@@ -0,0 +1,124 @@
+/****************************************************************************
+
+ GLUI User Interface Toolkit
+ ---------------------------
+
+ glui_statictext.cpp - GLUI_StaticText Control
+
+
+ --------------------------------------------------
+
+ Copyright (c) 1998 Paul Rademacher
+
+ This program is freely distributable without licensing fees and is
+ provided without guarantee or warrantee expressed or implied. This
+ program is -not- in the public domain.
+
+*****************************************************************************/
+
+#include "glui.h"
+#include "glui_stdinc.h"
+
+/****************************** GLUI_StaticText::draw() **********/
+
+void GLUI_StaticText::draw( int x, int y )
+{
+ int orig;
+
+ if ( NOT can_draw() )
+ return;
+
+ orig = set_to_glut_window();
+
+ draw_text();
+
+ restore_window( orig );
+}
+
+
+/****************************** GLUI_StaticText::set_text() **********/
+
+void GLUI_StaticText::set_text( char *text )
+{
+ int orig = 0;
+
+ if (strcmp(text,name) == 0) return;
+
+ if ( can_draw() )
+ {
+ /**** Erase old text first *****/
+ orig = set_to_glut_window();
+
+ glMatrixMode( GL_MODELVIEW );
+ glPushMatrix();
+ translate_to_origin();
+ erase_text();
+ glPopMatrix();
+ }
+
+ /* Copy text */
+ int old_w = w;
+ strncpy((char*)name,text,sizeof(GLUI_String));
+ update_size();
+ if ((w != old_w)&&(glui)) glui->refresh();
+
+ if ( can_draw() )
+ {
+
+ /**** Redraw the text in the window ****/
+ glMatrixMode( GL_MODELVIEW );
+ glPushMatrix();
+ translate_to_origin();
+ draw_text();
+ glPopMatrix();
+
+ restore_window( orig );
+}
+}
+
+
+/************************************ GLUI_StaticText::update_size() **********/
+
+void GLUI_StaticText::update_size( void )
+{
+ int text_size;
+
+ if ( NOT glui )
+ return;
+
+ text_size = string_width( name );
+
+ if ( w < text_size )
+ w = text_size;
+}
+
+
+/****************************** GLUI_StaticText::draw_text() **********/
+
+void GLUI_StaticText::draw_text( void )
+{
+ if ( NOT can_draw() )
+ return;
+
+ erase_text();
+ draw_name( 0, 9 );
+}
+
+
+/****************************** GLUI_StaticText::erase_text() **********/
+
+void GLUI_StaticText::erase_text( void )
+{
+ if ( NOT can_draw() )
+ return;
+
+ set_to_bkgd_color();
+ glDisable( GL_CULL_FACE );
+ glBegin( GL_TRIANGLES );
+ glVertex2i( 0,0 ); glVertex2i( w, 0 ); glVertex2i( w, h );
+ glVertex2i( 0, 0 ); glVertex2i( w, h ); glVertex2i( 0, h );
+ glEnd();
+}
+
+
+
Index: external/trimesh/gluit/glui_img_checkbox_0.c
--- external/trimesh/gluit/glui_img_checkbox_0.c (revision 0)
+++ external/trimesh/gluit/glui_img_checkbox_0.c (revision 0)
@@ -0,0 +1,38 @@
+
+
+int glui_img_checkbox_0[] = { 13, 13, /* width, height */
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 128,128,128, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 255,255,255, 128,128,128, 0, 0, 0, 255,255,255, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 255,255,255, 192,192,192, 255,255,255, 128,128,128,
+ 0, 0, 0, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 192,192,192, 255,255,255, 128,128,128, 0, 0, 0, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 192,192,192, 255,255,255,
+ 128,128,128, 0, 0, 0, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 192,192,192, 255,255,255, 128,128,128, 0, 0, 0,
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 192,192,192,
+ 255,255,255, 128,128,128, 0, 0, 0, 255,255,255, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 255,255,255, 192,192,192, 255,255,255, 128,128,128,
+ 0, 0, 0, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 192,192,192, 255,255,255, 128,128,128, 0, 0, 0, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 192,192,192, 255,255,255,
+ 128,128,128, 0, 0, 0, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 192,192,192, 255,255,255, 128,128,128, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192,192,192,
+ 255,255,255, 128,128,128, 128,128,128, 128,128,128, 128,128,128,
+ 128,128,128, 128,128,128, 128,128,128, 128,128,128, 128,128,128,
+ 128,128,128, 128,128,128, 128,128,128, 255,255,255,
+};
Index: external/trimesh/gluit/glui_bitmap_img_data.cc
--- external/trimesh/gluit/glui_bitmap_img_data.cc (revision 0)
+++ external/trimesh/gluit/glui_bitmap_img_data.cc (revision 0)
@@ -0,0 +1,22 @@
+
+#include "glui_img_checkbox_0.c"
+#include "glui_img_checkbox_1.c"
+#include "glui_img_radiobutton_0.c"
+#include "glui_img_radiobutton_1.c"
+#include "glui_img_uparrow.c"
+#include "glui_img_downarrow.c"
+#include "glui_img_leftarrow.c"
+#include "glui_img_rightarrow.c"
+#include "glui_img_spinup_1.c"
+#include "glui_img_spinup_0.c"
+#include "glui_img_spindown_1.c"
+#include "glui_img_spindown_0.c"
+#include "glui_img_checkbox_0_dis.c"
+#include "glui_img_checkbox_1_dis.c"
+#include "glui_img_radiobutton_0_dis.c"
+#include "glui_img_radiobutton_1_dis.c"
+#include "glui_img_spinup_dis.c"
+#include "glui_img_spindown_dis.c"
+#include "glui_img_listbox_up.c"
+#include "glui_img_listbox_down.c"
+#include "glui_img_listbox_up_dis.c"
Index: external/trimesh/gluit/freeglut_videoresize.c
--- external/trimesh/gluit/freeglut_videoresize.c (revision 0)
+++ external/trimesh/gluit/freeglut_videoresize.c (revision 0)
@@ -0,0 +1,54 @@
+/*
+ * freeglut_videoresize.c
+ *
+ * Video resize functions (as defined by GLUT API)
+ *
+ * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
+ * Written by Pawel W. Olszta, <olszta(a)sourceforge.net>
+ * Creation date: Thu Dec 16 1999
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <GL/freeglut.h>
+#include "freeglut_internal.h"
+
+/*
+ * NOTE: functions declared in this file probably will not be implemented.
+ */
+
+/* -- INTERFACE FUNCTIONS -------------------------------------------------- */
+
+int FGAPIENTRY glutVideoResizeGet( GLenum eWhat ) { return( 0x00 ); }
+void FGAPIENTRY glutSetupVideoResizing( void ) { /* Not implemented */ }
+void FGAPIENTRY glutStopVideoResizing( void ) { /* Not implemented */ }
+void FGAPIENTRY glutVideoResize( int x, int y, int w, int h ) { /* Not implemented */ }
+void FGAPIENTRY glutVideoPan( int x, int y, int w, int h ) { /* Not implemented */ }
+
+/*** END OF FILE ***/
+
+
+
+
+
+
+
Index: external/trimesh/gluit/glui_img_radiobutton_0.c
--- external/trimesh/gluit/glui_img_radiobutton_0.c (revision 0)
+++ external/trimesh/gluit/glui_img_radiobutton_0.c (revision 0)
@@ -0,0 +1,44 @@
+
+
+int glui_img_radiobutton_0[] = { 14, 14, /* width, height */
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 255,255,255, 255,255,255, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 255,255,255, 255,255,255, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 128,128,128,
+ 192,192,192, 192,192,192, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 192,192,192, 192,192,192, 255,255,255, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 128,128,128, 0, 0, 0,
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 192,192,192, 255,255,255, 192,192,192, 192,192,192,
+ 192,192,192, 128,128,128, 0, 0, 0, 255,255,255, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 192,192,192, 255,255,255, 192,192,192, 192,192,192,
+ 128,128,128, 0, 0, 0, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 192,192,192, 255,255,255, 192,192,192, 192,192,192, 128,128,128,
+ 0, 0, 0, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 192,192,192,
+ 255,255,255, 192,192,192, 192,192,192, 128,128,128, 0, 0, 0,
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 192,192,192, 255,255,255,
+ 192,192,192, 192,192,192, 192,192,192, 128,128,128, 0, 0, 0,
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 192,192,192, 255,255,255, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 128,128,128, 0, 0, 0, 0, 0, 0,
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 0, 0, 0,
+ 0, 0, 0, 255,255,255, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 128,128,128, 128,128,128, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 128,128,128, 128,128,128,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 128,128,128, 128,128,128,
+ 128,128,128, 128,128,128, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192,
+};
Index: external/trimesh/gluit/Makefile
--- external/trimesh/gluit/Makefile (revision 0)
+++ external/trimesh/gluit/Makefile (revision 0)
@@ -0,0 +1,75 @@
+#DEBUG = y
+MAKERULESDIR = ..
+DESTDIR = ../lib.$(UNAME)
+INCLUDES = -I../include -I../include/GL
+
+include $(MAKERULESDIR)/Makerules
+
+ifeq ($(UNAME),Darwin)
+CFILES =
+else
+CFILES = freeglut_callbacks.c \
+ freeglut_cursor.c \
+ freeglut_display.c \
+ freeglut_ext.c \
+ freeglut_font.c \
+ freeglut_font_data.c \
+ freeglut_gamemode.c \
+ freeglut_geometry.c \
+ freeglut_glutfont_definitions.c \
+ freeglut_init.c \
+ freeglut_joystick.c \
+ freeglut_main.c \
+ freeglut_menu.c \
+ freeglut_misc.c \
+ freeglut_overlay.c \
+ freeglut_state.c \
+ freeglut_stroke_mono_roman.c \
+ freeglut_stroke_roman.c \
+ freeglut_structure.c \
+ freeglut_teapot.c \
+ freeglut_videoresize.c \
+ freeglut_window.c
+endif
+
+CCFILES = glui.cc \
+ glui_add_controls.cc \
+ glui_algebra3.cc \
+ glui_arcball.cc \
+ glui_bitmap_img_data.cc \
+ glui_bitmaps.cc \
+ glui_button.cc \
+ glui_checkbox.cc \
+ glui_column.cc \
+ glui_control.cc \
+ glui_edittext.cc \
+ glui_listbox.cc \
+ glui_mouse_iaction.cc \
+ glui_node.cc \
+ glui_panel.cc \
+ glui_quaternion.cc \
+ glui_radio.cc \
+ glui_rollout.cc \
+ glui_rotation.cc \
+ glui_separator.cc \
+ glui_slider.cc \
+ glui_spinner.cc \
+ glui_statictext.cc \
+ glui_translation.cc
+
+OFILES = $(addprefix $(OBJDIR)/,$(CFILES:.c=.o) $(CCFILES:.cc=.o))
+LIB = $(DESTDIR)/libgluit.a
+default: $(LIB)
+
+$(LIB): $(OFILES)
+ $(STATICLIB)
+
+clean:
+ -rm -f $(OFILES) $(OBJDIR)/Makedepend $(OBJDIR)/*.d
+ -rm -rf $(OBJDIR)/ii_files
+ -rmdir $(OBJDIR)
+
+spotless: clean
+ -rm -f $(LIB)
+ -rmdir $(DESTDIR)
+
Index: external/trimesh/gluit/freeglut_structure.c
--- external/trimesh/gluit/freeglut_structure.c (revision 0)
+++ external/trimesh/gluit/freeglut_structure.c (revision 0)
@@ -0,0 +1,651 @@
+/*
+ * freeglut_structure.c
+ *
+ * Windows and menus need tree structure
+ *
+ * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
+ * Written by Pawel W. Olszta, <olszta(a)sourceforge.net>
+ * Creation date: Sat Dec 18 1999
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <GL/freeglut.h>
+#include "freeglut_internal.h"
+
+
+/* -- GLOBAL EXPORTS ------------------------------------------------------- */
+
+/*
+ * The SFG_Structure container holds information about windows and menus
+ * created between glutInit() and glutMainLoop() return.
+ */
+
+SFG_Structure fgStructure = { { NULL, NULL }, /* The list of windows */
+ { NULL, NULL }, /* The list of menus */
+ { NULL, NULL }, /* Windows to Destroy list */
+ NULL, /* The current window */
+ NULL, /* The current menu */
+ NULL, /* The menu OpenGL context */
+ NULL, /* The game mode window */
+ 0, /* The current new window ID */
+ 0 }; /* The current new menu ID */
+
+
+/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
+
+void fgClearCallBacks( SFG_Window *window )
+{
+ if( window )
+ {
+ int i;
+ for( i = 0; i < TOTAL_CALLBACKS; ++i )
+ window->CallBacks[ i ] = NULL;
+ }
+}
+
+/*
+ * This private function creates, opens and adds to the hierarchy
+ * a freeglut window complete with OpenGL context and stuff...
+ *
+ * If parent is set to NULL, the window created will be a topmost one.
+ */
+SFG_Window* fgCreateWindow( SFG_Window* parent, const char* title,
+ int x, int y, int w, int h,
+ GLboolean gameMode, GLboolean isMenu )
+{
+ /*
+ * Have the window object created
+ */
+ SFG_Window *window = (SFG_Window *)calloc( sizeof(SFG_Window), 1 );
+ int fakeArgc = 0;
+
+ fgClearCallBacks( window );
+
+ /*
+ * If the freeglut internals haven't been initialized yet,
+ * do it now. Hack's idea courtesy of Chris Purnell...
+ */
+ if( !fgState.Initialised )
+ glutInit( &fakeArgc, NULL );
+
+ /*
+ * Initialize the object properties
+ */
+ window->ID = ++fgStructure.WindowID;
+ window->State.OldHeight = window->State.OldWidth = -1;
+
+ fgListInit( &window->Children );
+ if( parent )
+ {
+ fgListAppend( &parent->Children, &window->Node );
+ window->Parent = parent;
+ }
+ else
+ fgListAppend( &fgStructure.Windows, &window->Node );
+
+ /*
+ * Set the default mouse cursor and reset the modifiers value
+ */
+ window->State.Cursor = GLUT_CURSOR_INHERIT;
+
+ window->IsMenu = isMenu;
+
+ window->State.IgnoreKeyRepeat = GL_FALSE;
+ window->State.KeyRepeating = GL_FALSE;
+
+ /*
+ * Open the window now. The fgOpenWindow() function is system
+ * dependant, and resides in freeglut_window.c. Uses fgState.
+ */
+ fgOpenWindow( window, title, x, y, w, h, gameMode,
+ parent ? GL_TRUE : GL_FALSE );
+
+ return window;
+}
+
+/*
+ * This private function creates a menu and adds it to the menus list
+ */
+SFG_Menu* fgCreateMenu( FGCBMenu menuCallback )
+{
+ int x = 100, y = 100, w = 100, h = 100;
+ SFG_Window *current_window = fgStructure.Window;
+
+ /*
+ * Have the menu object created
+ */
+ SFG_Menu* menu = (SFG_Menu *)calloc( sizeof(SFG_Menu), 1 );
+ int fakeArgc = 0;
+
+ /*
+ * If the freeglut internals haven't been initialized yet,
+ * do it now. Hack's idea courtesy of Chris Purnell...
+ */
+ if( !fgState.Initialised )
+ glutInit( &fakeArgc, NULL );
+
+ menu->ParentWindow = fgStructure.Window;
+
+ /*
+ * Create a window for the menu to reside in.
+ */
+
+ fgCreateWindow( NULL, NULL, x, y, w, h, GL_FALSE, GL_TRUE );
+ menu->Window = fgStructure.Window;
+ glutDisplayFunc( fgDisplayMenu );
+
+ glutHideWindow( ); /* Hide the window for now */
+ fgSetWindow( current_window );
+
+ /*
+ * Initialize the object properties:
+ */
+ menu->ID = ++fgStructure.MenuID;
+ menu->Callback = menuCallback;
+ menu->ActiveEntry = NULL;
+
+ fgListInit( &menu->Entries );
+ fgListAppend( &fgStructure.Menus, &menu->Node );
+
+ /*
+ * Newly created menus implicitly become current ones
+ */
+ fgStructure.Menu = menu;
+
+ return menu;
+}
+
+/*
+ * Function to add a window to the linked list of windows to destroy.
+ * Subwindows are automatically added because they hang from the window
+ * structure.
+ */
+void fgAddToWindowDestroyList( SFG_Window* window )
+{
+ SFG_WindowList *new_list_entry =
+ ( SFG_WindowList* )malloc( sizeof(SFG_WindowList ) );
+ new_list_entry->window = window;
+ fgListAppend( &fgStructure.WindowsToDestroy, &new_list_entry->node );
+
+ /*
+ * Check if the window is the current one...
+ */
+ if( fgStructure.Window == window )
+ fgStructure.Window = NULL;
+
+ /*
+ * Clear all window callbacks except Destroy, which will
+ * be invoked later. Right now, we are potentially carrying
+ * out a freeglut operation at the behest of a client callback,
+ * so we are reluctant to re-enter the client with the Destroy
+ * callback, right now. The others are all wiped out, however,
+ * to ensure that they are no longer called after this point.
+ */
+ {
+ FGCBDestroy destroy = FETCH_WCB( *window, Destroy );
+ fgClearCallBacks( window );
+ SET_WCB( *window, Destroy, destroy );
+ }
+}
+
+/*
+ * Function to close down all the windows in the "WindowsToDestroy" list
+ */
+void fgCloseWindows( )
+{
+ while( fgStructure.WindowsToDestroy.First )
+ {
+ SFG_WindowList *window_ptr = fgStructure.WindowsToDestroy.First;
+ fgDestroyWindow( window_ptr->window );
+ fgListRemove( &fgStructure.WindowsToDestroy, &window_ptr->node );
+ free( window_ptr );
+ }
+}
+
+/*
+ * This function destroys a window and all of its subwindows. Actually,
+ * another function, defined in freeglut_window.c is called, but this is
+ * a whole different story...
+ */
+void fgDestroyWindow( SFG_Window* window )
+{
+ int menu_index;
+
+ assert( window );
+ freeglut_assert_ready;
+
+ while( window->Children.First )
+ fgDestroyWindow( ( SFG_Window * )window->Children.First );
+
+ {
+ SFG_Window *activeWindow = fgStructure.Window;
+ INVOKE_WCB( *window, Destroy, ( ) );
+ fgSetWindow( activeWindow );
+ }
+
+ if( window->Parent )
+ fgListRemove( &window->Parent->Children, &window->Node );
+ else
+ fgListRemove( &fgStructure.Windows, &window->Node );
+
+ if( window->ActiveMenu )
+ fgDeactivateMenu( window );
+
+ for( menu_index = 0; menu_index < 3; menu_index ++ )
+ if( window->Menu[ menu_index ] )
+ window->Menu[ menu_index ]->ParentWindow = NULL;
+
+ fgClearCallBacks( window );
+ fgCloseWindow( window );
+ free( window );
+ if( fgStructure.Window == window )
+ fgStructure.Window = NULL;
+}
+
+/*
+ * This is a helper static function that removes a menu (given its pointer)
+ * from any windows that can be accessed from a given parent...
+ */
+static void fghRemoveMenuFromWindow( SFG_Window* window, SFG_Menu* menu )
+{
+ SFG_Window *subWindow;
+ int i;
+
+ /*
+ * Check if the menu is attached to the current window,
+ * if so, have it detached (by overwriting with a NULL):
+ */
+ for( i = 0; i < 3; i++ )
+ if( window->Menu[ i ] == menu )
+ window->Menu[ i ] = NULL;
+
+ /*
+ * Call this function for all of the window's children recursively:
+ */
+ for( subWindow = (SFG_Window *)window->Children.First;
+ subWindow;
+ subWindow = (SFG_Window *)subWindow->Node.Next)
+ fghRemoveMenuFromWindow( subWindow, menu );
+}
+
+/*
+ * This is a static helper function that removes menu references
+ * from another menu, given two pointers to them...
+ */
+static void fghRemoveMenuFromMenu( SFG_Menu* from, SFG_Menu* menu )
+{
+ SFG_MenuEntry *entry;
+
+ for( entry = (SFG_MenuEntry *)from->Entries.First;
+ entry;
+ entry = ( SFG_MenuEntry * )entry->Node.Next )
+ if( entry->SubMenu == menu )
+ entry->SubMenu = NULL;
+}
+
+/*
+ * This function destroys a menu specified by the parameter. All menus
+ * and windows are updated to make sure no ill pointers hang around.
+ */
+void fgDestroyMenu( SFG_Menu* menu )
+{
+ SFG_Window *window;
+ SFG_Menu *from;
+
+ assert( menu );
+ freeglut_assert_ready;
+
+ /*
+ * First of all, have all references to this menu removed from all windows:
+ */
+ for( window = (SFG_Window *)fgStructure.Windows.First;
+ window;
+ window = (SFG_Window *)window->Node.Next )
+ fghRemoveMenuFromWindow( window, menu );
+
+ /*
+ * Now proceed with removing menu entries that lead to this menu
+ */
+ for( from = ( SFG_Menu * )fgStructure.Menus.First;
+ from;
+ from = ( SFG_Menu * )from->Node.Next )
+ fghRemoveMenuFromMenu( from, menu );
+
+ /*
+ * If the programmer defined a destroy callback, call it
+ * A. Donev: But first make this the active menu
+ */
+ if( menu->Destroy )
+ {
+ SFG_Menu *activeMenu=fgStructure.Menu;
+ fgStructure.Menu = menu;
+ menu->Destroy( );
+ fgStructure.Menu = activeMenu;
+ }
+
+ /*
+ * Now we are pretty sure the menu is not used anywhere
+ * and that we can remove all of its entries
+ */
+ while( menu->Entries.First )
+ {
+ SFG_MenuEntry *entry = ( SFG_MenuEntry * ) menu->Entries.First;
+
+ fgListRemove( &menu->Entries, &entry->Node );
+
+ if( entry->Text )
+ free( entry->Text );
+ entry->Text = NULL;
+
+ free( entry );
+ }
+
+ if( fgStructure.Window == menu->Window )
+ fgSetWindow( menu->ParentWindow );
+ fgDestroyWindow( menu->Window );
+ fgListRemove( &fgStructure.Menus, &menu->Node );
+ if( fgStructure.Menu == menu )
+ fgStructure.Menu = NULL;
+
+ free( menu );
+}
+
+/*
+ * This function should be called on glutInit(). It will prepare the internal
+ * structure of freeglut to be used in the application. The structure will be
+ * destroyed using fgDestroyStructure() on glutMainLoop() return. In that
+ * case further use of freeglut should be preceeded with a glutInit() call.
+ */
+void fgCreateStructure( void )
+{
+ /*
+ * We will be needing two lists: the first containing windows,
+ * and the second containing the user-defined menus.
+ * Also, no current window/menu is set, as none has been created yet.
+ */
+
+ fgListInit(&fgStructure.Windows);
+ fgListInit(&fgStructure.Menus);
+ fgListInit(&fgStructure.WindowsToDestroy);
+}
+
+/*
+ * This function is automatically called on glutMainLoop() return.
+ * It should deallocate and destroy all remnants of previous
+ * glutInit()-enforced structure initialization...
+ */
+void fgDestroyStructure( void )
+{
+ freeglut_assert_ready;
+
+ /*
+ * Clean up the WindowsToDestroy list.
+ */
+ fgCloseWindows( );
+
+ /*
+ * Make sure all windows and menus have been deallocated
+ */
+ while( fgStructure.Menus.First )
+ fgDestroyMenu( ( SFG_Menu * )fgStructure.Menus.First );
+
+ while( fgStructure.Windows.First )
+ fgDestroyWindow( ( SFG_Window * )fgStructure.Windows.First );
+}
+
+/*
+ * Helper function to enumerate through all registered top-level windows
+ */
+void fgEnumWindows( FGCBenumerator enumCallback, SFG_Enumerator* enumerator )
+{
+ SFG_Window *window;
+
+ assert( enumCallback && enumerator );
+ freeglut_assert_ready;
+
+ /*
+ * Check every of the top-level windows
+ */
+ for( window = ( SFG_Window * )fgStructure.Windows.First;
+ window;
+ window = ( SFG_Window * )window->Node.Next )
+ {
+ enumCallback( window, enumerator );
+ if( enumerator->found )
+ return;
+ }
+}
+
+/*
+ * Helper function to enumerate through all a window's subwindows
+ * (single level descent)
+ */
+void fgEnumSubWindows( SFG_Window* window, FGCBenumerator enumCallback,
+ SFG_Enumerator* enumerator )
+{
+ SFG_Window *child;
+
+ assert( enumCallback && enumerator );
+ freeglut_assert_ready;
+
+ for( child = ( SFG_Window * )window->Children.First;
+ child;
+ child = ( SFG_Window * )child->Node.Next )
+ {
+ enumCallback( child, enumerator );
+ if( enumerator->found )
+ return;
+ }
+}
+
+/*
+ * A static helper function to look for a window given its handle
+ */
+static void fghcbWindowByHandle( SFG_Window *window,
+ SFG_Enumerator *enumerator )
+{
+ if ( enumerator->found )
+ return;
+
+ /*
+ * Check the window's handle. Hope this works. Looks ugly. That's for sure.
+ */
+ if( window->Window.Handle == (SFG_WindowHandleType) (enumerator->data) )
+ {
+ enumerator->found = GL_TRUE;
+ enumerator->data = window;
+
+ return;
+ }
+
+ /*
+ * Otherwise, check this window's children
+ */
+ fgEnumSubWindows( window, fghcbWindowByHandle, enumerator );
+}
+
+/*
+ * fgWindowByHandle returns a (SFG_Window *) value pointing to the
+ * first window in the queue matching the specified window handle.
+ * The function is defined in freeglut_structure.c file.
+ */
+SFG_Window* fgWindowByHandle ( SFG_WindowHandleType hWindow )
+{
+ SFG_Enumerator enumerator;
+
+ /*
+ * This is easy and makes use of the windows enumeration defined above
+ */
+ enumerator.found = GL_FALSE;
+ enumerator.data = (void *)hWindow;
+ fgEnumWindows( fghcbWindowByHandle, &enumerator );
+
+ if( enumerator.found )
+ return( SFG_Window *) enumerator.data;
+ return NULL;
+}
+
+/*
+ * A static helper function to look for a window given its ID
+ */
+static void fghcbWindowByID( SFG_Window *window, SFG_Enumerator *enumerator )
+{
+ /*
+ * Make sure we do not overwrite our precious results...
+ */
+ if( enumerator->found )
+ return;
+
+ /*
+ * Check the window's handle. Hope this works. Looks ugly. That's for sure.
+ */
+ if( window->ID == *( int *)(enumerator->data) )
+ {
+ enumerator->found = GL_TRUE;
+ enumerator->data = window;
+
+ return;
+ }
+
+ /*
+ * Otherwise, check this window's children
+ */
+ fgEnumSubWindows( window, fghcbWindowByID, enumerator );
+}
+
+/*
+ * This function is similiar to the previous one, except it is
+ * looking for a specified (sub)window identifier. The function
+ * is defined in freeglut_structure.c file.
+ */
+SFG_Window* fgWindowByID( int windowID )
+{
+ SFG_Enumerator enumerator;
+
+ /*
+ * Uses a method very similiar for fgWindowByHandle...
+ */
+ enumerator.found = GL_FALSE;
+ enumerator.data = ( void * )&windowID;
+ fgEnumWindows( fghcbWindowByID, &enumerator );
+ if( enumerator.found )
+ return ( SFG_Window * )enumerator.data;
+ return NULL;
+}
+
+/*
+ * Looks up a menu given its ID. This is easier that fgWindowByXXX
+ * as all menus are placed in a single doubly linked list...
+ */
+SFG_Menu* fgMenuByID( int menuID )
+{
+ SFG_Menu *menu = NULL;
+
+ freeglut_assert_ready;
+
+ /*
+ * It's enough to check all entries in fgStructure.Menus...
+ */
+ for( menu = (SFG_Menu *)fgStructure.Menus.First;
+ menu;
+ menu = (SFG_Menu *)menu->Node.Next )
+ if( menu->ID == menuID )
+ return menu;
+ return NULL;
+}
+
+/*
+ * List functions...
+ */
+void fgListInit(SFG_List *list)
+{
+ list->First = NULL;
+ list->Last = NULL;
+}
+
+void fgListAppend(SFG_List *list, SFG_Node *node)
+{
+ if ( list->Last )
+ {
+ SFG_Node *ln = (SFG_Node *) list->Last;
+ ln->Next = node;
+ node->Prev = ln;
+ }
+ else
+ {
+ node->Prev = NULL;
+ list->First = node;
+ }
+
+ node->Next = NULL;
+ list->Last = node;
+}
+
+void fgListRemove(SFG_List *list, SFG_Node *node)
+{
+ if( node->Next )
+ ( ( SFG_Node * )node->Next )->Prev = node->Prev;
+ if( node->Prev )
+ ( ( SFG_Node * )node->Prev )->Next = node->Next;
+ if( ( ( SFG_Node * )list->First ) == node )
+ list->First = node->Next;
+ if( ( ( SFG_Node * )list->Last ) == node )
+ list->Last = node->Prev;
+}
+
+int fgListLength(SFG_List *list)
+{
+ SFG_Node *node;
+ int length = 0;
+
+ for( node =( SFG_Node * )list->First;
+ node;
+ node = ( SFG_Node * )node->Next )
+ ++length;
+
+ return length;
+}
+
+
+void fgListInsert(SFG_List *list, SFG_Node *next, SFG_Node *node)
+{
+ SFG_Node *prev;
+
+ if( (node->Next = next) )
+ {
+ prev = next->Prev;
+ next->Prev = node;
+ }
+ else
+ {
+ prev = list->Last;
+ list->Last = node;
+ }
+
+ if( (node->Prev = prev) )
+ prev->Next = node;
+ else
+ list->First = node;
+}
+
+/*** END OF FILE ***/
Index: external/trimesh/gluit/glui_img_spindown_1.c
--- external/trimesh/gluit/glui_img_spindown_1.c (revision 0)
+++ external/trimesh/gluit/glui_img_spindown_1.c (revision 0)
@@ -0,0 +1,24 @@
+
+
+int glui_img_spindown_1[] = { 12, 8, /* width, height */
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 255,255,255, 0, 0, 0, 127,127,127, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 255,255,255, 0, 0, 0,
+ 127,127,127, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 255,255,255, 0, 0, 0, 127,127,127, 191,191,191, 191,191,191,
+ 191,191,191, 127,127,127, 0, 0, 0, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 255,255,255, 0, 0, 0, 127,127,127,
+ 191,191,191, 191,191,191, 127,127,127, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 191,191,191, 191,191,191, 191,191,191, 255,255,255,
+ 0, 0, 0, 127,127,127, 191,191,191, 127,127,127, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191,191,191,
+ 191,191,191, 255,255,255, 0, 0, 0, 127,127,127, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 255,255,255, 0, 0, 0,
+ 127,127,127, 127,127,127, 127,127,127, 127,127,127, 127,127,127,
+ 127,127,127, 127,127,127, 127,127,127, 127,127,127, 191,191,191,
+ 255,255,255,
+};
Index: external/trimesh/gluit/glui_control.cc
--- external/trimesh/gluit/glui_control.cc (revision 0)
+++ external/trimesh/gluit/glui_control.cc (revision 0)
@@ -0,0 +1,1223 @@
+/****************************************************************************
+
+ GLUI User Interface Toolkit
+ ---------------------------
+
+ glui_control.cpp - top-level GLUI_Control class
+
+
+ --------------------------------------------------
+
+ Copyright (c) 1998 Paul Rademacher
+
+ This program is freely distributable without licensing fees and is
+ provided without guarantee or warrantee expressed or implied. This
+ program is -not- in the public domain.
+
+*****************************************************************************/
+
+#include "glui.h"
+#include "glui_stdinc.h"
+
+int _glui_draw_border_only = 0;
+
+
+/**************************************** GLUI_Control::align() **************/
+
+void GLUI_Control::align( void )
+{
+ int col_x, col_y, col_w, col_h, col_x_off, col_y_off;
+ int orig_x_abs;
+
+ orig_x_abs = x_abs;
+
+ /* Fix alignment bug relating to columns */
+ /*return; */
+
+ if ( NOT parent() )
+ return; /* Clearly this shouldn't happen, though */
+
+ get_this_column_dims(&col_x, &col_y, &col_w, &col_h,
+ &col_x_off, &col_y_off);
+
+ if ( type == GLUI_CONTROL_COLUMN ) {
+ /* if ( this->prev() != NULL ) {
+ ((GLUI_Control*)prev())->get_this_column_dims(&col_x, &col_y,
&col_w, &col_h,
+ &col_x_off, &col_y_off);
+
+ x_abs = col_x + col_w;
+ }
+ else {
+ x_abs = ((GLUI_Control*)parent())->x_abs;
+ }
+ */
+ return;
+ }
+
+ if ( alignment == GLUI_ALIGN_LEFT ) {
+ x_abs = col_x + col_x_off;
+ }
+ else if ( alignment == GLUI_ALIGN_RIGHT ) {
+ x_abs = col_x + col_w - col_x_off - this->w;
+ }
+ else if ( alignment == GLUI_ALIGN_CENTER ) {
+ x_abs = col_x + (col_w - this->w) / 2;
+ }
+
+ if ( this->is_container ) {
+ /*** Shift all child columns ***/
+ int delta = x_abs - orig_x_abs;
+
+ GLUI_Control *node;
+
+ node = (GLUI_Control*) this->first_child();
+ while( node != NULL ) {
+ if ( node->type == GLUI_CONTROL_COLUMN ) {
+ node->x_abs += delta;
+ }
+
+ node = (GLUI_Control*) node->next();
+ }
+ }
+
+}
+
+
+/**************************************** GLUI_Control::pack() ************/
+/* Recalculate positions and offsets */
+
+void GLUI_Control::pack_old( int x, int y )
+{
+ GLUI_Control *node;
+ int max_w, curr_y, curr_x, max_y;
+ int x_in = x, y_in =y;
+ int x_margin, y_margin_top, y_margin_bot;
+ int y_top_column;
+ int column_x;
+ GLUI_Column *curr_column = NULL;
+ this->update_size();
+ x_margin = this->x_off;
+ y_margin_top = this->y_off_top;
+ y_margin_bot = this->y_off_bot;
+ this->x_abs = x_in;
+ this->y_abs = y_in;
+ max_w = -1;
+ max_y = -1;
+ curr_x = this->x_abs + x_margin;
+ curr_y = this->y_abs + y_margin_top;
+ /*** Record start of this set of columns ***/
+ y_top_column = curr_y;
+ column_x = 0;
+ if ( this == glui->main_panel ) {
+ x=x;
+ }
+ /*** Iterate over children, packing them first ***/
+ node = (GLUI_Control*) this->first_child();
+ while( node != NULL ) {
+ if ( node->type == GLUI_CONTROL_PANEL ) { /* Pad some space above panels */
+ curr_y += GLUI_ITEMSPACING;
+ }
+ else if ( node->type == GLUI_CONTROL_COLUMN ) {
+ curr_column = (GLUI_Column*) node;
+ if ( 1 ) {
+ column_x += max_w + 2 * x_margin;
+ curr_x += max_w + 2 * x_margin;
+ }
+ else {
+ column_x += max_w + 0 * x_margin;
+ curr_x += max_w + 0 * x_margin;
+ }
+ /*node->pack( curr_x, curr_y ); */
+ node->x_abs = curr_x;
+ node->y_abs = y_top_column;
+ node->w = 2;
+ node->h = curr_y - y_top_column;
+ curr_x += x_margin * 3 + 40;
+ curr_y = y_top_column;
+ max_w = 0;
+ node = (GLUI_Control*) node->next();
+ continue;
+ }
+ node->pack( curr_x, curr_y );
+ if ( node->type == GLUI_CONTROL_PANEL ) /* Pad some space below panels */
+ curr_y += GLUI_ITEMSPACING;
+ curr_y += node->h;
+ if ( node->w > max_w ) {
+ max_w = node->w;
+ if ( curr_column != NULL )
+ curr_column->w = max_w;
+ }
+ node = (GLUI_Control*) node->next();
+ if ( node ) {
+ curr_y += GLUI_ITEMSPACING;
+ }
+ if ( curr_y > max_y )
+ max_y = curr_y;
+ }
+ if ( this->is_container ) {
+ max_y += y_margin_bot; /*** Add bottom border inside box */
+ if ( this->first_child() ) {
+ if ( this->type == GLUI_CONTROL_ROLLOUT ) {
+ /** We don't want the rollout to shrink in width when it's
+ closed **/
+ this->w = MAX(this->w, column_x + max_w + 2 * x_margin );
+ }
+ else {
+ this->w = column_x + max_w + 2 * x_margin;
+ }
+ this->h = (max_y - y_in);
+ }
+ else { /* An empty container, so just assign default w & h */
+ this->w = GLUI_DEFAULT_CONTROL_WIDTH;
+ this->h = GLUI_DEFAULT_CONTROL_HEIGHT;
+ }
+ /** Expand panel if necessary (e.g., to include all the text in
+ a panel label) **/
+ this->update_size();
+ }
+}
+
+
+/********************************* GLUT_Control::draw_recursive() **********/
+
+void GLUI_Control::draw_recursive( int x, int y )
+{
+ GLUI_Control *node;
+
+ /* printf( "%s %d\n", this->name.string, this->hidden );*/
+ if ( NOT can_draw() )
+ return;
+
+ /*if ( 1 ) { -- Debugging to check control width
+ glColor3f( 1.0, 0.0, 0.0 );
+ glBegin( GL_LINES );
+ glVertex2i( x_abs, y_abs );00
+ glVertex2i( x_abs+w, y_abs );
+
+ glEnd();
+ }*/
+
+ glMatrixMode( GL_MODELVIEW );
+ glPushMatrix();
+
+ glTranslatef( (float) this->x_abs + .5,
+ (float) this->y_abs + .5,
+ 0.0 );
+
+ if ( NOT _glui_draw_border_only ) {
+ if ( NOT strcmp( name.string, "Rollout" ) ) {
+ }
+
+ this->draw( this->x_off, this->y_off_top );
+ }
+ else
+ {
+ if ( this->type == GLUI_CONTROL_COLUMN ) {
+ /* printf( "%s w/h: %d/%d\n", (char*) name, w, h ); */
+ /*w = 2; */
+ }
+
+ /* The following draws the area of each control */
+ glColor3f( 1.0, 0.0, 0.0 );
+ glBegin( GL_LINE_LOOP );
+ glVertex2i( 0, 0 ); glVertex2i( w, 0 );
+ glVertex2i( w, h ); glVertex2i( 0, h );
+ glEnd();
+ }
+ glPopMatrix();
+
+ node = (GLUI_Control*) first_child();
+ while( node ) {
+ node->draw_recursive( node->x_abs, node->y_abs );
+ node = (GLUI_Control*) node->next();
+ }
+}
+
+
+/******************************** GLUI_Control::set_to_glut_window() *********/
+/* Sets the current window to the glut window associated with this control */
+
+int GLUI_Control::set_to_glut_window( void )
+{
+ int orig_window;
+
+ if ( NOT glui)
+ return 1;
+
+ orig_window = glutGetWindow();
+
+ glutSetWindow( glui->get_glut_window_id());
+ glDrawBuffer( GL_FRONT );
+
+ return orig_window;
+}
+
+
+/************************************ GLUI_Control::restore_window() *********/
+
+void GLUI_Control::restore_window( int orig )
+{
+ if ( orig > 0 )
+ glutSetWindow( orig );
+}
+
+
+/************************************* GLUI_Control::enable() ****************/
+
+void GLUI_Control::enable( void )
+{
+ GLUI_Control *node;
+
+ if (!enabled)
+ {
+ enabled = true;
+
+ if ( NOT glui )
+ return;
+
+ translate_and_draw_front();
+ }
+
+ /*** Now recursively enable all buttons below it ***/
+ node = (GLUI_Control*) first_child();
+ while(node) {
+ node->enable();
+ node = (GLUI_Control*) node->next();
+ }
+}
+
+
+/************************************ GLUI_Control::disable() ****************/
+
+void GLUI_Control::disable( void )
+{
+ GLUI_Control *node;
+
+ if (enabled)
+ {
+ enabled = false;
+
+ if ( NOT glui )
+ return;
+
+ if ( glui->active_control == this )
+ glui->disactivate_current_control();
+
+ translate_and_draw_front();
+ }
+
+ /*** Now recursively disable all buttons below it ***/
+ node = (GLUI_Control*) first_child();
+ while(node) {
+ node->disable();
+ node = (GLUI_Control*) node->next();
+ }
+}
+
+
+/***************************************** GLUI_Control::set_font() **********/
+
+void GLUI_Control::set_font( void *new_font )
+{
+ int orig, state;
+
+ font = new_font;
+
+ /** Now redraw **/
+ if ( NOT glui )
+ return;
+
+ orig = set_to_glut_window();
+ state = glui->set_front_draw_buffer();
+ glMatrixMode( GL_MODELVIEW );
+ glPushMatrix();
+ translate_to_origin();
+ glDisable( GL_CULL_FACE );
+ set_to_bkgd_color();
+ glBegin( GL_QUADS );
+ glVertex2i( 0,0 ); glVertex2i( w,0 );
+ glVertex2i( w,h ); glVertex2i( 0,h );
+ glEnd();
+ glPopMatrix();
+ glui->restore_draw_buffer(state);
+ restore_window(orig);
+
+ translate_and_draw_front();
+}
+
+
+/************************************ GLUI_Control::draw_string() ************/
+
+void GLUI_Control::draw_string( char *text )
+{
+ _glutBitmapString( get_font(), text );
+}
+
+
+/****************************************** GLUI_Control::draw_char() ********/
+
+void GLUI_Control::draw_char( char c )
+{
+ glutBitmapCharacter( get_font(), c );
+}
+
+
+/************************************* GLUI_Control::string_width() **********/
+
+int GLUI_Control::string_width( char *text )
+{
+ return _glutBitmapWidthString( get_font(), text );
+}
+
+
+/*************************************** GLUI_Control::char_width() **********/
+
+int GLUI_Control::char_width( char c )
+{
+ return glutBitmapWidth( get_font(), c );
+}
+
+
+/***************************************** GLUI_Control::get_font() **********/
+
+void *GLUI_Control::get_font( void )
+{
+ /*** Does this control have its own font? ***/
+ if ( this->font != NULL )
+ return this->font;
+
+ /*** Does the parent glui have a font? ***/
+ if ( glui )
+ return glui->font;
+
+ /*** Return the default font ***/
+ return GLUT_BITMAP_HELVETICA_12;
+}
+
+
+/*************************************** GLUI_Control::draw_name() ***********/
+/* This draws the name of the control as either black (if enabled), or */
+/* embossed if disabled. */
+
+void GLUI_Control::draw_name( int x, int y )
+{
+ if ( NOT can_draw() )
+ return;
+
+ if ( enabled ) {
+ set_to_bkgd_color();
+ glRasterPos2i(x+1, y+1);
+ draw_string(name);
+ glColor3b( 0, 0, 0 );
+ glRasterPos2i(x, y);
+ draw_string(name);
+ }
+ else { /* Control is disabled - emboss the string */
+ glColor3f( 1.0f, 1.0f, 1.0f );
+ glRasterPos2i(x+1, y+1);
+ draw_string(name);
+ glColor3f( .4f, .4f, .4f );
+ glRasterPos2i(x, y);
+ draw_string(name);
+ }
+}
+
+
+/*************************** GLUI_Control::translate_and_draw_front() ********/
+
+void GLUI_Control::translate_and_draw_front( void )
+{
+ int orig,state;
+
+ if ( NOT can_draw() )
+ return;
+
+ orig = set_to_glut_window();
+ state = glui->set_front_draw_buffer();
+ glMatrixMode( GL_MODELVIEW );
+ glPushMatrix();
+ translate_to_origin();
+ draw(0,0);
+ glPopMatrix();
+ glui->restore_draw_buffer(state);
+ restore_window(orig);
+}
+
+
+/**************************************** GLUI_Control::set_w() **************/
+
+void GLUI_Control::set_w( int new_w )
+{
+ w = new_w;
+ update_size(); /* Make sure control is big enough to fit text */
+
+ if ( NOT glui )
+ return;
+
+ glui->pack_controls();
+
+ if ( glui->get_glut_window_id() != -1 ) {
+ int orig = set_to_glut_window();
+ glutReshapeWindow( glui->main_panel->w, glui->main_panel->h );
+ glutPostRedisplay();
+ /* printf( "Requesting a reshape to window %d: %d %d\n",
+ glutGetWindow(),
+ glui->main_panel->w, glui->main_panel->h );*/
+ restore_window(orig);
+ }
+}
+
+
+/**************************************** GLUI_Control::set_h() **************/
+
+void GLUI_Control::set_h( int new_h )
+{
+ h = new_h;
+ update_size(); /* Make sure control is big enough to fit text */
+
+ if ( NOT glui )
+ return;
+
+ glui->pack_controls();
+
+ if ( glui->get_glut_window_id() != -1 ) {
+ int orig = set_to_glut_window();
+ glutReshapeWindow( glui->main_panel->w, glui->main_panel->h );
+ glutPostRedisplay();
+ restore_window(orig);
+ }
+}
+
+
+/**************************************** GLUI_Control::set_alignment() ******/
+
+void GLUI_Control::set_alignment( int new_align )
+{
+ alignment = new_align;
+
+ if ( glui ) {
+ glui->align_controls( this );
+
+ if ( glui->get_glut_window_id() != -1 ) {
+ int orig = set_to_glut_window();
+ glutPostRedisplay();
+ restore_window(orig);
+ }
+ }
+}
+
+
+/************************************* GLUI_Control::sync_live() ************/
+/* Reads live variable and sets control to its current value */
+/* This function is recursive, and operates on control's children */
+
+void GLUI_Control::sync_live( int recurse, int draw_it )
+{
+ GLUI_Node *node;
+ int sync_it=true;
+ int i;
+ float *fp;
+ int changed = false;
+
+ /*** If this is currently active control, and mouse button is down,
+ don't sync ***/
+ if ( glui ) {
+ if ( this == glui->active_control AND glui->mouse_button_down )
+ sync_it = false;
+
+ /*** Actually, just disable syncing if button is down ***/
+ /*** Nope, go ahead and sync if mouse is down - this allows syncing in
+ callbacks ***/
+ if ( 0 ) { /* THIS CODE BELOW SHOULD NOT BE EXECUTED */
+ if ( glui->mouse_button_down ) {
+ /* printf( "Can't sync\n" ); */
+ return;
+ }
+ }
+ }
+
+ /*** If this control has a live variable, we check its current value
+ against the stored value in the control ***/
+
+ if ( ptr_val != NULL ) {
+ if ( live_type == GLUI_LIVE_NONE OR NOT sync_it ) {
+ }
+ else if ( live_type == GLUI_LIVE_INT ) {
+ if ( *((int*)ptr_val) != last_live_int ) {
+ set_int_val( *((int*)ptr_val) );
+ last_live_int = *((int*)ptr_val);
+ changed = true;
+ }
+ }
+ else if ( live_type == GLUI_LIVE_FLOAT ) {
+ if ( *((float*)ptr_val) != last_live_float ) {
+ set_float_val( *((float*)ptr_val) );
+ last_live_float = *((float*)ptr_val);
+ changed = true;
+ }
+ }
+ else if ( live_type == GLUI_LIVE_TEXT ) {
+ if ( strncmp((char*)ptr_val,last_live_text,sizeof(GLUI_String)) != 0 ) {
+ set_text( (char*) ptr_val );
+ strncpy( last_live_text, (char*) ptr_val, sizeof(GLUI_String));
+ changed = true;
+ }
+ }
+ else if ( live_type == GLUI_LIVE_FLOAT_ARRAY ) {
+ /*** Step through the arrays, and see if they're the same ***/
+
+ fp = (float*) ptr_val;
+ for ( i=0; i<float_array_size; i++ ) {
+ if ( *fp != last_live_float_array[i] ) {
+ changed = true;
+ break;
+ }
+
+ fp++;
+ }
+
+ if ( changed == true) {
+ fp = (float*) ptr_val;
+ set_float_array_val( fp );
+ for ( i=0; i<float_array_size; i++ ) {
+ last_live_float_array[i] = *fp;
+ fp++;
+ }
+ }
+ }
+ else if ( live_type == GLUI_LIVE_DOUBLE ) {
+ }
+ }
+
+ /*** If this control is changed and we're supposed to be drawing, then
+ draw it now ***/
+ if ( changed == true AND draw_it ) {
+ translate_and_draw_front();
+ }
+
+ if ( recurse ) {
+ /*** Now recursively output live vars for all children ***/
+
+ node = this->first_child();
+ while( node ) {
+ ((GLUI_Control*) node)->sync_live(true, true);
+ node = node->next();
+ }
+
+ if ( collapsible == true AND is_open == false ) {
+ /** Here we have a collapsed control (e.g., a rollout that is closed **/
+ /** We need to go in and sync all the collapsed controls inside **/
+
+ node = this->collapsed_node.first_child();
+ while( node ) {
+ ((GLUI_Control*) node)->sync_live(true, false);
+ node = node->next();
+ }
+ }
+ }
+}
+
+
+/************************************ GLUI_Control::output_live() ************/
+/* Writes current value of control to live variable. */
+
+void GLUI_Control::output_live( int update_main_gfx )
+{
+ int i;
+ float *fp;
+
+ if ( ptr_val == NULL )
+ return;
+
+ if ( NOT live_inited )
+ return;
+
+ if ( live_type == GLUI_LIVE_NONE ) {
+ }
+ else if ( live_type == GLUI_LIVE_INT ) {
+ *((int*)ptr_val) = int_val;
+ last_live_int = int_val;
+ }
+ else if ( live_type == GLUI_LIVE_FLOAT ) {
+ *((float*)ptr_val) = float_val;
+ last_live_float = float_val;
+ }
+ else if ( live_type == GLUI_LIVE_TEXT ) {
+ strncpy( (char*) ptr_val, text, sizeof(GLUI_String));
+ strncpy( last_live_text, text, sizeof(GLUI_String));
+ }
+ else if ( live_type == GLUI_LIVE_FLOAT_ARRAY ) {
+ fp = (float*) ptr_val;
+
+ for( i=0; i<float_array_size; i++ ) {
+ *fp = float_array_val[i];
+ last_live_float_array[i] = float_array_val[i];
+ fp++;
+ }
+ }
+ else if ( live_type == GLUI_LIVE_DOUBLE ) {
+ }
+
+ /** Update the main gfx window? **/
+ if ( update_main_gfx AND this->glui != NULL ) {
+ this->glui->post_update_main_gfx();
+ }
+}
+
+
+/******************************** GLUI_Control::execute_callback() **********/
+
+void GLUI_Control::execute_callback( void )
+{
+ int old_window;
+
+ old_window = glutGetWindow();
+
+ if ( glui AND glui->main_gfx_window_id != -1 )
+ glutSetWindow( glui->main_gfx_window_id );
+
+ if ( this->callback )
+ this->callback( this->user_id );
+
+ glutSetWindow( old_window );
+}
+
+
+/***************************** GLUI_Control::get_this_column_dims() **********/
+/* Gets the x,y,w,h,and x/y offsets of the column to which a control belongs */
+
+void GLUI_Control::get_this_column_dims( int *col_x, int *col_y,
+ int *col_w, int *col_h,
+ int *col_x_off, int *col_y_off )
+{
+ GLUI_Control *node, *parent_ptr;
+ int parent_h, parent_y_abs;
+
+ parent_ptr = (GLUI_Control*) parent();
+
+ if ( parent_ptr==NULL )
+ return;
+
+ parent_h = parent_ptr->h;
+ parent_y_abs = parent_ptr->y_abs;
+
+ if ( parent_ptr->type == GLUI_CONTROL_PANEL AND
+ parent_ptr->int_val == GLUI_PANEL_EMBOSSED AND
+ parent_ptr->name[0] != '\0' ) {
+ parent_h -= GLUI_PANEL_EMBOSS_TOP;
+ parent_y_abs += GLUI_PANEL_EMBOSS_TOP;
+ }
+
+ if ( 0 ) {
+ GLUI_Node *first, *last, *curr;
+
+ /** Look for first control in this column **/
+ first = this;
+ while (first->prev() != NULL AND
+ ((GLUI_Control*)first->prev())->type != GLUI_CONTROL_COLUMN )
+ first = first->prev();
+
+ /** Look for last control in this column **/
+ last = this;
+ while ( last->next() != NULL AND
+ ((GLUI_Control*)first->next())->type != GLUI_CONTROL_COLUMN )
+ last = last->next();
+
+ curr = first;
+ int max_w = -1;
+ do {
+ if ( ((GLUI_Control*)curr)->w > max_w )
+ max_w = ((GLUI_Control*)curr)->w;
+
+ if ( curr == last )
+ break;
+
+ curr = curr->next();
+ } while( curr != NULL );
+
+ *col_x = ((GLUI_Control*)first)->x_abs;
+ *col_y = ((GLUI_Control*)first)->y_abs;
+ *col_w = max_w;
+ if ( parent() ) {
+ *col_h = ((GLUI_Control*)parent())->h;
+ *col_x_off = ((GLUI_Control*)parent())->x_off;
+ }
+ else {
+ *col_h = 10;
+ *col_x_off = 0;
+ }
+ *col_y_off = 0;
+
+ return;
+ }
+
+ if ( 1 ) { /* IS THIS WRONG? */
+ /*** Look for preceding column ***/
+ node = (GLUI_Control*) this->prev();
+ while( node ) {
+ if ( node->type == GLUI_CONTROL_COLUMN ) {
+ *col_x = node->x_abs;
+ *col_y = parent_y_abs;
+ *col_w = node->w;
+ *col_h = parent_h;
+ *col_x_off = node->x_off;
+ *col_y_off = 0;
+
+ return;
+ }
+
+ node = (GLUI_Control*) node->prev();
+ }
+
+ /*** Nope, Look for next column ***/
+ node = (GLUI_Control*) this->next();
+ while( node ) {
+ if ( node->type == GLUI_CONTROL_COLUMN ) {
+ *col_x = parent_ptr->x_abs;
+ *col_y = parent_y_abs;
+ *col_w = node->x_abs - parent_ptr->x_abs;
+ *col_h = parent_h;
+ *col_x_off = node->x_off;
+ *col_y_off = 0;
+
+ return;
+ }
+
+ node = (GLUI_Control*) node->next();
+ }
+
+ /*** This is single-column panel, so return panel dims ***/
+ *col_x = parent_ptr->x_abs;
+ *col_y = parent_y_abs;
+ *col_w = parent_ptr->w;
+ *col_h = parent_h;
+ *col_x_off = parent_ptr->x_off;
+ *col_y_off = 0;
+ }
+}
+
+
+/**************************************** GLUI_Control::init_live() **********/
+/* Reads in value of a live variable. Called once, when ctrl is created */
+
+void GLUI_Control::init_live( void )
+{
+ int i;
+ float *fp;
+
+ if ( ptr_val == NULL )
+ return;
+
+ if ( live_type == GLUI_LIVE_NONE ) {
+ }
+ else if ( live_type == GLUI_LIVE_INT ) {
+ set_int_val( *((int*)ptr_val) );
+ last_live_int = *((int*)ptr_val);
+ }
+ else if ( live_type == GLUI_LIVE_FLOAT ) {
+ set_float_val( *((float*)ptr_val) );
+ last_live_float = *((float*)ptr_val);
+ }
+ else if ( live_type == GLUI_LIVE_TEXT ) {
+ set_text( (char*) ptr_val );
+ strncpy( last_live_text, (char*) ptr_val, sizeof(GLUI_String));
+ }
+ else if ( live_type == GLUI_LIVE_FLOAT_ARRAY ) {
+ set_float_array_val( (float*) ptr_val );
+
+ fp = (float*) ptr_val;
+
+ for( i=0; i<float_array_size; i++ ) {
+ last_live_float_array[i] = *fp;
+ fp++;
+ }
+
+ }
+ else if ( live_type == GLUI_LIVE_DOUBLE ) {
+ }
+
+ live_inited = true;
+}
+
+
+/**************************************** GLUI_Control::needs_idle() *********/
+/* This method gets overloaded by specific classes, e.g. Spinner. */
+/* It returns whether or not a control needs to receive an idle event or not */
+/* For example, a spinner only needs idle events when the user is holding */
+/* the mouse down in one of the arrows. Otherwise, don't waste cycles */
+/* and OpenGL context switching by calling its idle. */
+
+int GLUI_Control::needs_idle( void )
+{
+ return false;
+};
+
+
+/*********************************** GLUI_Control::~GLUI_Control() **********/
+
+GLUI_Control::~GLUI_Control()
+{
+ GLUI_Control *node, *node_tmp;
+
+ /* printf( "destroying %s\n", this->name ); */
+
+ node = (GLUI_Control*) this->first_child();
+ while( node != NULL ) {
+ /* printf( "recursively destroying: '%s'\n", node->name );
*/
+
+ node_tmp = node;
+ node = (GLUI_Control*) node->next();
+ delete node_tmp;
+ }
+}
+
+
+/************************** GLUI_Control::draw_box_inwards_outline() ********/
+
+void GLUI_Control::draw_box_inwards_outline( int x_min, int x_max,
+ int y_min, int y_max )
+{
+ glBegin( GL_LINES );
+ glColor3f( .5, .5, .5 );
+ glVertex2i( x_min, y_min ); glVertex2i( x_max, y_min );
+ glVertex2i( x_min, y_min ); glVertex2i( x_min, y_max );
+
+ glColor3f( 1., 1., 1. );
+ glVertex2i( x_min, y_max ); glVertex2i( x_max, y_max );
+ glVertex2i( x_max, y_max ); glVertex2i( x_max, y_min );
+
+ if ( enabled )
+ glColor3f( 0., 0., 0. );
+ else
+ glColor3f( .25, .25, .25 );
+ glVertex2i( x_min+1, y_min+1 ); glVertex2i( x_max-1, y_min+1 );
+ glVertex2i( x_min+1, y_min+1 ); glVertex2i( x_min+1, y_max-1 );
+
+ glColor3f( .75, .75, .75 );
+ glVertex2i( x_min+1, y_max-1 ); glVertex2i( x_max-1, y_max-1 );
+ glVertex2i( x_max-1, y_max-1 ); glVertex2i( x_max-1, y_min+1 );
+ glEnd();
+}
+
+
+/************************************* GLUI_Control::draw_box() **********/
+
+void GLUI_Control::draw_box( int x_min, int x_max, int y_min, int y_max,
+ float r, float g, float b)
+{
+ if ( r == 1.0 AND g == 1.0 AND b == 1.0 AND NOT enabled AND glui ) {
+ draw_bkgd_box( x_min, x_max, y_min, y_max );
+ return;
+ }
+
+ glColor3f( r, g, b );
+ glBegin( GL_QUADS );
+ glVertex2i( x_min, y_min ); glVertex2i( x_max, y_min );
+ glVertex2i( x_max, y_max ); glVertex2i( x_min, y_max );
+ glEnd();
+}
+
+
+/************************************* GLUI_Control::draw_bkgd_box() **********/
+
+void GLUI_Control::draw_bkgd_box( int x_min, int x_max, int y_min, int y_max )
+{
+ set_to_bkgd_color();
+
+ glBegin( GL_QUADS );
+ glVertex2i( x_min, y_min ); glVertex2i( x_max, y_min );
+ glVertex2i( x_max, y_max ); glVertex2i( x_min, y_max );
+ glEnd();
+}
+
+
+/***************************** GLUI_Control::draw_active_area() ********/
+
+void GLUI_Control::draw_active_box( int x_min, int x_max,
+ int y_min, int y_max )
+{
+ int orig;
+
+ if ( NOT glui )
+ return;
+
+ orig = set_to_glut_window();
+
+ if ( active ) {
+ glEnable( GL_LINE_STIPPLE );
+ glLineStipple( 1, 0x5555 );
+ glColor3f( 0., 0., 0. );
+ } else {
+ set_to_bkgd_color();
+ }
+
+ glBegin( GL_LINE_LOOP );
+ glVertex2i(x_min, y_min); glVertex2i( x_max, y_min );
+ glVertex2i(x_max, y_max); glVertex2i( x_min, y_max );
+ glEnd();
+
+ glDisable( GL_LINE_STIPPLE );
+
+ restore_window(orig);
+}
+
+
+/************************************** GLUI_Control::set_to_bkgd_color() ********/
+
+void GLUI_Control::set_to_bkgd_color( void )
+{
+ if ( NOT glui )
+ return;
+
+ glColor3ub( glui->bkgd_color.r, glui->bkgd_color.g, glui->bkgd_color.b );
+}
+
+
+/******************************* GLUI_Control::set_float_array_val() ********/
+
+void GLUI_Control::set_float_array_val( float *array_ptr )
+{
+ int i;
+
+ if ( array_ptr == NULL )
+ return;
+
+ for( i=0; i<float_array_size; i++ ) {
+ float_array_val[i] = array_ptr[i];
+ }
+
+ /*** Output the live var, without updating the main gfx window ***/
+ output_live(false);
+}
+
+
+/******************************* GLUI_Control::get_float_array_val() ********/
+
+void GLUI_Control::get_float_array_val( float *array_ptr )
+{
+ int i;
+
+ if ( array_ptr == NULL )
+ return;
+
+ for( i=0; i<float_array_size; i++ ) {
+ array_ptr[i] = float_array_val[i];
+ }
+}
+
+
+
+/****************************** GLUI_Control::set_name() ********************/
+
+void GLUI_Control::set_name(char *string )
+{
+ strncpy((char*)name,string,sizeof(GLUI_String));
+
+ if ( glui)
+ glui->refresh();
+};
+
+
+
+
+
+void GLUI_Control::pack( int x, int y )
+{
+ GLUI_Control *node;
+ int max_w, curr_y, curr_x, max_y;
+ int x_in = x, y_in =y;
+ int x_margin, y_margin_top, y_margin_bot;
+ int y_top_column;
+ int column_x;
+ GLUI_Column *curr_column = NULL;
+
+ this->update_size();
+
+ x_margin = this->x_off;
+ y_margin_top = this->y_off_top;
+ y_margin_bot = this->y_off_bot;
+
+ this->x_abs = x_in;
+ this->y_abs = y_in;
+
+ max_w = 0;
+ max_y = 0;
+ curr_x = this->x_abs + x_margin;
+ curr_y = this->y_abs + y_margin_top;
+
+ /*** Record start of this set of columns ***/
+
+ y_top_column = curr_y;
+ column_x = curr_x;
+
+ /*** Iterate over children, packing them first ***/
+
+ node = (GLUI_Control*) this->first_child();
+ while( node != NULL ) {
+ if ( node->type == GLUI_CONTROL_PANEL ) { /* Pad some space above panels */
+ curr_y += GLUI_ITEMSPACING;
+ }
+ else if ( node->type == GLUI_CONTROL_COLUMN ) {
+ curr_column = (GLUI_Column*) node;
+ curr_x += max_w + 1 * x_margin;
+ column_x = curr_x;
+
+ node->x_abs = curr_x;
+ node->y_abs = y_top_column;
+ node->w = 2;
+ node->h = curr_y - y_top_column;
+
+ curr_x += x_margin * 1;
+ curr_y = y_top_column;
+ max_w = 0;
+
+ node = (GLUI_Control*) node->next();
+ continue;
+ }
+
+ node->pack( curr_x, curr_y );
+
+ if ( node->type == GLUI_CONTROL_PANEL ) /* Pad some space below panels */
+ curr_y += GLUI_ITEMSPACING;
+
+ curr_y += node->h;
+
+ if ( node->w > max_w ) {
+ max_w = node->w;
+ if ( curr_column != NULL )
+ curr_column->w = max_w + x_margin;
+ }
+
+ if ( curr_y > max_y ) {
+ max_y = curr_y;
+ if ( curr_column != NULL )
+ curr_column->h = max_y - y_top_column;
+ }
+
+ node = (GLUI_Control*) node->next();
+
+ if ( node ) {
+ curr_y += GLUI_ITEMSPACING;
+ }
+
+ }
+
+ if ( this->is_container ) {
+ max_y += y_margin_bot; /*** Add bottom border inside box */
+
+ if ( this->first_child() ) {
+ this->w = column_x + max_w + 2 * x_margin - x_in;
+ this->h = (max_y - y_in);
+ }
+ else { /* An empty container, so just assign default w & h */
+ if ( this->type != GLUI_CONTROL_ROLLOUT ) {
+ this->w = GLUI_DEFAULT_CONTROL_WIDTH;
+ this->h = GLUI_DEFAULT_CONTROL_HEIGHT;
+ }
+ }
+
+ /** Expand panel if necessary (e.g., to include all the text in
+ a panel label) **/
+ this->update_size();
+
+
+ /*** Now we step through the GLUI_Columns, setting the 'h' ***/
+ node = (GLUI_Control*) this->first_child();
+ while( node != NULL ) {
+ if ( node->type == GLUI_CONTROL_COLUMN ) {
+ node->h = this->h - y_margin_bot - y_margin_top;
+ }
+
+ node = (GLUI_Control*) node->next();
+ }
+ }
+}
+
+
+/****************************** GLUI_Control::draw_emboss_box() ********/
+
+void GLUI_Control::draw_emboss_box(int x_min,int x_max,int y_min,int y_max)
+{
+ glLineWidth( 1.0 );
+ glColor3f( 1.0, 1.0, 1.0 );
+
+ glBegin( GL_LINE_LOOP );
+ glVertex2i( x_min, y_min ); glVertex2i( x_max, y_min );
+ glVertex2i( x_max, y_max ); glVertex2i( x_min, y_max );
+ glEnd();
+
+ glBegin( GL_LINE_LOOP );
+ glVertex2i( x_min+1, y_min+1 ); glVertex2i( x_max-1, y_min+1 );
+ glVertex2i( x_max-1, y_max-1 ); glVertex2i( x_min+1, y_max-1 );
+ glEnd();
+
+ glColor3f( .5, .5, .5 );
+ glBegin( GL_LINE_LOOP );
+ glVertex2i( x_min, y_min );
+ glVertex2i( x_max-1, y_min );
+ glVertex2i( x_max-1, y_max-1 );
+ glVertex2i( x_min, y_max-1 );
+ glEnd();
+}
+
+
+/*********************************** GLUI_Control::hide_internal() ********/
+/** Sets hidden==true for this control and all its siblings. */
+/** If recurse is true, we go to children as well */
+
+void GLUI_Control::hide_internal( int recurse )
+{
+ GLUI_Node *node;
+
+ node = (GLUI_Node *) this;
+ while( node != NULL ) {
+ ((GLUI_Control*)node)->hidden = true;
+
+ if ( recurse AND node->first_child() != NULL )
+ ((GLUI_Control*) node->first_child())->hide_internal(true);
+
+ node = node->next();
+ }
+
+ node = this->collapsed_node.first_child();
+ while( node != NULL ) {
+ ((GLUI_Control*)node)->hidden = true;
+
+ if ( recurse AND node->first_child() != NULL )
+ ((GLUI_Control*) node->first_child())->hide_internal(true);
+
+ node = node->next();
+ }
+}
+
+
+/*********************************** GLUI_Control::unhide_internal() ********/
+/** Sets hidden==false for this control and all its siblings. */
+/** If recurse is true, we go to children as well */
+
+void GLUI_Control::unhide_internal( int recurse )
+{
+ GLUI_Node *node;
+
+ node = (GLUI_Node *) this;
+ while( node != NULL ) {
+ /* printf( "unhide: %s [%d]\n", ((GLUI_Control*)node)->name.string,
+ ((GLUI_Control*)node)->hidden );*/
+ ((GLUI_Control*)node)->hidden = false;
+
+ if ( recurse AND node->first_child() != NULL )
+ ((GLUI_Control*) node->first_child())->unhide_internal(true);
+
+ node = node->next();
+ }
+
+ node = this->collapsed_node.first_child();
+ while( node != NULL ) {
+ ((GLUI_Control*)node)->hidden = false;
+
+ if ( recurse AND node->first_child() != NULL )
+ ((GLUI_Control*) node->first_child())->unhide_internal(true);
+
+ node = node->next();
+ }
+}
Index: external/trimesh/gluit/glui.cc
--- external/trimesh/gluit/glui.cc (revision 0)
+++ external/trimesh/gluit/glui.cc (revision 0)
@@ -0,0 +1,1960 @@
+/****************************************************************************
+
+ GLUI User Interface Toolkit
+ ---------------------------
+
+ glui.cpp
+
+
+ --------------------------------------------------
+
+ Copyright (c) 1998 Paul Rademacher
+
+ This program is freely distributable without licensing fees and is
+ provided without guarantee or warrantee expressed or implied. This
+ program is -not- in the public domain.
+
+*****************************************************************************/
+
+#include "glui.h"
+#include "glui_stdinc.h"
+
+
+/*** This object must be used to create a GLUI ***/
+
+GLUI_Master_Object GLUI_Master;
+
+
+/************************************ finish_drawing() ************/
+
+void finish_drawing( void )
+{
+ glFinish();
+}
+
+/************************************************ GLUI::GLUI() **********/
+
+int GLUI::init( char *text, long Flags, int x, int y, int Parent_window )
+{
+ int old_glut_window;
+
+ this->flags = Flags;
+
+ strncpy( window_name.string, text, sizeof(GLUI_String));
+
+ /*** We copy over the current window callthroughs ***/
+ /*** (I think this might actually only be needed for subwindows) ***/
+ /* glut_keyboard_CB = GLUI_Master.glut_keyboard_CB;
+ glut_reshape_CB = GLUI_Master.glut_reshape_CB;
+ glut_special_CB = GLUI_Master.glut_special_CB;
+ glut_mouse_CB = GLUI_Master.glut_mouse_CB;*/
+
+
+ if ( (flags & GLUI_SUBWINDOW) != GLUI_SUBWINDOW ) {
+ old_glut_window = glutGetWindow();
+
+ create_standalone_window( window_name, x, y );
+ setup_default_glut_callbacks();
+
+ if ( old_glut_window > 0 )
+ glutSetWindow( old_glut_window );
+
+ top_level_glut_window_id = glut_window_id;
+ }
+ else {
+ old_glut_window = glutGetWindow();
+
+ create_subwindow( Parent_window, flags );
+ setup_default_glut_callbacks();
+
+ if ( old_glut_window > 0 )
+ glutSetWindow( old_glut_window );
+
+ top_level_glut_window_id = Parent_window;
+
+ /*
+ glutReshapeFunc( glui_parent_window_reshape_func );
+ glutSpecialFunc( glui_parent_window_special_func );
+ glutKeyboardFunc( glui_parent_window_keyboard_func );
+ glutMouseFunc( glui_parent_window_mouse_func );
+ */
+
+ }
+
+ return true;
+}
+
+
+/**************************** GLUI_Main::create_standalone_window() ********/
+
+void GLUI_Main::create_standalone_window( char *name, int x, int y )
+{
+ glutInitWindowSize( 100, 100 );
+ if ( x >= 0 OR y >= 0 )
+ glutInitWindowPosition( x, y );
+ glutInitDisplayMode( GLUT_RGB | GLUT_SINGLE ); /* | GLUT_DOUBLE ); */
+ glut_window_id = glutCreateWindow( name );
+ glDisable( GL_DEPTH_TEST );
+ glCullFace( GL_BACK );
+ glDisable( GL_CULL_FACE );
+ glDisable( GL_LIGHTING );
+ glDrawBuffer( GL_FRONT );
+}
+
+
+/******************************** GLUI_Main::create_subwindow() **********/
+
+void GLUI_Main::create_subwindow( int Parent_window,
+ int /* window_alignment */ )
+{
+ glut_window_id = glutCreateSubWindow( Parent_window, 0,0, 100, 100 );
+ glDisable( GL_DEPTH_TEST );
+ glCullFace( GL_BACK );
+ glDisable( GL_CULL_FACE );
+ glDisable( GL_LIGHTING );
+ glDrawBuffer( GL_FRONT );
+
+ this->parent_window = Parent_window;
+}
+
+
+/**************************** GLUI_Main::setup_default_glut_callbacks() *****/
+
+void GLUI_Main::setup_default_glut_callbacks( void )
+{
+ glutDisplayFunc( glui_display_func );
+ glutReshapeFunc( glui_reshape_func );
+ glutKeyboardFunc( glui_keyboard_func );
+ glutSpecialFunc( glui_special_func );
+ glutMouseFunc( glui_mouse_func );
+ glutMotionFunc( glui_motion_func );
+ glutPassiveMotionFunc( glui_passive_motion_func );
+ glutEntryFunc( glui_entry_func );
+ glutVisibilityFunc( glui_visibility_func );
+ /* glutIdleFunc( glui_idle_func ); */
+}
+
+
+/********************************************** glui_display_func() ********/
+
+void glui_display_func( void )
+{
+ GLUI *glui;
+
+ /* printf( "display func\n" ); */
+
+ glui = GLUI_Master.find_glui_by_window_id( glutGetWindow() );
+
+ if ( glui ) {
+ glui->display();
+ /*
+ Do not do anything after the above line, b/c the GLUI
+ window might have just closed itself
+ */
+ }
+}
+
+
+/********************************************** glui_reshape_func() ********/
+
+void glui_reshape_func( int w, int h )
+{
+ GLUI *glui;
+ GLUI_Glut_Window *glut_window;
+ int current_window;
+
+ /*printf( "glui_reshape_func(): %d w/h: %d/%d\n", glutGetWindow(), w, h );
*/
+
+ current_window = glutGetWindow();
+
+ /*** First check if this is main glut window ***/
+ glut_window = GLUI_Master.find_glut_window( current_window );
+ if ( glut_window ) {
+ glut_window->glut_reshape_CB(w,h);
+
+ /*** Now send reshape events to all subwindows ***/
+ glui = (GLUI*) GLUI_Master.gluis.first_child();
+ while(glui) {
+ if ( TEST_AND( glui->flags, GLUI_SUBWINDOW) AND
+ glui->parent_window == current_window ) {
+ glutSetWindow( glui->get_glut_window_id());
+ glui->reshape(w,h);
+ /* glui->check_subwindow_position(); */
+ }
+ glui = (GLUI*) glui->next();
+ }
+ }
+ else {
+ /*** A standalone GLUI window ***/
+
+ glui = GLUI_Master.find_glui_by_window_id( current_window );
+
+ if ( glui ) {
+ glui->reshape(w,h);
+ }
+ }
+}
+
+/********************************************** glui_keyboard_func() ********/
+
+void glui_keyboard_func(unsigned char key, int x, int y)
+{
+ GLUI *glui;
+ int current_window;
+ GLUI_Glut_Window *glut_window;
+
+ current_window = glutGetWindow();
+ glut_window = GLUI_Master.find_glut_window( current_window );
+
+ /*printf( "key: %d\n", current_window ); */
+
+ if ( glut_window ) { /** Was event in a GLUT window? **/
+ if ( GLUI_Master.active_control_glui AND GLUI_Master.active_control ) {
+ glutSetWindow( GLUI_Master.active_control_glui->get_glut_window_id() );
+
+ GLUI_Master.active_control_glui->keyboard(key,x,y);
+ finish_drawing();
+
+ glutSetWindow( current_window );
+ }
+ else {
+ glut_window->glut_keyboard_CB( key, x, y );
+ }
+ }
+ else { /*** Nope, event was in a standalone GLUI window **/
+ glui = GLUI_Master.find_glui_by_window_id( glutGetWindow() );
+
+ if ( glui ) {
+ glui->keyboard(key,x,y);
+ finish_drawing();
+ }
+ }
+}
+
+
+/************************************************ glui_special_func() ********/
+
+void glui_special_func(int key, int x, int y)
+{
+ GLUI *glui;
+ int current_window;
+ GLUI_Glut_Window *glut_window;
+
+ current_window = glutGetWindow();
+ glut_window = GLUI_Master.find_glut_window( current_window );
+
+ if ( glut_window ) { /** Was event in a GLUT window? **/
+ if ( GLUI_Master.active_control_glui AND GLUI_Master.active_control ) {
+ glutSetWindow( GLUI_Master.active_control_glui->get_glut_window_id() );
+
+ GLUI_Master.active_control_glui->special(key,x,y);
+ finish_drawing();
+
+ glutSetWindow( current_window );
+ }
+ else {
+ glut_window->glut_special_CB( key, x, y );
+ }
+ }
+ else { /*** Nope, event was in a standalone GLUI window **/
+ glui = GLUI_Master.find_glui_by_window_id( glutGetWindow() );
+
+ if ( glui ) {
+ glui->special(key,x,y);
+ finish_drawing();
+ }
+ }
+}
+
+
+
+/********************************************** glui_mouse_func() ********/
+
+void glui_mouse_func(int button, int state, int x, int y)
+{
+ GLUI *glui;
+ int current_window;
+ GLUI_Glut_Window *glut_window;
+
+ current_window = glutGetWindow();
+ glut_window = GLUI_Master.find_glut_window( current_window );
+
+ if ( glut_window ) { /** Was event in a GLUT window? **/
+ if ( GLUI_Master.active_control_glui != NULL )
+ GLUI_Master.active_control_glui->disactivate_current_control();
+
+ glut_window->glut_mouse_CB( button, state, x, y );
+ finish_drawing();
+ }
+ else { /** Nope - event was in a GLUI standalone window **/
+ glui = GLUI_Master.find_glui_by_window_id( glutGetWindow() );
+ if ( glui ) {
+ glui->passive_motion( 0,0 );
+ glui->mouse( button, state, x, y );
+ finish_drawing();
+ }
+ }
+}
+
+
+/********************************************** glui_motion_func() ********/
+
+void glui_motion_func(int x, int y)
+{
+ GLUI *glui;
+
+ glui = GLUI_Master.find_glui_by_window_id( glutGetWindow() );
+
+ if ( glui ) {
+ glui->motion(x,y);
+ finish_drawing();
+ }
+
+}
+
+
+/**************************************** glui_passive_motion_func() ********/
+
+void glui_passive_motion_func(int x, int y)
+{
+ GLUI *glui;
+
+ glui = GLUI_Master.find_glui_by_window_id( glutGetWindow() );
+
+ if ( glui ) {
+ glui->passive_motion(x,y);
+ finish_drawing();
+ }
+}
+
+
+/********************************************** glui_entry_func() ********/
+
+void glui_entry_func(int state)
+{
+ GLUI *glui;
+
+ glui = GLUI_Master.find_glui_by_window_id( glutGetWindow() );
+
+ if ( glui ) {
+ glui->entry(state);
+ }
+}
+
+
+/******************************************** glui_visibility_func() ********/
+
+void glui_visibility_func(int state)
+{
+ GLUI *glui;
+
+ /* printf( "IN GLUI VISIBILITY()\n" ); */
+ /* fflush( stdout ); */
+
+ glui = GLUI_Master.find_glui_by_window_id( glutGetWindow() );
+
+ if ( glui ) {
+ glui->visibility(state);
+ }
+}
+
+
+/********************************************** glui_idle_func() ********/
+/* Send idle event to each glui, then to the main window */
+
+void glui_idle_func(void)
+{
+ GLUI *glui;
+
+ glui = (GLUI*) GLUI_Master.gluis.first_child();
+ while( glui ) {
+ glui->idle();
+ finish_drawing();
+
+ glui = (GLUI*) glui->next();
+ }
+
+ if ( GLUI_Master.glut_idle_CB ) {
+ /*** We set the current glut window before calling the user's
+ idle function, even though glut explicitly says the window id is
+ undefined in an idle callback. ***/
+
+ /** Check what the current window is first ***/
+
+ /*** Arbitrarily set the window id to the main gfx window of the
+ first glui window ***/
+ /* int current_window, new_window; */
+ /* current_window = glutGetWindow(); */
+ /* if (GLUI_Master.gluis.first_child() != NULL ) { */
+ /* new_window = ((GLUI_Main*)GLUI_Master.gluis.first_child())-> */
+ /* main_gfx_window_id; */
+ /* if ( new_window > 0 AND new_window != old_window ) { */
+ /* --- Window is changed only if its not already the current window ---*/
+ /* glutSetWindow( new_window ); */
+ /* } */
+ /*} */
+
+ GLUI_Master.glut_idle_CB();
+ }
+}
+
+
+/*********************************** GLUI_Master_Object::create_glui() ******/
+
+GLUI *GLUI_Master_Object::create_glui( char *name, long flags,int x,int y )
+{
+ GLUI *new_glui;
+
+ new_glui = new GLUI;
+
+ if ( new_glui ) {
+ new_glui->init( name, flags, x, y, -1 );
+ new_glui->link_this_to_parent_last( &this->gluis );
+ return new_glui;
+ }
+ else {
+ return NULL;
+ }
+}
+
+
+/************************** GLUI_Master_Object::create_glui_subwindow() ******/
+
+GLUI *GLUI_Master_Object::create_glui_subwindow( int parent_window,
+ long flags )
+{
+ GLUI *new_glui;
+ char new_name[80];
+
+ new_glui = new GLUI;
+
+ if ( new_glui ) {
+ sprintf( new_name, "subwin_%p", this );
+
+ new_glui->init( new_name, flags | GLUI_SUBWINDOW, 0,0,
+ parent_window );
+ new_glui->main_panel->set_int_val( GLUI_PANEL_EMBOSSED );
+ new_glui->link_this_to_parent_last( &this->gluis );
+ return new_glui;
+ }
+ else {
+ return NULL;
+ }
+}
+
+
+
+/********************** GLUI_Master_Object::find_glui_by_window_id() ********/
+
+GLUI *GLUI_Master_Object::find_glui_by_window_id( int window_id )
+{
+ GLUI_Node *node;
+
+ node = gluis.first_child();
+ while( node ) {
+ if ( ((GLUI*)node)->get_glut_window_id() == window_id )
+ return (GLUI*) node;
+
+ node = node->next();
+ }
+ return NULL;
+}
+
+
+/******************************************** GLUI_Main::display() **********/
+
+void GLUI_Main::display( void )
+{
+ int win_w, win_h;
+
+ /*glutSetWindow(1);///WOW WHAT A HACK */
+
+ /**** This function is used as a special place to do 'safe' processing,
+ e.g., handling window close requests.
+ That is, we can't close the window directly in the callback, so
+ we set a flag, post a redisplay message (which eventually calls
+ this function), then close the window safely in here. ****/
+ if ( closing == true ) {
+ close_internal();
+ return;
+ }
+
+ /* if ( TEST_AND( this->flags, GLUI_SUBWINDOW ))
+ check_subwindow_position();
+ */
+
+ /******* Draw GLUI window ******/
+
+ glClearColor( (float) bkgd_color.r / 255.0,
+ (float) bkgd_color.g / 255.0,
+ (float) bkgd_color.b / 255.0,
+ 1.0 );
+ glClear( GL_COLOR_BUFFER_BIT ); /* | GL_DEPTH_BUFFER_BIT ); */
+
+ /* glutSwapBuffers(); //performs flush also // %%%%%%%%%% */
+ /* return; */
+
+ win_w = glutGet( GLUT_WINDOW_WIDTH );
+ win_h = glutGet( GLUT_WINDOW_HEIGHT );
+
+ /*** Check here if the window needs resizing ***/
+ if ( win_w != main_panel->w OR win_h != main_panel->h ) {
+ glutReshapeWindow( main_panel->w, main_panel->h );
+ glutPostRedisplay();
+ return;
+ }
+
+ set_ortho_projection();
+
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+
+ /*** Rotate image so y increases upwards, contrary to OpenGL axes ***/
+ glTranslatef( (float) win_w/2.0, (float) win_h/2.0, 0.0 );
+ glRotatef( 180.0, 0.0, 1.0, 0.0 );
+ glRotatef( 180.0, 0.0, 0.0, 1.0 );
+ glTranslatef( (float) -win_w/2.0, (float) -win_h/2.0, 0.0 );
+
+ /* glDrawBuffer( GL_BACK ); // Is there ever a need to draw to back buffer??
*/
+
+ // main_panel->draw_bkgd_box( 0, 0, win_w, win_h );
+ main_panel->draw_recursive( 0, 0 );
+
+ /*glutSwapBuffers(); //performs flush also */
+ finish_drawing();
+}
+
+
+
+
+/*************************************** _glutBitmapWidthString() **********/
+
+int _glutBitmapWidthString( void *font, char *s )
+{
+ char *p = s;
+ int width = 0;
+
+ while( *p != '\0' ) {
+ width += glutBitmapWidth( font, *p );
+ p++;
+ }
+
+ return width;
+}
+
+/************************************ _glutBitmapString *********************/
+/* Displays the contents of a string using GLUT's bitmap character function */
+/* Does not handle newlines */
+
+void _glutBitmapString( void *font, char *s )
+{
+ char *p = s;
+
+ while( *p != '\0' ) {
+ glutBitmapCharacter( font, *p );
+ p++;
+ }
+}
+
+
+
+/****************************** GLUI_Main::reshape() **************/
+
+void GLUI_Main::reshape( int reshape_w, int reshape_h )
+{
+ int new_w, new_h;
+
+ pack_controls();
+
+ new_w = main_panel->w;/* + 1; */
+ new_h = main_panel->h;/* + 1; */
+
+ if ( reshape_w != new_w OR reshape_h != new_h ) {
+ this->w = new_w;
+ this->h = new_h;
+
+ glutReshapeWindow( new_w, new_h );
+ glutPostRedisplay();
+ }
+ else {
+ }
+
+ if ( TEST_AND( this->flags, GLUI_SUBWINDOW ) ) {
+ check_subwindow_position();
+
+ /***** if ( TEST_AND(this->flags,GLUI_SUBWINDOW_LEFT )) {
+ }
+ else if ( TEST_AND(this->flags,GLUI_SUBWINDOW_LEFT )) {
+ }
+ else if ( TEST_AND(this->flags,GLUI_SUBWINDOW_LEFT )) {
+ }
+ else if ( TEST_AND(this->flags,GLUI_SUBWINDOW_RIGHT )) {
+ }
+ ****/
+ }
+
+ glViewport( 0, 0, new_w, new_h );
+
+ /* printf( "%d: %d\n", glutGetWindow(), this->flags ); */
+
+ /* glutPostRedisplay(); */
+}
+
+
+/****************************** GLUI_Main::keyboard() **************/
+
+void GLUI_Main::keyboard(unsigned char key, int x, int y)
+{
+ GLUI_Control *new_control;
+
+ curr_modifiers = glutGetModifiers();
+
+ /*** If it's a tab or shift tab, we don't pass it on to the controls.
+ Instead, we use it to cycle through active controls ***/
+ if ( key == '\t' AND mouse_button_down == false ) {
+ if ( curr_modifiers & GLUT_ACTIVE_SHIFT ) {
+ new_control = find_prev_control( active_control );
+ }
+ else {
+ new_control = find_next_control( active_control );
+ }
+
+ /* if ( new_control )
+ printf( "new_control: %s\n", new_control->name );
+ */
+
+ disactivate_current_control();
+ activate_control( new_control, GLUI_ACTIVATE_TAB );
+ }
+ else if ( key == ' ' AND active_control
+ AND active_control->spacebar_mouse_click == true ) {
+ /*** If the user presses the spacebar, and a non-edittext control
+ is active, we send it a mouse down event followed by a mouse up
+ event (simulated mouse-click) ***/
+
+ active_control->mouse_down_handler( 0, 0 );
+ active_control->mouse_up_handler( 0, 0, true );
+ } else {
+ /*** Pass the keystroke onto the active control, if any ***/
+ if ( active_control != NULL )
+ active_control->key_handler( key, curr_modifiers );
+ }
+}
+
+
+/****************************** GLUI_Main::special() **************/
+
+void GLUI_Main::special(int key, int x, int y)
+{
+ curr_modifiers = glutGetModifiers();
+
+ /*** Pass the keystroke onto the active control, if any ***/
+ if ( active_control != NULL )
+ active_control->special_handler( key, glutGetModifiers() );
+}
+
+
+
+/****************************** GLUI_Main::mouse() **************/
+
+void GLUI_Main::mouse(int button, int state, int x, int y)
+{
+ int callthrough;
+ GLUI_Control *control;
+
+ /* printf( "MOUSE: %d %d\n", button, state ); */
+
+ callthrough = true;
+
+ curr_modifiers = glutGetModifiers();
+
+ if ( button == GLUT_LEFT ) {
+ control = find_control( x, y );
+
+ /*if ( control ) printf( "control: %s\n", control->name.string );
*/
+
+ if ( mouse_button_down AND active_control != NULL AND
+ state == GLUT_UP ) {
+ /** We just released the mouse, which was depressed at some
+ control **/
+
+ callthrough = active_control->
+ mouse_up_handler( x, y, control==active_control);
+ glutSetCursor( GLUT_CURSOR_LEFT_ARROW );
+
+ if ( active_control AND
+ active_control->active_type ==
+ GLUI_CONTROL_ACTIVE_MOUSEDOWN AND 0){
+ /*** This is a control that needs to be disactivated when the
+ mouse button is released ****/
+ disactivate_current_control();
+ }
+ }
+ else {
+ if ( control ) {
+ if ( NOT mouse_button_down AND state == GLUT_DOWN ) {
+ /*** We just pressed the mouse down at some control ***/
+
+ if ( active_control != control ) {
+ if ( active_control != NULL ) {
+ /** There is an active control still - disactivate it ***/
+ disactivate_current_control();
+ }
+ }
+
+ if ( control->enabled ) {
+ activate_control( control, GLUI_ACTIVATE_MOUSE );
+ callthrough = control->mouse_down_handler( x, y );
+ }
+ }
+ }
+ }
+
+ if ( state == GLUT_DOWN )
+ mouse_button_down = true;
+ else if ( state == GLUT_UP )
+ mouse_button_down = false;
+ }
+
+ /**
+ NO CALLTHROUGH NEEDED FOR MOUSE EVENTS
+ if ( callthrough AND glut_mouse_CB )
+ glut_mouse_CB( button, state, x, y );
+ **/
+
+ callthrough=callthrough; /* To get rid of compiler warnings */
+}
+
+
+/****************************** GLUI_Main::motion() **************/
+
+void GLUI_Main::motion(int x, int y)
+{
+ int callthrough;
+ GLUI_Control *control;
+
+ /* printf( "MOTION: %d %d\n", x, y ); */
+
+ callthrough = true;
+
+ control = find_control(x,y);
+
+ if ( mouse_button_down AND active_control != NULL ) {
+ callthrough =
+ active_control->mouse_held_down_handler(x,y,control==active_control);
+ }
+
+ /**
+ NO CALLTHROUGH NEEDED FOR MOUSE EVENTS
+
+ if ( callthrough AND glut_motion_CB )
+ glut_motion_CB(x,y);
+ **/
+
+ callthrough=callthrough; /* To get rid of compiler warnings */
+}
+
+
+/*********************** GLUI_Main::passive_motion() **************/
+
+void GLUI_Main::passive_motion(int x, int y)
+{
+ GLUI_Control *control;
+
+ control = find_control( x, y );
+
+ /* printf( "%p %p\n", control, mouse_over_control ); */
+
+ if ( control != mouse_over_control ) {
+ if ( mouse_over_control ) {
+ mouse_over_control->mouse_over( false, x, y );
+ }
+
+ if ( control ) {
+ control->mouse_over( true, x, y );
+ mouse_over_control = control;
+ }
+ }
+
+ /*
+ if ( curr_cursor != GLUT_CURSOR_INHERIT ) {
+ curr_cursor = GLUT_CURSOR_INHERIT;
+ glutSetCursor( GLUT_CURSOR_INHERIT );
+ }*/
+
+}
+
+
+/****************************** GLUI_Main::entry() **************/
+
+void GLUI_Main::entry(int state)
+{
+ /*if ( NOT active_control OR ( active_control AND ( active_control->type ==
GLUI_CONTROL_EDITTEXT
+ OR active_control->type == GLUI_CONTROL_SPINNER) ) )*/
+ glutSetCursor( GLUT_CURSOR_LEFT_ARROW );
+}
+
+
+/****************************** GLUI_Main::visibility() **************/
+
+void GLUI_Main::visibility(int state)
+{
+}
+
+
+/****************************** GLUI_Main::idle() **************/
+
+void GLUI_Main::idle(void)
+{
+ /*** Pass the idle event onto the active control, if any ***/
+
+ /* printf( "IDLE \t" ); */
+
+ if ( active_control != NULL ) {
+ /* First we check if the control actually needs the idle right now.
+ Otherwise, let's avoid wasting cycles and OpenGL context switching */
+
+ if ( active_control->needs_idle() ) {
+ /*** Set the current glut window to the glui window */
+ /*** But don't change the window if we're already at that window ***/
+
+ if ( glut_window_id > 0 AND glutGetWindow() != glut_window_id ) {
+ glutSetWindow( glut_window_id );
+ }
+
+ active_control->idle();
+ }
+ }
+}
+
+
+/******************************************* GLUI_Main::find_control() ******/
+
+GLUI_Control *GLUI_Main::find_control( int x, int y )
+{
+ GLUI_Control *node, *last_container;
+
+ last_container = NULL;
+
+ node = main_panel;
+ while( node != NULL ) {
+ if ( node->type != GLUI_CONTROL_COLUMN AND
+ PT_IN_BOX( x, y,
+ node->x_abs, node->x_abs + node->w,
+ node->y_abs, node->y_abs + node->h ) ) {
+ /*** Point is inside current node ***/
+
+ if ( node->first_child() == NULL ) {
+ /*** SPECIAL CASE: for edittext boxes, we make sure click is
+ in box, and not on name string. This should be generalized
+ for all controls later... ***/
+ if ( node->type == GLUI_CONTROL_EDITTEXT ) {
+ if ( x < node->x_abs + ((GLUI_EditText*)node)->text_x_offset )
+ return (GLUI_Control*) node->parent();
+ }
+
+ return node; /* point is inside this node, and node has no children,
+ so return this node as the selected node */
+ }
+ else {
+ /*** This is a container class ***/
+ last_container = node;
+ node = (GLUI_Control*) node->first_child(); /* Descend into child */
+ }
+
+ }
+ else {
+ node = (GLUI_Control*) node->next();
+ }
+ }
+
+ /** No leaf-level nodes found to accept the mouse click, so
+ return the last container control found which DOES accept the click **/
+
+ if ( last_container ) {
+ /* printf( "ctrl: '%s'\n", last_container->name );
*/
+
+ return last_container;
+ }
+ else {
+ return NULL;
+ }
+}
+
+
+/************************************* GLUI_Main::pack_controls() ***********/
+
+void GLUI_Main::pack_controls( void )
+{
+ main_panel->pack(0,0);
+
+ /**** Now align controls within their bounds ****/
+ align_controls( main_panel );
+
+ /*** If this is a subwindow, expand panel to fit parent window ***/
+ if ( TEST_AND( this->flags, GLUI_SUBWINDOW ) ) {
+ int parent_h, parent_w;
+ int orig_window;
+
+ orig_window = glutGetWindow();
+ glutSetWindow( this->top_level_glut_window_id );
+ parent_h = glutGet( GLUT_WINDOW_HEIGHT );
+ parent_w = glutGet( GLUT_WINDOW_WIDTH );
+
+ glutSetWindow( orig_window );
+
+ /* printf( "%d %d\n", parent_h, parent_w ); */
+
+ if ( 1 ) {
+ if ( TEST_AND(this->flags,GLUI_SUBWINDOW_TOP )) {
+ main_panel->w = MAX( main_panel->w, parent_w );
+ }
+ else if ( TEST_AND(this->flags,GLUI_SUBWINDOW_LEFT )) {
+ main_panel->h = MAX( main_panel->h, parent_h );
+ }
+ else if ( TEST_AND(this->flags,GLUI_SUBWINDOW_BOTTOM )) {
+ main_panel->w = MAX( main_panel->w, parent_w );
+ }
+ else if ( TEST_AND(this->flags,GLUI_SUBWINDOW_RIGHT )) {
+ main_panel->h = MAX( main_panel->h, parent_h );
+ }
+ }
+ }
+
+ this->w = main_panel->w;
+ this->h = main_panel->h;
+}
+
+
+/************************************ GLUI_Main::align_controls() **********/
+
+void GLUI_Main::align_controls( GLUI_Control *control )
+{
+ GLUI_Control *child;
+
+ control->align();
+
+ child = (GLUI_Control*) control->first_child();
+
+ while( child != NULL ) {
+ align_controls( child );
+
+ child = (GLUI_Control*)child->next();
+ }
+}
+
+
+
+/*********************************** GLUI::set_main_gfx_window() ************/
+
+void GLUI::set_main_gfx_window( int window_id )
+{
+ main_gfx_window_id = window_id;
+}
+
+
+/********************************* GLUI_Main::post_update_main_gfx() ********/
+
+void GLUI_Main::post_update_main_gfx( void )
+{
+ int old_window;
+
+ if ( main_gfx_window_id > 0 ) {
+ old_window = glutGetWindow();
+ glutSetWindow( main_gfx_window_id );
+ glutPostRedisplay();
+ if( old_window > 0 )
+ glutSetWindow( old_window );
+ }
+}
+
+
+/********************************* GLUI_Main::set_front_draw_buffer() ********/
+
+int GLUI_Main::set_front_draw_buffer( void )
+{
+ GLint state;
+
+ glGetIntegerv( GL_DRAW_BUFFER, &state );
+
+ glDrawBuffer( GL_FRONT );
+
+ return (int)state;
+}
+
+
+/********************************* GLUI_Main::restore_draw_buffer() **********/
+
+void GLUI_Main::restore_draw_buffer( int buffer_state )
+{
+ glDrawBuffer( buffer_state );
+}
+
+
+/******************************************** GLUI_Main::GLUI_Main() ********/
+
+GLUI_Main::GLUI_Main( void )
+{
+ mouse_button_down = false;
+ w = 0;
+ h = 0;
+ active_control = NULL;
+ mouse_over_control = NULL;
+ main_gfx_window_id = -1;
+ glut_window_id = -1;
+ curr_modifiers = 0;
+ closing = false;
+ parent_window = -1;
+ glui_id = GLUI_Master.glui_id_counter;
+ GLUI_Master.glui_id_counter++;
+
+ font = GLUT_BITMAP_HELVETICA_12;
+ curr_cursor = GLUT_CURSOR_LEFT_ARROW;
+
+ bkgd_color.set( 200, 200, 200 );
+ bkgd_color_f[0] = 200.0 / 255.0;
+ bkgd_color_f[1] = 200.0 / 255.0;
+ bkgd_color_f[2] = 200.0 / 255.0;
+
+ /*** Create the main panel ***/
+ main_panel = new GLUI_Panel;
+ main_panel->set_int_val( GLUI_PANEL_NONE );
+ main_panel->glui = (GLUI*) this;
+ main_panel->name = "\0";
+}
+
+/************************************ GLUI_Main::draw_raised_box() **********/
+
+void GLUI_Main::draw_raised_box( int x, int y, int w, int h )
+{
+ w = w+x;
+ h = h+y;
+
+ glColor3ub( bkgd_color.r, bkgd_color.g, bkgd_color.b );
+ glBegin( GL_LINE_LOOP );
+ glVertex2i( x+1, y+1 ); glVertex2i( w-1, y+1 );
+ glVertex2i( w-1, h-1 ); glVertex2i( x+1, h-1 );
+ glEnd();
+
+ glColor3d( 1.0, 1.0, 1.0 );
+ glBegin( GL_LINE_STRIP );
+ glVertex2i( x, h ); glVertex2i( x, y ); glVertex2i( w, y );
+ glEnd();
+
+ glColor3d( 0.0, 0.0, 0.0 );
+ glBegin( GL_LINE_STRIP );
+ glVertex2i( w, y ); glVertex2i( w, h ); glVertex2i( x, h );
+ glEnd();
+
+ glColor3d( .5, .5, .5 );
+ glBegin( GL_LINE_STRIP );
+ glVertex2i( w-1, y+1 ); glVertex2i( w-1, h-1 ); glVertex2i( x+1, h-1 );
+ glEnd();
+}
+
+
+/************************************ GLUI_Main::draw_lowered_box() **********/
+/* Not quite perfect... **/
+
+void GLUI_Main::draw_lowered_box( int x, int y, int w, int h )
+{
+ w = w+x;
+ h = h+y;
+
+ glColor3ub( bkgd_color.r, bkgd_color.g, bkgd_color.b );
+ glBegin( GL_LINE_LOOP );
+ glVertex2i( x+1, y+1 ); glVertex2i( w-1, y+1 );
+ glVertex2i( w-1, h-1 ); glVertex2i( x+1, h-1 );
+ glEnd();
+
+ glColor3d( 0.0, 0.0, 0.0 );
+ glBegin( GL_LINE_STRIP );
+ glVertex2i( x, h ); glVertex2i( x, y ); glVertex2i( w, y );
+ glEnd();
+
+ glColor3d( 1.0, 1.0, 1.0 );
+ glBegin( GL_LINE_STRIP );
+ glVertex2i( w, y ); glVertex2i( w, h ); glVertex2i( x, h );
+ glEnd();
+
+ glColor3d( .5, .5, .5 );
+ glBegin( GL_LINE_STRIP );
+ glVertex2i( w-1, y+1 ); glVertex2i( w-1, h-1 ); glVertex2i( x+1, h-1 );
+ glEnd();
+}
+
+
+/************************************* GLUI_Main::activate_control() *********/
+
+void GLUI_Main::activate_control( GLUI_Control *control, int how )
+{
+ /** Are we not activating a control in the same window as the
+ previous active control? */
+ if ( GLUI_Master.active_control_glui AND
+ this != (GLUI_Main*) GLUI_Master.active_control_glui ) {
+ GLUI_Master.active_control_glui->disactivate_current_control();
+ }
+
+ /******* Now activate it *****/
+ if ( control != NULL AND control->can_activate AND control->enabled ) {
+ active_control = control;
+
+ control->activate(how);
+
+ /*if ( NOT active_control->is_container OR */
+ /* active_control->type == GLUI_CONTROL_ROLLOUT) { */
+ active_control->translate_and_draw_front();
+ /*} */
+ }
+ else {
+ active_control = NULL;
+ }
+
+ /* printf( "activate: %d\n", glutGetWindow() ); */
+ GLUI_Master.active_control = active_control;
+ GLUI_Master.active_control_glui = (GLUI*) this;
+}
+
+
+/************************* GLUI_Main::disactivate_current_control() **********/
+
+void GLUI_Main::disactivate_current_control( void )
+{
+ int orig;
+
+ if ( active_control != NULL ) {
+ orig = active_control->set_to_glut_window();
+
+ active_control->disactivate();
+
+ /** If this isn't a container control, then redraw it in its
+ disactivated state. Container controls, such as panels, look
+ the same activated or not **/
+
+ /*if ( NOT active_control->is_container OR */
+ /* active_control->type == GLUI_CONTROL_ROLLOUT ) { */
+ active_control->translate_and_draw_front();
+ /*} */
+
+ active_control->restore_window( orig );
+
+ active_control = NULL;
+ }
+
+ /* printf( "disactivate: %d\n", glutGetWindow() ); */
+ GLUI_Master.active_control = NULL;
+ GLUI_Master.active_control_glui = NULL;
+}
+
+
+/****************************** GLUI_Main::find_next_control() **************/
+
+GLUI_Control *GLUI_Main::find_next_control_( GLUI_Control *control )
+{
+ /*** THIS IS NOT find_next_control()! This is an unused older
+ version (look at the underscore at the end) ***/
+
+ if ( control == NULL )
+ return find_next_control_rec( main_panel );
+ else
+ return find_next_control_rec( control );
+}
+
+/****************************** GLUI_Main::find_next_control() **************/
+
+GLUI_Control *GLUI_Main::find_next_control_rec( GLUI_Control *control )
+{
+ GLUI_Control *child = NULL, *rec_control, *sibling;
+
+ /*** Recursively investigate children ***/
+ child = (GLUI_Control*) control->first_child();
+ if ( child ) {
+ /*** If we can activate the first child, then do so ***/
+ if ( child->can_activate AND child->enabled )
+ return child;
+ else /*** Recurse into first child ***/
+ rec_control = find_next_control_rec( child );
+
+ if ( rec_control )
+ return rec_control;
+ }
+
+ /*** At this point, either we don't have children, or the child cannot
+ be activated. So let's try the next sibling ***/
+
+ sibling = (GLUI_Control*) control->next();
+ if ( sibling ) {
+ if ( sibling->can_activate AND sibling->enabled )
+ return sibling;
+ else /*** Recurse into sibling ***/
+ rec_control = find_next_control_rec( sibling );
+
+ if ( rec_control )
+ return rec_control;
+ }
+
+ return NULL;
+}
+
+
+/****************************** GLUI_Main::find_next_control() **************/
+
+GLUI_Control *GLUI_Main::find_next_control( GLUI_Control *control )
+{
+ GLUI_Control *tmp_control = NULL;
+ int back_up;
+
+ if ( control == NULL )
+ control = main_panel;
+
+ while( control != NULL ) {
+ /** see if this control has a child **/
+ tmp_control = (GLUI_Control*) control->first_child();
+
+ if ( tmp_control != NULL ) {
+ if ( tmp_control->can_activate AND tmp_control->enabled )
+ return tmp_control;
+
+ control = tmp_control; /* Descend into child */
+ continue;
+ }
+
+ /*** At this point, control has no children ***/
+
+ /** see if this control has a next sibling **/
+ tmp_control = (GLUI_Control*) control->next();
+
+ if ( tmp_control != NULL ) {
+ if ( tmp_control->can_activate AND tmp_control->enabled )
+ return tmp_control;
+
+ control = tmp_control;
+ continue;
+ }
+
+ /** back up until we find a sibling of an ancestor **/
+ back_up = true;
+ while ( control->parent() AND back_up ) {
+ control = (GLUI_Control*) control->parent();
+
+ if ( control->next() ) {
+ control = (GLUI_Control*) control->next();
+ if ( control->can_activate AND control->enabled )
+ return control;
+ else
+ back_up = false;
+
+ /*** if ( control->is_container ) {
+ tmp_control = control;
+ control = NULL;
+ break;
+ }
+ else {
+ back_up = false;
+ }
+ ***/
+ }
+ }
+
+ /** Check if we've cycled back to the top... if so, return NULL **/
+ if ( control == main_panel ) {
+ return NULL;
+ }
+ }
+ /*
+ if ( tmp_control != NULL AND tmp_control->can_activate AND
+ tmp_control->enabled ) {
+ return tmp_control;
+ }*/
+
+ return NULL;
+}
+
+
+/****************************** GLUI_Main::find_prev_control() **************/
+
+GLUI_Control *GLUI_Main::find_prev_control( GLUI_Control *control )
+{
+ GLUI_Control *tmp_control, *next_control;
+
+ if ( control == NULL ) { /* here we find the last valid control */
+ next_control = main_panel;
+
+ do {
+ tmp_control = next_control;
+ next_control = find_next_control( tmp_control );
+ } while( next_control != NULL );
+
+ return tmp_control;
+ }
+ else { /* here we find the actual previous control */
+ next_control = main_panel;
+
+ do {
+ tmp_control = next_control;
+ next_control = find_next_control( tmp_control );
+ } while( next_control != NULL AND next_control != control );
+
+ if ( next_control == NULL OR tmp_control == main_panel )
+ return NULL;
+ else
+ return tmp_control;
+ }
+}
+
+/************************* GLUI_Master_Object::set_glutIdleFunc() ***********/
+
+void GLUI_Master_Object::set_glutIdleFunc(void (*f)(void))
+{
+ glut_idle_CB = f;
+ glutIdleFunc( glui_idle_func );
+}
+
+
+/**************************************** GLUI::disable() ********************/
+
+void GLUI::disable( void )
+{
+ disactivate_current_control();
+ main_panel->disable();
+}
+
+
+/******************************************** GLUI::sync_live() **************/
+
+void GLUI::sync_live( void )
+{
+ main_panel->sync_live(true, true);
+}
+
+
+/********************************* GLUI_Master_Object::sync_live_all() *****/
+
+void GLUI_Master_Object::sync_live_all( void )
+{
+ GLUI *glui;
+
+ glui = (GLUI*) GLUI_Master.gluis.first_child();
+ while( glui ) {
+
+ glui->sync_live(); /** sync it **/
+
+ glui = (GLUI*) glui->next();
+ }
+}
+
+
+/************************************* GLUI_Master_Object::close() **********/
+
+void GLUI_Master_Object::close_all( void )
+{
+ GLUI *glui;
+
+ glui = (GLUI*) GLUI_Master.gluis.first_child();
+ while( glui ) {
+
+ glui->close(); /** Set flag to close **/
+
+ glui = (GLUI*) glui->next();
+ }
+}
+
+
+/************************************* GLUI_Main::close_internal() **********/
+
+void GLUI_Main::close_internal( void )
+{
+ glutDestroyWindow(glutGetWindow()); /** Close this window **/
+
+ this->unlink();
+
+ if ( GLUI_Master.active_control_glui == this ) {
+ GLUI_Master.active_control = NULL;
+ GLUI_Master.active_control_glui = NULL;
+ }
+
+ if ( parent_window != -1 ) {
+ glutSetWindow( parent_window );
+ int win_w = glutGet( GLUT_WINDOW_WIDTH );
+ int win_h = glutGet( GLUT_WINDOW_HEIGHT );
+ glutReshapeWindow(win_w+1, win_h);
+ glutReshapeWindow(win_w-1, win_h);
+ glutPostRedisplay();
+ }
+
+ delete this->main_panel;
+
+ delete this;
+}
+
+
+/************************************************** GLUI::close() **********/
+
+void GLUI::close( void )
+{
+ int old_glut_window;
+
+ closing = true;
+
+ old_glut_window = glutGetWindow();
+ glutSetWindow( get_glut_window_id() );
+ glutPostRedisplay();
+
+ glutSetWindow( old_glut_window );
+}
+
+
+/************************** GLUI_Main::check_subwindow_position() **********/
+
+void GLUI_Main::check_subwindow_position( void )
+{
+ /*** Reposition this window if subwindow ***/
+ if ( TEST_AND( this->flags, GLUI_SUBWINDOW ) ) {
+
+ int parent_w, parent_h, new_x, new_y;
+ int old_window = glutGetWindow();
+
+ glutSetWindow( glut_window_id );
+
+ glutSetWindow( glutGet( GLUT_WINDOW_PARENT ));
+ parent_w = glutGet( GLUT_WINDOW_WIDTH );
+ parent_h = glutGet( GLUT_WINDOW_HEIGHT );
+
+ glutSetWindow( glut_window_id );
+
+ if ( TEST_AND(this->flags,GLUI_SUBWINDOW_RIGHT )) {
+ new_x = parent_w - this->w;
+ new_y = 0;
+ }
+ else if ( TEST_AND(this->flags,GLUI_SUBWINDOW_LEFT )) {
+ new_x = 0;
+ new_y = 0;
+ }
+ else if ( TEST_AND(this->flags,GLUI_SUBWINDOW_BOTTOM )) {
+ new_x = 0;
+ new_y = parent_h - this->h;
+ }
+ else { /*** GLUI_SUBWINDOW_TOP ***/
+ new_x = 0;
+ new_y = 0;
+ }
+
+ /** Now make adjustments based on presence of other subwindows **/
+ GLUI *curr_glui;
+ curr_glui = (GLUI*) GLUI_Master.gluis.first_child();
+ while( curr_glui ) {
+ if ( TEST_AND( curr_glui->flags, GLUI_SUBWINDOW) AND
+ curr_glui->parent_window == this->parent_window ) {
+
+ if ( TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_LEFT ) ) {
+ }
+ else if ( TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_BOTTOM ) ) {
+ }
+ else if ( TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_RIGHT ) ) {
+ }
+ else if ( TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_TOP ) AND
+ ( TEST_AND( this->flags,GLUI_SUBWINDOW_LEFT ) OR
+ TEST_AND( this->flags,GLUI_SUBWINDOW_RIGHT ) ) ) {
+ /** If we are a RIGHT or LEFT subwindow, and there exists some
+ TOP subwindow, bump our position down **/
+
+ new_y += curr_glui->h;
+ }
+
+ /** CHeck multiple subwins at same position **/
+ /** We check the glui_id's: only the glui with the higher
+ ID number (meaning it was created later) gets bumped over **/
+ if ( curr_glui != this AND this->glui_id > curr_glui->glui_id ) {
+ if ( TEST_AND( this->flags,GLUI_SUBWINDOW_LEFT ) AND
+ TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_LEFT ) ) {
+ new_x += curr_glui->w;
+ }
+ else if ( TEST_AND( this->flags,GLUI_SUBWINDOW_TOP ) AND
+ TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_TOP ) ) {
+ new_y += curr_glui->h;
+ }
+ else if ( TEST_AND( this->flags,GLUI_SUBWINDOW_BOTTOM ) AND
+ TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_BOTTOM ) ) {
+ new_y -= curr_glui->h;
+ }
+ else if ( TEST_AND( this->flags,GLUI_SUBWINDOW_RIGHT ) AND
+ TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_RIGHT ) ) {
+ new_x -= curr_glui->w;
+ }
+
+ }
+ }
+
+ curr_glui = (GLUI*) curr_glui->next();
+ }
+
+
+
+ CLAMP( new_x, 0, new_x );
+ CLAMP( new_y, 0, new_y );
+
+ glutPositionWindow( new_x, new_y );
+ /* glutPostRedisplay(); */
+
+ glutSetWindow( old_window );
+ }
+}
+
+
+/********************************* GLUI_Master_Object::reshape() **********/
+/* This gets called by the user from a GLUT reshape callback. So we look */
+/* for subwindows that belong to the current window */
+
+void GLUI_Master_Object::reshape( void )
+{
+ GLUI *glui;
+ int current_window;
+
+ current_window = glutGetWindow();
+
+ glui = (GLUI*) GLUI_Master.gluis.first_child();
+ while( glui ) {
+ if ( TEST_AND( glui->flags, GLUI_SUBWINDOW) AND
+ glui->parent_window == current_window ) {
+ glutSetWindow( glui->get_glut_window_id());
+ glui->check_subwindow_position();
+ }
+
+ glui = (GLUI*) glui->next();
+ }
+
+ glutSetWindow(current_window);
+}
+
+
+/**************************** GLUI_Master_Object::set_glutReshapeFunc() *****/
+
+void GLUI_Master_Object::set_glutReshapeFunc(void (*f)(int width, int height))
+{
+ glutReshapeFunc( glui_reshape_func );
+ add_cb_to_glut_window( glutGetWindow(), GLUI_GLUT_RESHAPE, (void*) f);
+}
+
+
+/**************************** GLUI_Master_Object::set_glutKeyboardFunc() ****/
+
+void GLUI_Master_Object::set_glutKeyboardFunc(void (*f)(unsigned char key,
+ int x, int y))
+{
+ glutKeyboardFunc( glui_keyboard_func );
+ add_cb_to_glut_window( glutGetWindow(), GLUI_GLUT_KEYBOARD, (void*) f);
+}
+
+
+/*********************** GLUI_Master_Object::set_glutSpecialFunc() **********/
+
+void GLUI_Master_Object::set_glutSpecialFunc(void (*f)(int key,
+ int x, int y))
+{
+ glutSpecialFunc( glui_special_func );
+ add_cb_to_glut_window( glutGetWindow(), GLUI_GLUT_SPECIAL, (void*) f);
+}
+
+
+/*********************** GLUI_Master_Object::set_glutMouseFunc() **********/
+
+void GLUI_Master_Object::set_glutMouseFunc(void (*f)(int button, int state,
+ int x, int y))
+{
+ glutMouseFunc( glui_mouse_func );
+ add_cb_to_glut_window( glutGetWindow(), GLUI_GLUT_MOUSE, (void*) f);
+}
+
+
+/****************************** glui_parent_window_reshape_func() **********/
+/* This is the reshape callback for a window that contains subwindows */
+
+void glui_parent_window_reshape_func( int w, int h )
+{
+ int current_window;
+ GLUI *glui;
+ int first = true;
+
+ /* printf( "glui_parent_window_reshape_func: %d\n", glutGetWindow() );
*/
+
+ current_window = glutGetWindow();
+
+ glui = (GLUI*) GLUI_Master.gluis.first_child();
+ while( glui ) {
+ if ( TEST_AND( glui->flags, GLUI_SUBWINDOW) AND
+ glui->parent_window == current_window ) {
+ glutSetWindow( glui->get_glut_window_id());
+ glui->check_subwindow_position();
+ glutSetWindow( current_window );
+
+ if ( first ) {
+ glui->glut_reshape_CB( w, h );
+
+ first = false;
+ }
+ }
+
+ glui = (GLUI*) glui->next();
+ }
+}
+
+
+/****************************** glui_parent_window_keyboard_func() **********/
+
+void glui_parent_window_keyboard_func(unsigned char key, int x, int y)
+{
+ /* printf( "glui_parent_window_keyboard_func: %d\n", glutGetWindow() );
*/
+
+ int current_window;
+ GLUI *glui;
+
+ current_window = glutGetWindow();
+
+ if ( GLUI_Master.active_control_glui AND GLUI_Master.active_control ) {
+ glutSetWindow( GLUI_Master.active_control_glui->get_glut_window_id() );
+
+ GLUI_Master.active_control_glui->keyboard(key,x,y);
+
+ glutSetWindow( current_window );
+ }
+ else {
+ glui = (GLUI*) GLUI_Master.gluis.first_child();
+ while( glui ) {
+ if ( TEST_AND( glui->flags, GLUI_SUBWINDOW) AND
+ glui->parent_window == current_window ) {
+ glui->glut_keyboard_CB( key, x, y );
+ break;
+ }
+
+ glui = (GLUI*) glui->next();
+ }
+ }
+}
+
+
+/****************************** glui_parent_window_special_func() **********/
+
+void glui_parent_window_special_func(int key, int x, int y)
+{
+ /*printf( "glui_parent_window_special_func: %d\n", glutGetWindow() );
*/
+
+ int current_window;
+ GLUI *glui;
+
+ /** If clicking in the main area of a window w/subwindows,
+ disactivate any current control **/
+ if ( GLUI_Master.active_control_glui != NULL )
+ GLUI_Master.active_control_glui->disactivate_current_control();
+
+ /*** Now pass on the mouse event ***/
+
+ current_window = glutGetWindow();
+
+ glui = (GLUI*) GLUI_Master.gluis.first_child();
+ while( glui ) {
+ if ( TEST_AND( glui->flags, GLUI_SUBWINDOW) AND
+ glui->parent_window == current_window ) {
+ glutSetWindow( glui->get_glut_window_id());
+ glui->glut_special_CB( key, x, y );
+ break;
+ }
+
+ glui = (GLUI*) glui->next();
+ }
+}
+
+
+/****************************** glui_parent_window_mouse_func() **********/
+
+void glui_parent_window_mouse_func(int button, int state, int x, int y)
+{
+ int current_window;
+ GLUI *glui;
+
+ /** If clicking in the main area of a window w/subwindows,
+ disactivate any current control **/
+ if ( GLUI_Master.active_control_glui != NULL )
+ GLUI_Master.active_control_glui->disactivate_current_control();
+
+
+ /*** Now pass on the mouse event ***/
+
+ current_window = glutGetWindow();
+
+ glui = (GLUI*) GLUI_Master.gluis.first_child();
+ while( glui ) {
+ if ( TEST_AND( glui->flags, GLUI_SUBWINDOW) AND
+ glui->parent_window == current_window ) {
+ glutSetWindow( glui->get_glut_window_id());
+ glui->glut_mouse_CB( button, state, x, y );
+ break;
+ }
+
+ glui = (GLUI*) glui->next();
+ }
+
+}
+
+
+/************************** GLUI_Master_Object::find_glut_window() **********/
+
+GLUI_Glut_Window *GLUI_Master_Object::find_glut_window( int window_id )
+{
+ GLUI_Glut_Window *window;
+
+ window = (GLUI_Glut_Window*) glut_windows.first_child();
+ while( window ) {
+ if ( window->glut_window_id == window_id )
+ return window;
+
+ window = (GLUI_Glut_Window*) window->next();
+ }
+
+ /*** Window not found - return NULL ***/
+ return NULL;
+}
+
+
+/******************** GLUI_Master_Object::add_cb_to_glut_window() **********/
+
+void GLUI_Master_Object::add_cb_to_glut_window(int window_id,
+ int cb_type,void *cb)
+{
+ GLUI_Glut_Window *window;
+
+ window = find_glut_window( window_id );
+ if ( NOT window ) {
+ /*** Allocate new window structure ***/
+
+ window = new GLUI_Glut_Window;
+ window->glut_window_id = window_id;
+ window->link_this_to_parent_last( (GLUI_Node*) &this->glut_windows );
+ }
+
+ switch( cb_type ) {
+ case GLUI_GLUT_RESHAPE:
+ window->glut_reshape_CB = (void(*)(int,int)) cb;
+ break;
+ case GLUI_GLUT_DISPLAY:
+ window->glut_display_CB = (void(*)()) cb;
+ break;
+ case GLUI_GLUT_KEYBOARD:
+ window->glut_keyboard_CB = (void(*)(unsigned char,int,int)) cb;
+ break;
+ case GLUI_GLUT_SPECIAL:
+ window->glut_special_CB = (void(*)(int,int,int)) cb;
+ break;
+ case GLUI_GLUT_MOUSE:
+ window->glut_mouse_CB = (void(*)(int,int,int,int)) cb;
+ break;
+ case GLUI_GLUT_MOTION:
+ window->glut_motion_CB = (void(*)(int,int)) cb;
+ break;
+ case GLUI_GLUT_PASSIVE_MOTION:
+ window->glut_passive_motion_CB = (void(*)(int,int)) cb;
+ break;
+ case GLUI_GLUT_ENTRY:
+ window->glut_entry_CB = (void(*)(int)) cb;
+ break;
+ case GLUI_GLUT_VISIBILITY:
+ window->glut_visibility_CB= (void(*)(int)) cb;
+ break;
+ }
+}
+
+
+/************* GLUI_Master_Object::set_left_button_glut_menu_control() *****/
+
+void GLUI_Master_Object::set_left_button_glut_menu_control(
+ GLUI_Control *control )
+{
+ curr_left_button_glut_menu = control;
+}
+
+
+/******************************* GLUI_Main::set_ortho_projection() **********/
+
+void GLUI_Main::set_ortho_projection( void )
+{
+ int win_h, win_w;
+
+ win_w = glutGet( GLUT_WINDOW_WIDTH );
+ win_h = glutGet( GLUT_WINDOW_HEIGHT );
+
+ glViewport(0, 0, win_w, win_h);
+ glMatrixMode( GL_PROJECTION );
+ glLoadIdentity();
+ /* gluOrtho2D( 0.0, (float) win_w, 0.0, (float) win_h ); */
+ glOrtho( 0.0, (float)win_w, 0.0, (float) win_h, -1000.0, 1000.0 );
+
+ glMatrixMode( GL_MODELVIEW );
+
+ return; /****-----------------------------------------------***/
+
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+
+ /*** Rotate image so y increases upwards, contrary to OpenGL axes ***/
+ glTranslatef( (float) win_w/2.0, (float) win_h/2.0, 0.0 );
+ glRotatef( 180.0, 0.0, 1.0, 0.0 );
+ glRotatef( 180.0, 0.0, 0.0, 1.0 );
+ glTranslatef( (float) -win_w/2.0, (float) -win_h/2.0, 0.0 );
+}
+
+
+/******************************* GLUI_Main::set_viewport() **********/
+
+void GLUI_Main::set_viewport( void )
+{
+ glViewport( 0, 0, main_panel->w, main_panel->h );
+}
+
+
+/****************************** GLUI_Main::refresh() ****************/
+
+void GLUI_Main::refresh( void )
+{
+ int orig;
+ int new_w, new_h;
+
+ /****** GLUI_Glut_Window *glut_window;
+ int current_window;
+ current_window = glutGetWindow();
+ glut_window = GLUI_Master.find_glut_window( current_window );
+ if ( glut_window ) {
+ glut_window->glut_reshape_CB(w,h);
+ ******/
+
+ orig = glutGetWindow();
+
+ pack_controls();
+
+ if ( TEST_AND( this->flags, GLUI_SUBWINDOW ) ) {
+ /*** GLUI subwindow ***/
+
+ check_subwindow_position();
+
+ if ( glut_window_id > 0 )
+ glutSetWindow( glut_window_id );
+ glutPostRedisplay();
+
+ /* printf( "top_level: %d\n", top_level_glut_window_id );*/
+ glutSetWindow( top_level_glut_window_id );
+ }
+ else {
+ /*** Standalone GLUI window ***/
+
+ if ( glut_window_id > 0 )
+ glutSetWindow( glut_window_id );
+
+ new_h = glutGet( GLUT_WINDOW_HEIGHT );
+ new_w = glutGet( GLUT_WINDOW_WIDTH );
+
+ new_h = this->h;
+ new_w = this->w;
+
+ glutReshapeWindow( new_w, new_h );
+
+ glutPostRedisplay();
+ }
+
+ glutSetWindow( orig);
+}
+
+
+
+/***************** GLUI_Master_Object::get_main_gfx_viewport() ***********/
+
+void GLUI_Master_Object::get_viewport_area( int *x, int *y,
+ int *w, int *h )
+{
+ GLUI *curr_glui;
+ int curr_x, curr_y, curr_w, curr_h;
+ int curr_window;
+
+ curr_window = glutGetWindow();
+ curr_x = 0;
+ curr_y = 0;
+ curr_w = glutGet( GLUT_WINDOW_WIDTH );
+ curr_h = glutGet( GLUT_WINDOW_HEIGHT );
+
+ curr_glui = (GLUI*) gluis.first_child();
+ while( curr_glui ) {
+ if ( TEST_AND( curr_glui->flags, GLUI_SUBWINDOW) AND
+ curr_glui->parent_window == curr_window ) {
+
+ /* printf( "%s -> %d %d %d\n",
curr_glui->window_name.string, curr_glui->flags,
+ curr_glui->w, curr_glui->h );*/
+
+ if ( TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_LEFT ) ) {
+ curr_x += curr_glui->w;
+ curr_w -= curr_glui->w;
+ }
+ else if ( TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_BOTTOM ) ) {
+ curr_y += curr_glui->h;
+ curr_h -= curr_glui->h;
+ }
+ else if ( TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_RIGHT ) ) {
+ curr_w -= curr_glui->w;
+ }
+ else if ( TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_TOP ) ) {
+ curr_h -= curr_glui->h;
+ }
+ }
+
+ curr_glui = (GLUI*) curr_glui->next();
+ }
+
+ curr_x = MAX( 0, curr_x );
+ curr_y = MAX( 0, curr_y );
+ curr_w = MAX( 0, curr_w );
+ curr_h = MAX( 0, curr_h );
+
+ *x = curr_x;
+ *y = curr_y;
+ *w = curr_w;
+ *h = curr_h;
+}
+
+
+/*****************GLUI_Master_Object::auto_set_main_gfx_viewport() **********/
+
+void GLUI_Master_Object::auto_set_viewport( void )
+{
+ int x, y, w, h;
+
+ get_viewport_area( &x, &y, &w, &h );
+ glViewport( MAX(x,0), MAX(y,0), MAX(w,0), MAX(h,0) );
+}
+
+
+
+/***************************************** GLUI::show() **********************/
+
+void GLUI::show( void )
+{
+ int orig_window;
+
+ orig_window = main_panel->set_to_glut_window();
+
+ glutShowWindow();
+
+ main_panel->restore_window(orig_window);
+}
+
+
+
+/***************************************** GLUI::hide() **********************/
+
+void GLUI::hide( void )
+{
+ int orig_window;
+
+ this->disactivate_current_control();
+
+ orig_window = main_panel->set_to_glut_window();
+
+ glutHideWindow();
+
+ main_panel->restore_window(orig_window);
+}
Index: external/trimesh/gluit/glui_img_listbox_up.c
--- external/trimesh/gluit/glui_img_listbox_up.c (revision 0)
+++ external/trimesh/gluit/glui_img_listbox_up.c (revision 0)
@@ -0,0 +1,42 @@
+
+
+int glui_img_listbox_up[] = { 11, 17, /* width, height */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 191,191,191, 127,127,127, 127,127,127, 127,127,127,
+ 127,127,127, 127,127,127, 127,127,127, 127,127,127, 127,127,127,
+ 127,127,127, 0, 0, 0, 191,191,191, 255,255,255, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 127,127,127, 0, 0, 0, 191,191,191, 255,255,255,
+ 191,191,191, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 127,127,127, 0, 0, 0, 191,191,191,
+ 255,255,255, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 127,127,127, 0, 0, 0,
+ 191,191,191, 255,255,255, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 191,191,191, 127,127,127,
+ 0, 0, 0, 191,191,191, 255,255,255, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 127,127,127, 0, 0, 0, 191,191,191, 255,255,255, 191,191,191,
+ 191,191,191, 191,191,191, 0, 0, 0, 191,191,191, 191,191,191,
+ 191,191,191, 127,127,127, 0, 0, 0, 191,191,191, 255,255,255,
+ 191,191,191, 191,191,191, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 191,191,191, 191,191,191, 127,127,127, 0, 0, 0, 191,191,191,
+ 255,255,255, 191,191,191, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 191,191,191, 127,127,127, 0, 0, 0,
+ 191,191,191, 255,255,255, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 191,191,191, 127,127,127,
+ 0, 0, 0, 191,191,191, 255,255,255, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 127,127,127, 0, 0, 0, 191,191,191, 255,255,255, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 127,127,127, 0, 0, 0, 191,191,191, 255,255,255,
+ 191,191,191, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 127,127,127, 0, 0, 0, 191,191,191,
+ 255,255,255, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 127,127,127, 0, 0, 0,
+ 191,191,191, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,252, 255,255,255, 127,127,127,
+ 0, 0, 0, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 0, 0, 0,
+};
Index: external/trimesh/gluit/glui_algebra3.h
--- external/trimesh/gluit/glui_algebra3.h (revision 0)
+++ external/trimesh/gluit/glui_algebra3.h (revision 0)
@@ -0,0 +1,474 @@
+/**************************************************************************
+
+ algebra3.cpp, algebra3.h - C++ Vector and Matrix Algebra routines
+
+ There are three vector classes and two matrix classes: vec2, vec3,
+ vec4, mat3, and mat4.
+
+ All the standard arithmetic operations are defined, with '*'
+ for dot product of two vectors and multiplication of two matrices,
+ and '^' for cross product of two vectors.
+
+ Additional functions include length(), normalize(), homogenize for
+ vectors, and print(), set(), apply() for all classes.
+
+ There is a function transpose() for matrices, but note that it
+ does not actually change the matrix,
+
+ When multiplied with a matrix, a vector is treated as a row vector
+ if it precedes the matrix (v*M), and as a column vector if it
+ follows the matrix (M*v).
+
+ Matrices are stored in row-major form.
+
+ A vector of one dimension (2d, 3d, or 4d) can be cast to a vector
+ of a higher or lower dimension. If casting to a higher dimension,
+ the new component is set by default to 1.0, unless a value is
+ specified:
+ vec3 a(1.0, 2.0, 3.0 );
+ vec4 b( a, 4.0 ); // now b == {1.0, 2.0, 3.0, 4.0};
+ When casting to a lower dimension, the vector is homogenized in
+ the lower dimension. E.g., if a 4d {X,Y,Z,W} is cast to 3d, the
+ resulting vector is {X/W, Y/W, Z/W}. It is up to the user to
+ insure the fourth component is not zero before casting.
+
+ There are also the following function for building matrices:
+ identity2D(), translation2D(), rotation2D(),
+ scaling2D(), identity3D(), translation3D(),
+ rotation3D(), rotation3Drad(), scaling3D(),
+ perspective3D()
+
+ NOTE: When compiling for Windows, include this file first, to avoid
+ certain name conflicts
+
+ ---------------------------------------------------------------------
+
+ Author: Jean-Francois DOUEg
+ Revised: Paul Rademacher
+ Version 3.2 - Feb 1998
+
+**************************************************************************/
+
+#ifndef _ALGEBRA3_H_
+#define _ALGEBRA3_H_
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+// this line defines a new type: pointer to a function which returns a
+// float and takes as argument a float
+typedef float (*V_FCT_PTR)(float);
+
+// min-max macros
+#ifndef MIN
+#define MIN(A,B) ((A) < (B) ? (A) : (B))
+#define MAX(A,B) ((A) > (B) ? (A) : (B))
+#endif
+
+//#include <stream.h>
+// error handling macro
+//#define VEC_ERROR(E) { cerr << E; exit(1); }
+/*#define <<
+#define >>*/
+
+#ifdef VEC_ERROR_FATAL
+#ifndef VEC_ERROR
+#define VEC_ERROR(E) { printf( "VERROR %s\n", E ); exit(1); }
+#endif
+#else
+#ifndef VEC_ERROR
+#define VEC_ERROR(E) { printf( "VERROR %s\n", E ); }
+#endif
+#endif
+
+class vec2;
+class vec3;
+class vec4;
+class mat3;
+class mat4;
+
+/*#ifndef X
+enum {X,Y,Z,W};
+#endif
+*/
+
+/*#ifndef R
+enum {R,G,B,ALPHA};
+#endif
+*/
+
+#ifndef M_PI
+#define M_PI 3.141592654
+#endif
+
+
+enum {VX, VY, VZ, VW}; // axes
+enum {PA, PB, PC, PD}; // planes
+enum {RED, GREEN, BLUE, ALPHA}; // colors
+enum {KA, KD, KS, ES}; // phong coefficients
+
+/****************************************************************
+* *
+* 2D Vector *
+* *
+****************************************************************/
+
+class vec2
+{
+protected:
+
+ float n[2];
+
+public:
+
+ // Constructors
+
+ vec2(void);
+ vec2(const float x, const float y);
+ vec2(const float d);
+ vec2(const vec2& v); // copy constructor
+ vec2(const vec3& v); // cast v3 to v2
+ vec2(const vec3& v, int dropAxis);
// cast v3 to v2
+
+ // Assignment
operators
+
+ vec2& operator =
( const vec2& v ); // assignment of a vec2
+
vec2& operator += ( const vec2& v ); // incrementation by a vec2
+
vec2& operator -= ( const vec2& v ); //
decrementation by a vec2
+
vec2& operator *= ( const float d
); // multiplication by a constant
+
vec2&
operator /= ( const float d ); // division by a constant
+
float& operator [] ( int i); // indexing
+
+
// special functions
+
+
float length(void); // length of a vec2
+
float length2(void); //
squared length of a vec2
+
vec2&
normalize(void); // normalize a vec2
+
vec2& apply(V_FCT_PTR fct); // apply a func. to each component
+
void set( float x, float y ); // set vector
+
+
// friends
+
+
friend vec2 operator - (const
vec2& v); // -v1
+
friend vec2 operator + (const vec2& a, const vec2& b); // v1 + v2
+
friend vec2 operator - (const vec2& a, const vec2&
b); // v1 - v2
+
friend vec2 operator *
(const vec2& a, const float d); // v1 * 3.0
+
friend vec2 operator * (const float d, const vec2& a); // 3.0 * v1
+
friend vec2 operator * (const mat3& a, const
vec2& v); // M . v
+
friend vec2 operator *
(const vec2& v, mat3& a); // v . M
+
friend float operator * (const vec2& a, const vec2& b); // dot product
+
friend vec2 operator / (const vec2& a, const
float d); // v1 / 3.0
+
friend vec3
operator ^ (const vec2& a, const vec2& b); // cross product
+
friend int operator == (const vec2& a, const vec2& b); // v1 ==
v2 ?
+
friend int operator != (const vec2& a,
const vec2& b); // v1 != v2 ?
+
//friend
ostream& operator << (ostream& s, vec2& v); // output to stream
+
//friend istream& operator >> (istream& s, vec2& v);
// input from strm.
+
friend void swap(vec2& a, vec2&
b); // swap v1 & v2
+
friend
vec2 min_vec(const vec2& a, const vec2& b); // min(v1, v2)
+
friend vec2 max_vec(const vec2& a, const vec2& b);
// max(v1, v2)
+
friend vec2 prod(const
vec2& a, const vec2& b); // term by term *
+
+
// necessary friend declarations
+
+
friend class vec3;
+};
+
+/****************************************************************
+* *
+* 3D Vector *
+* *
+****************************************************************/
+
+class vec3
+{
+protected:
+
+ float n[3];
+
+public:
+
+ // Constructors
+
+ vec3(void);
+ vec3(const float x, const float y, const float z);
+ vec3(const float d);
+ vec3(const vec3& v); // copy constructor
+ vec3(const vec2& v); // cast v2 to v3
+ vec3(const vec2& v, float d);
// cast v2 to v3
+ vec3(const
vec4& v); // cast v4 to v3
+
vec3(const vec4& v, int dropAxis); // cast v4 to v3
+
+
// Assignment operators
+
+
vec3& operator = ( const vec3& v ); //
assignment of a vec3
+
vec3& operator += ( const
vec3& v ); // incrementation by a vec3
+
vec3&
operator -= ( const vec3& v ); // decrementation by a vec3
+
vec3& operator *= ( const float d ); // multiplication by a
constant
+
vec3& operator /= ( const float d ); //
division by a constant
+
float& operator [] ( int
i); // indexing
+
+
//
special functions
+
+
float
length(void); // length of a vec3
+
float length2(void); // squared length of a vec3
+
vec3& normalize(void); //
normalize a vec3
+
vec3&
homogenize(void); // homogenize (div by Z)
+
vec3& apply(V_FCT_PTR fct); // apply a func. to each component
+
void set( float x, float y, float z ); // set vector
+
void print( FILE *file, char *name );
// print vector to a file
+
+
// friends
+
+
friend vec3
operator - (const vec3& v); // -v1
+
friend vec3 operator + (const vec3& a, const vec3& b); //
v1 + v2
+
friend vec3 operator - (const vec3&
a, const vec3& b); // v1 - v2
+
friend
vec3 operator * (const vec3& a, const float d); // v1 * 3.0
+
friend vec3 operator * (const float d, const vec3& a); //
3.0 * v1
+
friend vec3 operator * (const
mat4& a, const vec3& v); // M . v
+
friend vec3 operator * (const vec3& v, mat4& a); // v . M
+
friend float operator * (const vec3& a, const vec3&
b); // dot product
+
friend vec3 operator / (const
vec3& a, const float d); // v1 / 3.0
+
friend vec3 operator ^ (const vec3& a, const vec3& b); // cross product
+
friend int operator == (const vec3& a, const
vec3& b); // v1 == v2 ?
+
friend int operator !=
(const vec3& a, const vec3& b); // v1 != v2 ?
+
//friend ostream& operator << (ostream& s, vec3& v); //
output to stream
+
//friend istream& operator >>
(istream& s, vec3& v); // input from strm.
+
friend void
swap(vec3& a, vec3& b); // swap v1 & v2
+
friend vec3 min_vec(const vec3& a, const vec3& b); // min(v1
, v2)
+
friend vec3 max_vec(const vec3&
a, const vec3& b); // max(v1, v2)
+
friend vec3 prod(const vec3& a, const vec3& b); // term by term *
+
+
// necessary friend declarations
+
+
friend class vec2;
+
friend class vec4;
+
friend class mat3;
+
friend vec2 operator * (const mat3& a, const vec2& v); // linear
transform
+
friend vec3 operator * (const mat3& a, const
vec3& v); // linear transform
+
friend mat3 operator
* (mat3& a, mat3& b); // matrix 3 product
+
+
};
+
+/****************************************************************
+* *
+* 4D Vector *
+* *
+****************************************************************/
+
+class vec4
+{
+protected:
+
+ float n[4];
+
+public:
+
+ // Constructors
+
+ vec4(void);
+ vec4(const float x, const float y, const float z, const float w);
+ vec4(const float d);
+ vec4(const vec4& v); // copy constructor
+ vec4(const vec3& v); // cast vec3 to vec4
+ vec4(const vec3& v, const float d);
// cast vec3 to vec4
+
+ // Assignment
operators
+
+ vec4&
operator = ( const vec4& v ); // assignment of a vec4
+
vec4& operator += ( const vec4& v ); // incrementation by a vec4
+
vec4& operator -= ( const vec4& v ); //
decrementation by a vec4
+
vec4& operator *= ( const float
d ); // multiplication by a constant
+
vec4&
operator /= ( const float d ); // division by a constant
+
float& operator [] ( int i); // indexing
+
+
// special functions
+
+
float length(void); // length of a
vec4
+
float length2(void);
// squared length of a vec4
+
vec4& normalize(void); // normalize a vec4
+
vec4& apply(V_FCT_PTR fct); // apply a func. to each
component
+
vec4& homogenize(void);
+
void print( FILE *file, char *name ); // print vector to a file
+
void set( float x, float y, float z, float a );
+
+
// friends
+
+
friend vec4 operator - (const vec4& v); // -v1
+
friend vec4 operator + (const
vec4& a, const vec4& b); // v1 + v2
+
friend vec4 operator - (const vec4& a, const vec4& b); // v1 - v2
+
friend vec4 operator * (const vec4& a, const float d);
// v1 * 3.0
+
friend vec4 operator * (const
float d, const vec4& a); // 3.0 * v1
+
friend vec4 operator * (const mat4& a, const vec4& v); // M . v
+
friend vec4 operator * (const vec4& v, mat4& a);
// v . M
+
friend float operator *
(const vec4& a, const vec4& b); // dot product
+
friend vec4 operator / (const vec4& a, const float d); // v1 / 3.0
+
friend int operator == (const vec4& a, const
vec4& b); // v1 == v2 ?
+
friend int operator !=
(const vec4& a, const vec4& b); // v1 != v2 ?
+
//friend ostream& operator << (ostream& s, vec4& v); //
output to stream
+
//friend istream& operator >>
(istream& s, vec4& v); // input from strm.
+
friend void
swap(vec4& a, vec4& b); // swap v1 & v2
+
friend vec4 min_vec(const vec4& a, const vec4& b); //
min(v1, v2)
+
friend vec4 max_vec(const vec4& a,
const vec4& b); // max(v1, v2)
+
friend vec4 prod(const vec4& a, const vec4& b); // term by term *
+
+
// necessary friend declarations
+
+
friend class vec3;
+
friend class mat4;
+
friend vec3 operator * (const mat4& a, const vec3& v); // linear transform
+
friend mat4 operator * (mat4& a, mat4& b); //
matrix 4 product
+
};
+
+/****************************************************************
+* *
+* 3x3 Matrix *
+* *
+****************************************************************/
+
+class mat3
+{
+protected:
+
+ vec3 v[3];
+
+public:
+
+ // Constructors
+
+ mat3(void);
+ mat3(const vec3& v0, const vec3& v1, const vec3& v2);
+ mat3(const float d);
+ mat3(const mat3& m);
+
+ // Assignment operators
+
+ mat3& operator = ( const mat3& m ); // assignment of a mat3
+ mat3& operator += ( const mat3& m ); //
incrementation by a mat3
+ mat3& operator -= ( const
mat3& m ); // decrementation by a mat3
+ mat3&
operator *= ( const float d ); // multiplication by a constant
+
mat3& operator /= ( const float d ); // division by a constant
+
vec3& operator [] ( int i); // indexing
+
+
// special functions
+
+
mat3 transpose(void);
// transpose
+
mat3
inverse(void); // inverse
+
mat3& apply(V_FCT_PTR fct); // apply a func. to each
element
+
void print( FILE *file, char *name ); //
print matrix to a file
+
void set(const vec3&
v0, const vec3& v1, const vec3& v2);
+
+
+
// friends
+
+
friend mat3 operator - (const mat3& a);
// -m1
+
friend mat3
operator + (const mat3& a, const mat3& b); // m1 + m2
+
friend mat3 operator - (const mat3& a, const mat3& b); // m1
- m2
+
friend mat3 operator * (mat3& a,
mat3& b); // m1 * m2
+
friend
mat3 operator * (const mat3& a, const float d); // m1 * 3.0
+
friend mat3 operator * (const float d, const mat3& a); //
3.0 * m1
+
friend mat3 operator / (const
mat3& a, const float d); // m1 / 3.0
+
friend int operator == (const mat3& a, const mat3& b); // m1 == m2 ?
+
friend int operator != (const mat3& a, const mat3& b);
// m1 != m2 ?
+
//friend ostream& operator
<< (ostream& s, mat3& m); // output to stream
+
//friend istream& operator >> (istream& s, mat3& m); // input from
strm.
+
friend void swap(mat3& a, mat3& b);
// swap m1 & m2
+
+
// necessary friend
declarations
+
+
friend vec3 operator *
(const mat3& a, const vec3& v); // linear transform
+
friend vec2 operator * (const mat3& a, const vec2& v); // linear
transform
+
};
+
+/****************************************************************
+* *
+* 4x4 Matrix *
+* *
+****************************************************************/
+
+class mat4
+{
+protected:
+public:
+
+ vec4 v[4];
+
+
+ // Constructors
+
+ mat4(void);
+ mat4(const vec4& v0, const vec4& v1, const vec4& v2, const vec4& v3);
+ mat4(const float d);
+ mat4(const mat4& m);
+ mat4(const float a00, const float a01, const float a02, const float a03,
+ const float a10, const float a11, const float a12, const float a13,
+ const float a20, const float a21, const float a22, const float a23,
+ const float a30, const float a31, const float a32, const float a33 );
+
+
+ // Assignment operators
+
+ mat4& operator = ( const mat4& m ); // assignment of a mat4
+ mat4& operator += ( const mat4& m ); //
incrementation by a mat4
+ mat4& operator -= ( const
mat4& m ); // decrementation by a mat4
+ mat4&
operator *= ( const float d ); // multiplication by a constant
+
mat4& operator /= ( const float d ); // division by a constant
+
vec4& operator [] ( int i); // indexing
+
+
// special functions
+
+
mat4 transpose(void);
// transpose
+
mat4
inverse(void); // inverse
+
mat4& apply(V_FCT_PTR fct); // apply a func. to each
element
+
void print( FILE *file, char *name ); //
print matrix to a file
+
void swap_rows( int
i, int j ); // swap rows i and j
+
void swap_cols( int i, int j ); // swap cols i and j
+
+
// friends
+
+
friend mat4 operator - (const mat4& a); //
-m1
+
friend mat4 operator + (const
mat4& a, const mat4& b); // m1 + m2
+
friend mat4 operator - (const mat4& a, const mat4& b); // m1 - m2
+
friend mat4 operator * (mat4& a, mat4& b);
// m1 * m2
+
friend mat4 operator *
(const mat4& a, const float d); // m1 * 4.0
+
friend mat4 operator * (const float d, const mat4& a); // 4.0 * m1
+
friend mat4 operator / (const mat4& a, const
float d); // m1 / 3.0
+
friend int operator
== (const mat4& a, const mat4& b); // m1 == m2 ?
+
friend int operator != (const mat4& a, const mat4& b); // m1 != m2
?
+
//friend ostream& operator <<
(ostream& s, mat4& m); // output to stream
+
//friend
istream& operator >> (istream& s, mat4& m); // input from strm.
+
friend void swap(mat4& a, mat4& b); // swap m1
& m2
+
+
// necessary friend declarations
+
+
friend vec4 operator * (const mat4&
a, const vec4& v); // linear transform
+
//friend
vec4 operator * (const vec4& v, const mat4& a); // linear transform
+
friend vec3 operator * (const mat4& a, const vec3& v);
// linear transform
+
friend vec3 operator * (const
vec3& v, const mat4& a); // linear transform
+
};
+
+/****************************************************************
+* *
+* 2D functions and 3D functions *
+* *
+****************************************************************/
+
+mat3 identity2D(void); // identity 2D
+mat3 translation2D(vec2& v); // translation 2D
+mat3 rotation2D(vec2& Center, const float angleDeg); // rotation 2D
+mat3 scaling2D(vec2& scaleVector); // scaling 2D
+mat4 identity3D(void); // identity 3D
+mat4 translation3D(vec3& v); // translation 3D
+mat4 rotation3D(vec3& Axis, const float angleDeg); // rotation 3D
+mat4 rotation3Drad(vec3& Axis, const float angleRad); // rotation 3D
+mat4 scaling3D(vec3& scaleVector); // scaling 3D
+mat4 perspective3D(const float d); // perspective 3D
+
+
+vec3 operator * (const vec3& v, mat3& a);
+vec2 operator * (const vec2& v, mat3& a);
+vec3 operator * (const vec3& v, mat4& a);
+vec4 operator * (const vec4& v, mat4& a);
+
+
+#endif
Index: external/trimesh/gluit/glui_listbox.cc
--- external/trimesh/gluit/glui_listbox.cc (revision 0)
+++ external/trimesh/gluit/glui_listbox.cc (revision 0)
@@ -0,0 +1,445 @@
+/****************************************************************************
+
+ GLUI User Interface Toolkit
+ ---------------------------
+
+ glui_listbox - GLUI_ListBox control class
+
+
+ --------------------------------------------------
+
+ Copyright (c) 1998 Paul Rademacher
+
+ This program is freely distributable without licensing fees and is
+ provided without guarantee or warrantee expressed or implied. This
+ program is -not- in the public domain.
+
+*****************************************************************************/
+
+#include "glui.h"
+#include "glui_stdinc.h"
+
+/****************************** GLUI_Listbox::mouse_down_handler() **********/
+
+int GLUI_Listbox::mouse_down_handler( int local_x, int local_y )
+{
+ return false;
+}
+
+
+/****************************** GLUI_Listbox::mouse_up_handler() **********/
+
+int GLUI_Listbox::mouse_up_handler( int local_x, int local_y, int inside )
+{
+
+ return false;
+}
+
+
+/****************************** GLUI_Listbox::mouse_held_down_handler() ******/
+
+int GLUI_Listbox::mouse_held_down_handler( int local_x, int local_y,
+ int inside)
+{
+
+ return false;
+}
+
+
+/****************************** GLUI_Listbox::key_handler() **********/
+
+int GLUI_Listbox::key_handler( unsigned char key,int modifiers )
+{
+ return false;
+}
+
+
+/****************************** GLUI_Listbox::draw() **********/
+
+void GLUI_Listbox::draw( int x, int y )
+{
+ int orig, name_x;
+
+ if ( NOT can_draw() )
+ return;
+
+ orig = set_to_glut_window();
+
+ /* draw_active_area(); */
+
+ name_x = MAX(text_x_offset - string_width(this->name) - 3,0);
+ draw_name( name_x , 13);
+ draw_box_inwards_outline( text_x_offset, w,
+ 0, h );
+
+
+ if ( NOT active ) {
+ draw_box( text_x_offset+3, w-2, 2, h-2, 1.0, 1.0, 1.0 );
+ if ( NOT enabled )
+ glColor3b( 32, 32, 32 );
+ else
+ glColor3f( 0.0, 0.0, 0.0 );
+ glRasterPos2i( text_x_offset+5, 13 );
+ draw_string( curr_text.string );
+ }
+ else {
+ draw_box( text_x_offset+3, w-2, 2, h-2, .0, .0, .6 );
+ glColor3f( 1.0, 1.0, 1.0 );
+ glRasterPos2i( text_x_offset+5, 13 );
+ draw_string( curr_text.string );
+ }
+
+
+ if ( enabled ) {
+ glui->std_bitmaps.
+ draw(GLUI_STDBITMAP_LISTBOX_UP,
+ w-glui->std_bitmaps.bitmaps[GLUI_STDBITMAP_LISTBOX_UP].w-1,
+ 2 );
+ }
+ else {
+ glui->std_bitmaps.
+ draw(GLUI_STDBITMAP_LISTBOX_UP_DIS,
+ w-glui->std_bitmaps.bitmaps[GLUI_STDBITMAP_LISTBOX_UP].w-1,
+ 2 );
+ }
+
+ restore_window(orig);
+}
+
+
+/************************************ GLUI_Listbox::update_si() **********/
+
+void GLUI_Listbox::update_size( void )
+{
+ int text_size, delta;
+ int item_text_size;
+
+ if ( NOT glui )
+ return;
+
+ text_size = string_width( name );
+
+ /*** Find the longest item string ***/
+ item_text_size = 0;
+ delta = 0;
+
+ if ( text_x_offset < text_size +2 )
+ delta = text_size+2-text_x_offset;
+
+ text_x_offset += delta;
+ if ( w < text_x_offset + MAX(GLUI_EDITTEXT_MIN_TEXT_WIDTH,item_text_size) + 20 )
+ w = text_x_offset + MAX( GLUI_EDITTEXT_MIN_TEXT_WIDTH,item_text_size)+20;
+}
+
+
+
+/********************************* GLUI_Listbox::set_int_val() **************/
+
+void GLUI_Listbox::set_int_val( int new_val )
+{
+ /* int_val = new_val; */
+
+ do_selection( new_val );
+
+ /*** Update the variable we're (possibly) pointing to, and update the main gfx
***/
+ output_live(true);
+}
+
+
+/**************************** GLUI_Listbox::draw_active_area() **************/
+
+void GLUI_Listbox::draw_active_area( void )
+{
+ int orig;
+
+ if ( NOT can_draw() )
+ return;
+
+ orig = set_to_glut_window();
+
+ restore_window(orig);
+}
+
+
+/**************************************** GLUI_Listbox::add_item() **********/
+
+int GLUI_Listbox::add_item( int id, char *new_text )
+{
+ GLUI_Listbox_Item *new_node = new GLUI_Listbox_Item;
+ GLUI_Listbox_Item *head;
+
+ strcpy( new_node->text, new_text );
+ new_node->id = id;
+
+ head = (GLUI_Listbox_Item*) items_list.first_child();
+ new_node->link_this_to_parent_last( &items_list );
+
+ if ( head == NULL ) {
+ /*** This is first item added ***/
+
+ int_val = id+1; /** Different than id **/
+ do_selection( id );
+ last_live_int = id;
+
+ if( glui )
+ glui->post_update_main_gfx();
+ }
+
+ /*** Check if we need to increase control size ***/
+ if ( w < text_x_offset + MAX( GLUI_EDITTEXT_MIN_TEXT_WIDTH, string_width( new_text )
) + 20 ) {
+ w = text_x_offset + MAX( GLUI_EDITTEXT_MIN_TEXT_WIDTH, string_width( new_text ) ) +
20;
+
+ if ( glui )
+ glui->refresh();
+
+ /* printf( "%s\n", new_text ); */
+ }
+
+
+ return true;
+}
+
+
+/************************************** GLUI_Listbox::delete_item() **********/
+
+int GLUI_Listbox::delete_item( char *text )
+{
+ GLUI_Listbox_Item *node = get_item_ptr( text );
+
+ if ( node ) {
+ node->unlink();
+ delete node;
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+
+/************************************** GLUI_Listbox::delete_item() **********/
+
+int GLUI_Listbox::delete_item( int id )
+{
+ GLUI_Listbox_Item *node = get_item_ptr( id );
+
+ if ( node ) {
+ node->unlink();
+ delete node;
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+
+/************************************** GLUI_Listbox::sort_items() **********/
+
+int GLUI_Listbox::sort_items( void )
+{
+ return false;
+}
+
+
+/********************************************* GLUI_Listbox::dump() **********/
+
+void GLUI_Listbox::dump( FILE *output )
+{
+ GLUI_Listbox_Item *item;
+
+ /* printf( "%p\n", (char*) name ); */
+
+ fprintf( output, "Listbox: %s\n", (char*) name );
+
+ item = (GLUI_Listbox_Item *) items_list.first_child();
+ while( item ) {
+ fprintf( output, " %3d : %s\n", item->id, (char*) item->text
);
+
+ item = (GLUI_Listbox_Item *) item->next();
+ }
+}
+
+
+/************************************ GLUI_Listbox::get_item_ptr() **********/
+
+GLUI_Listbox_Item *GLUI_Listbox::get_item_ptr( char *text )
+{
+ GLUI_Listbox_Item *item;
+
+ item = (GLUI_Listbox_Item *) items_list.first_child();
+ while( item ) {
+ if ( NOT strcmp( item->text, text ))
+ return item;
+
+ item = (GLUI_Listbox_Item *) item->next();
+ }
+
+ return NULL;
+}
+
+
+/************************************ GLUI_Listbox::get_item_ptr() **********/
+
+GLUI_Listbox_Item *GLUI_Listbox::get_item_ptr( int id )
+{
+ GLUI_Listbox_Item *item;
+
+ item = (GLUI_Listbox_Item *) items_list.first_child();
+ while( item ) {
+ if ( item->id == id )
+ return item;
+
+ item = (GLUI_Listbox_Item *) item->next();
+ }
+
+ return NULL;
+}
+
+
+/************************************ GLUI_Listbox::mouse_over() **********/
+
+static void listbox_callback( int i )
+{
+ int old_val;
+
+ if ( NOT GLUI_Master.curr_left_button_glut_menu OR
+ GLUI_Master.curr_left_button_glut_menu->type != GLUI_CONTROL_LISTBOX )
+ return;
+
+ old_val = ((GLUI_Listbox*)GLUI_Master.curr_left_button_glut_menu)->int_val;
+ ((GLUI_Listbox*)GLUI_Master.curr_left_button_glut_menu)->set_int_val(i);
+
+ /**** If value changed, execute callback ****/
+ if ( old_val !=
+ ((GLUI_Listbox*)GLUI_Master.curr_left_button_glut_menu)->int_val ) {
+ ((GLUI_Listbox*)GLUI_Master.curr_left_button_glut_menu)->execute_callback();
+ }
+}
+
+
+/*************************************** GLUI_Listbox::mouse_over() **********/
+
+int GLUI_Listbox::mouse_over( int state, int x, int y )
+{
+ GLUI_Listbox_Item *item;
+
+ /* printf( "x/y: %d/%d\n", x, y ); */
+
+ if ( state AND enabled AND x > x_abs + text_x_offset) {
+ /**** Build a GLUT menu for this listbox ***/
+
+ /* printf( "%d %d\n", x, y ); */
+
+ glut_menu_id = glutCreateMenu(listbox_callback);
+
+ item = (GLUI_Listbox_Item *) items_list.first_child();
+ while( item ) {
+ glutAddMenuEntry( item->text, item->id );
+ item = (GLUI_Listbox_Item *) item->next();
+ }
+
+ glutAttachMenu( GLUT_LEFT_BUTTON);
+
+ GLUI_Master.set_left_button_glut_menu_control( this );
+ }
+ else if ( glut_menu_id != -1 ) {
+ /* printf( "OUT\n" ); */
+ glutDetachMenu( GLUT_LEFT_BUTTON );
+ glutDestroyMenu( glut_menu_id );
+ glut_menu_id = -1;
+ }
+
+ return true;
+}
+
+
+/************************************ GLUI_Listbox::do_selection() **********/
+
+int GLUI_Listbox::do_selection( int item_num )
+{
+ GLUI_Listbox_Item *item, *sel_item;
+
+ /*** Is this item already selected? ***/
+ if ( item_num == int_val )
+ return false;
+
+ sel_item = NULL;
+ item = (GLUI_Listbox_Item *) items_list.first_child();
+ while( item ) {
+ if ( item->id == item_num ) {
+ sel_item = item;
+ break;
+ }
+
+ item = (GLUI_Listbox_Item *) item->next();
+ }
+
+ if ( NOT sel_item )
+ return false;
+
+ /* printf( "-> %s\n", (char*) sel_item->text ); */
+
+ int_val = item_num;
+ strcpy( curr_text.string, sel_item->text.string );
+
+ translate_and_draw_front();
+
+ return true;
+}
+
+
+/*********************************** GLUI_Listbox::~GLUI_Listbox() **********/
+
+GLUI_Listbox::~GLUI_Listbox( )
+{
+ GLUI_Listbox_Item* item = (GLUI_Listbox_Item*) items_list.first_child();
+ while( item ) {
+ GLUI_Listbox_Item* prev = item;
+
+ item = (GLUI_Listbox_Item *) prev->next();
+
+ delete prev;
+ }
+}
+
+
+/****************************** GLUI_Listbox::special_handler() **********/
+
+int GLUI_Listbox::special_handler( int key,int modifiers )
+{
+ GLUI_Listbox_Item *node, *new_node;
+
+ node = get_item_ptr( int_val );
+ new_node = NULL;
+
+ if ( key == GLUT_KEY_DOWN ) {
+ new_node = (GLUI_Listbox_Item*) node->next();
+ }
+ else if ( key == GLUT_KEY_UP ) {
+ new_node = (GLUI_Listbox_Item*) node->prev();
+ }
+ else if ( key == GLUT_KEY_HOME ) {
+ new_node = (GLUI_Listbox_Item*) items_list.first_child();
+ }
+ else if ( key == GLUT_KEY_END ) {
+ new_node = (GLUI_Listbox_Item*) items_list.last_child();
+ }
+
+ if ( new_node != NULL AND new_node != node ) {
+ node = new_node;
+ set_int_val( node->id );
+ execute_callback();
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+
+/************************* GLUI_Listbox::increase_width( void ) ***********/
+
+void GLUI_Listbox::increase_width( void )
+{
+}
Index: external/trimesh/gluit/glui_node.cc
--- external/trimesh/gluit/glui_node.cc (revision 0)
+++ external/trimesh/gluit/glui_node.cc (revision 0)
@@ -0,0 +1,175 @@
+/****************************************************************************
+
+ GLUI User Interface Toolkit
+ ---------------------------
+
+ glui_node.cpp - linked-list tree structure
+
+
+ --------------------------------------------------
+
+ Copyright (c) 1998 Paul Rademacher
+
+ This program is freely distributable without licensing fees and is
+ provided without guarantee or warrantee expressed or implied. This
+ program is -not- in the public domain.
+
+*****************************************************************************/
+
+
+#include "glui.h"
+#include "glui_stdinc.h"
+
+/********************************************* GLUI_Node::first() *******/
+/* Returns first sibling in 'this' node's sibling list */
+
+GLUI_Node *GLUI_Node::first_sibling( void )
+{
+ if ( parent_node == NULL )
+ return this; /* root node has no siblings */
+ else
+ return parent_node->child_head;
+}
+
+
+/******************************************** GLUI_Node::next() ********/
+/* Returns next sibling in 'this' node's sibling list */
+
+GLUI_Node *GLUI_Node::next( void )
+{
+ return next_sibling;
+}
+
+
+/******************************************** GLUI_Node::prev() ********/
+/* Returns prev sibling in 'this' node's sibling list */
+
+GLUI_Node *GLUI_Node::prev( void )
+{
+ return prev_sibling;
+}
+
+
+/********************************************* GLUI_Node::last() *******/
+/* Returns last sibling in 'this' node's sibling list */
+
+GLUI_Node *GLUI_Node::last_sibling( void )
+{
+ if ( parent_node == NULL )
+ return this; /* root node has no siblings */
+ else
+ return parent_node->child_tail;
+}
+
+
+/*************************** GLUI_Node::link_this_to_parent_last() *******/
+/* Links as last child of parent */
+
+void GLUI_Node::link_this_to_parent_last( GLUI_Node *new_parent )
+{
+ if ( new_parent->child_tail == NULL ) { /* parent has no children */
+ new_parent->child_head = this;
+ new_parent->child_tail = this;
+ this->parent_node = new_parent;
+ this->parent_node = new_parent;
+ }
+ else { /* parent has children */
+ new_parent->child_tail->next_sibling = this;
+ this->prev_sibling = new_parent->child_tail;
+ new_parent->child_tail = this;
+ this->parent_node = new_parent;
+ }
+}
+
+
+/*************************** GLUI_Node::link_this_to_parent_first() *******/
+/* Links as first child of parent */
+
+void GLUI_Node::link_this_to_parent_first( GLUI_Node *new_parent )
+{
+ if ( new_parent->child_head == NULL ) { /* parent has no children */
+ new_parent->child_head = this;
+ new_parent->child_tail = this;
+ this->parent_node = new_parent;
+ }
+ else { /* parent has children */
+ new_parent->child_head->prev_sibling = this;
+ this->next_sibling = new_parent->child_head;
+ new_parent->child_head = this;
+ this->parent_node = new_parent;
+ }
+}
+
+/**************************** GLUI_Node::link_this_to_sibling_next() *****/
+
+void GLUI_Node::link_this_to_sibling_next( GLUI_Node *sibling )
+{
+ if ( sibling->next_sibling == NULL ) { /* node has no next sibling */
+ sibling->next_sibling = this;
+ this->prev_sibling = sibling;
+
+ /* This was the parent's last child, so update that as well */
+ if ( sibling->parent_node != NULL ) {
+ sibling->parent_node->child_tail = this;
+ }
+ }
+ else { /* node already has a next sibling */
+ sibling->next_sibling->prev_sibling = this;
+ this->next_sibling = sibling->next_sibling;
+ sibling->next_sibling = this;
+ this->prev_sibling = sibling;
+ }
+
+ this->parent_node = sibling->parent_node;
+}
+
+
+/**************************** GLUI_Node::link_this_to_sibling_prev() *****/
+
+void GLUI_Node::link_this_to_sibling_prev( GLUI_Node *sibling )
+{
+ if ( sibling->prev_sibling == NULL ) { /* node has no prev sibling */
+ sibling->prev_sibling = this;
+ this->next_sibling = sibling;
+
+ /* This was the parent's first child, so update that as well */
+ if ( sibling->parent_node != NULL ) {
+ sibling->parent_node->child_head = this;
+ }
+ }
+ else { /* node already has a prev sibling */
+ sibling->prev_sibling->next_sibling = this;
+ this->prev_sibling = sibling->prev_sibling;
+ sibling->prev_sibling = this;
+ this->next_sibling = sibling;
+ }
+
+ this->parent_node = sibling->parent_node;
+}
+
+/**************************************** GLUI_Node::unlink() **************/
+
+void GLUI_Node::unlink( void )
+{
+ /* Unlink from prev sibling */
+ if ( this->prev_sibling != NULL ) {
+ this->prev_sibling->next_sibling = this->next_sibling;
+ }
+ else { /* No prev sibling: this was parent's first child */
+ this->parent_node->child_head = this->next_sibling;
+ }
+
+ /* Unlink from next sibling */
+ if ( this->next_sibling != NULL ) {
+ this->next_sibling->prev_sibling = this->prev_sibling;
+ }
+ else { /* No next sibling: this was parent's last child */
+ this->parent_node->child_tail = this->prev_sibling;
+ }
+
+ this->parent_node = NULL;
+ this->next_sibling = NULL;
+ this->prev_sibling = NULL;
+ this->child_head = NULL;
+ this->child_tail = NULL;
+}
Index: external/trimesh/gluit/glui_img_checkbox_0_dis.c
--- external/trimesh/gluit/glui_img_checkbox_0_dis.c (revision 0)
+++ external/trimesh/gluit/glui_img_checkbox_0_dis.c (revision 0)
@@ -0,0 +1,38 @@
+
+
+int glui_img_checkbox_0_dis[] = { 13, 13, /* width, height */
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 128,128,128, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 255,255,255, 128,128,128, 64, 64, 64, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 255,255,255, 128,128,128,
+ 64, 64, 64, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 255,255,255, 128,128,128, 64, 64, 64, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 255,255,255,
+ 128,128,128, 64, 64, 64, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 255,255,255, 128,128,128, 64, 64, 64,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 255,255,255, 128,128,128, 64, 64, 64, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 255,255,255, 128,128,128,
+ 64, 64, 64, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 255,255,255, 128,128,128, 64, 64, 64, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 255,255,255,
+ 128,128,128, 64, 64, 64, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 255,255,255, 128,128,128, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 192,192,192,
+ 255,255,255, 128,128,128, 128,128,128, 128,128,128, 128,128,128,
+ 128,128,128, 128,128,128, 128,128,128, 128,128,128, 128,128,128,
+ 128,128,128, 128,128,128, 128,128,128, 255,255,255,
+};
Index: external/trimesh/gluit/glui_img_leftarrow.c
--- external/trimesh/gluit/glui_img_leftarrow.c (revision 0)
+++ external/trimesh/gluit/glui_img_leftarrow.c (revision 0)
@@ -0,0 +1,56 @@
+
+
+int glui_img_leftarrow[] = { 16, 16, /* width, height */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 192,192,192, 128,128,128, 128,128,128, 128,128,128,
+ 128,128,128, 128,128,128, 128,128,128, 128,128,128, 128,128,128,
+ 128,128,128, 128,128,128, 128,128,128, 128,128,128, 128,128,128,
+ 128,128,128, 0, 0, 0, 192,192,192, 255,255,255, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 128,128,128, 0, 0, 0, 192,192,192, 255,255,255,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 128,128,128, 0, 0, 0, 192,192,192,
+ 255,255,255, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 128,128,128, 0, 0, 0,
+ 192,192,192, 255,255,255, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 0, 0, 0, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 128,128,128,
+ 0, 0, 0, 192,192,192, 255,255,255, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 0, 0, 0, 0, 0, 0,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 128,128,128, 0, 0, 0, 192,192,192, 255,255,255, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 128,128,128, 0, 0, 0, 192,192,192, 255,255,255,
+ 192,192,192, 192,192,192, 192,192,192, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 128,128,128, 0, 0, 0, 192,192,192,
+ 255,255,255, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 128,128,128, 0, 0, 0,
+ 192,192,192, 255,255,255, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 0, 0, 0, 0, 0, 0, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 128,128,128,
+ 0, 0, 0, 192,192,192, 255,255,255, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 0, 0, 0,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 128,128,128, 0, 0, 0, 192,192,192, 255,255,255, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 128,128,128, 0, 0, 0, 192,192,192, 255,255,255,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 128,128,128, 0, 0, 0, 192,192,192,
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 128,128,128, 0, 0, 0,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 0, 0, 0,
+};
Index: external/trimesh/gluit/glui_mouse_iaction.cc
--- external/trimesh/gluit/glui_mouse_iaction.cc (revision 0)
+++ external/trimesh/gluit/glui_mouse_iaction.cc (revision 0)
@@ -0,0 +1,212 @@
+/****************************************************************************
+
+ GLUI User Interface Toolkit
+ ---------------------------
+
+ glui_mouse_iaction - GLUI Mouse Interaction control class
+
+
+ --------------------------------------------------
+
+ Copyright (c) 1998 Paul Rademacher
+
+ This program is freely distributable without licensing fees and is
+ provided without guarantee or warrantee expressed or implied. This
+ program is -not- in the public domain.
+
+*****************************************************************************/
+
+#include "glui.h"
+#include "glui_stdinc.h"
+
+/********************** GLUI_Mouse_Interaction::mouse_down_handler() ******/
+
+int GLUI_Mouse_Interaction::mouse_down_handler( int local_x, int local_y )
+{
+ /* int win_h = glutGet( GLUT_WINDOW_HEIGHT ); */
+
+ /* iaction_mouse_down_handler( local_x, local_y ); */
+ iaction_mouse_down_handler( local_x-x_abs, local_y-y_abs );
+ /*local_x-x_abs, ((glui->h-local_y)-y_abs) ); */
+
+ return false;
+}
+
+
+/**************************** GLUI_Mouse_Interaction::mouse_up_handler() */
+
+int GLUI_Mouse_Interaction::mouse_up_handler( int local_x, int local_y, int inside )
+{
+ iaction_mouse_up_handler( local_x-x_abs, local_y-y_abs, inside );
+ return false;
+}
+
+
+/****************************** GLUI_Mouse_Interaction::mouse_held_down_handler()
******/
+
+int GLUI_Mouse_Interaction::mouse_held_down_handler( int local_x, int local_y,
+ int inside)
+{
+ iaction_mouse_held_down_handler( local_x-x_abs, local_y-y_abs , inside );
+
+ draw_active_area();
+
+ /** Tell the main graphics window to update iteself **/
+ if( glui )
+ glui->post_update_main_gfx();
+
+ execute_callback();
+
+ return false;
+}
+
+
+
+/****************************** GLUI_Mouse_Interaction::draw() **********/
+
+void GLUI_Mouse_Interaction::draw( int x, int y )
+{
+ int orig;
+ int text_width = string_width( this->name );
+ int x_left = this->w/2 - text_width/2;
+
+ if ( NOT glui )
+ return;
+
+ if ( NOT draw_active_area_only ) {
+ orig = set_to_glut_window();
+ draw_name( x_left, h-4 );
+ restore_window(orig);
+
+ draw_active_box( x_left-4, x_left+string_width( name.string )+4,
+ h, h-14 );
+ }
+
+ draw_active_area();
+}
+
+
+/************************************ GLUI_Mouse_Interaction::update_size() **********/
+
+void GLUI_Mouse_Interaction::update_size( void )
+{
+ if ( NOT glui )
+ return;
+
+ int text_width = string_width( this->name );
+
+ if ( w < text_width+6 )
+ w = text_width+6;
+
+ if ( h - 18 > w )
+ w = h - 18;
+
+ iaction_init();
+}
+
+
+/****************************** GLUI_Mouse_Interaction::special_handler() **********/
+
+int GLUI_Mouse_Interaction::special_handler( int key,int modifiers )
+{
+ int center_x, center_y;
+ int drag_x, drag_y;
+
+ center_x = x_abs + w/2;
+ center_y = y_abs + (h-18)/2;
+ drag_x = 0;
+ drag_y = 0;
+
+
+ if ( key == GLUT_KEY_LEFT )
+ drag_x = -6;
+ else if ( key == GLUT_KEY_RIGHT )
+ drag_x = 6;
+ else if ( key == GLUT_KEY_UP )
+ drag_y = -6;
+ else if ( key == GLUT_KEY_DOWN )
+ drag_y = 6;
+
+ if ( drag_x != 0 OR drag_y != 0 ) {
+ mouse_down_handler( center_x, center_y );
+ mouse_held_down_handler( center_x + drag_x, center_y + drag_y,true );
+ mouse_up_handler( center_x + drag_x, center_y + drag_y, true );
+ }
+
+ return false;
+}
+
+
+/****************************** GLUI_Mouse_Interaction::draw_active_area() **********/
+
+void GLUI_Mouse_Interaction::draw_active_area( void )
+{
+ int orig;
+ int win_h = glutGet( GLUT_WINDOW_HEIGHT ), win_w = glutGet(GLUT_WINDOW_WIDTH);
+
+ if ( NOT glui )
+ return;
+
+ /*putchar( 'X' ); flushout; */
+
+ orig = set_to_glut_window();
+
+ int text_height = 18; /* what a kludge */
+
+ int viewport_size = h-text_height; /*MIN(w,h); */
+
+ glMatrixMode( GL_MODELVIEW );
+ glPushMatrix();
+ glLoadIdentity();
+ glTranslatef( (float) win_w/2.0, (float) win_h/2.0, 0.0 );
+ glRotatef( 180.0, 0.0, 1.0, 0.0 );
+ glRotatef( 180.0, 0.0, 0.0, 1.0 );
+ glTranslatef( (float) -win_w/2.0, (float) -win_h/2.0, 0.0 );
+
+ glTranslatef( (float) this->x_abs + .5, (float) this->y_abs + .5, 0.0 );
+
+ glTranslatef( (float)this->w/2.0, (float)viewport_size/2.0 + 2.0 , 0.0 );
+
+ /*** Draw the interaction control's orthographic elements ***/
+ iaction_draw_active_area_ortho();
+
+ /*** Setup and draw the interaction control's perspective elements ***/
+
+ /*** Set the viewport to just the square of the drawing area ***/
+ /* glViewport( this->x_abs , glui->main_panel->h - this->y_abs -
this->h,*/
+ /*glViewport( this->x_abs+1+(this->w/2-viewport_size/2),
+ this->h-this->y_abs-viewport_size-1,
+ viewport_size, viewport_size );*/
+
+ viewport_size -= 4;
+ int offset = 0;
+ if ( ((this->w-viewport_size) % 2) == 1 )
+ offset = 1;
+
+ glViewport( this->x_abs + (this->w-viewport_size)/2 + offset,
+ win_h - this->y_abs - this->h + text_height,
+ viewport_size, viewport_size );
+
+ glMatrixMode( GL_PROJECTION );
+ glLoadIdentity();
+ glFrustum( -1.0*.08, 1.0*.08, -.08, .08, .1, 8.0 );
+ glMatrixMode( GL_MODELVIEW );
+ glPushMatrix();
+ glLoadIdentity();
+ glTranslatef( 0.0, 0.0, -3.2f );
+
+ /* glutSolidTeapot( 1.0 ); */
+ iaction_draw_active_area_persp();
+
+ glMatrixMode( GL_MODELVIEW );
+ glPopMatrix();
+
+ glui->set_viewport();
+ glui->set_ortho_projection();
+
+ glMatrixMode( GL_MODELVIEW );
+ glPopMatrix();
+
+ restore_window(orig);
+}
+
Index: external/trimesh/gluit/glui_separator.cc
--- external/trimesh/gluit/glui_separator.cc (revision 0)
+++ external/trimesh/gluit/glui_separator.cc (revision 0)
@@ -0,0 +1,60 @@
+/****************************************************************************
+
+ GLUI User Interface Toolkit
+ ---------------------------
+
+ glui_separator.cpp - GLUI_Separator control class
+
+
+ --------------------------------------------------
+
+ Copyright (c) 1998 Paul Rademacher
+
+ This program is freely distributable without licensing fees and is
+ provided without guarantee or warrantee expressed or implied. This
+ program is -not- in the public domain.
+
+*****************************************************************************/
+
+#include "glui.h"
+#include "glui_stdinc.h"
+
+/****************************** GLUI_Separator::draw() **********/
+
+void GLUI_Separator::draw( int x, int y )
+{
+ int width, indent, orig;
+ int cont_x, cont_y, cont_w, cont_h, cont_x_off, cont_y_off;
+
+ if ( NOT can_draw() )
+ return;
+
+ orig = set_to_glut_window();
+
+ if ( parent() != NULL ) {
+ get_this_column_dims(&cont_x, &cont_y, &cont_w, &cont_h,
+ &cont_x_off, &cont_y_off);
+
+ width = cont_w - cont_x_off*2;
+ }
+ else {
+ width = this->w;
+ }
+
+ indent = (int) floor(width * .05);
+
+ glLineWidth( 1.0 );
+ glBegin( GL_LINES );
+ glColor3f( .5, .5, .5 );
+ glVertex2i( indent, GLUI_SEPARATOR_HEIGHT/2-1 );
+ glVertex2i( width-indent, GLUI_SEPARATOR_HEIGHT/2-1 );
+
+ glColor3f( 1., 1., 1. );
+ glVertex2i( indent, GLUI_SEPARATOR_HEIGHT/2 );
+ glVertex2i( width-indent, GLUI_SEPARATOR_HEIGHT/2 );
+ glEnd();
+
+ restore_window(orig);
+}
+
+
Index: external/trimesh/gluit/glui_img_radiobutton_0_dis.c
--- external/trimesh/gluit/glui_img_radiobutton_0_dis.c (revision 0)
+++ external/trimesh/gluit/glui_img_radiobutton_0_dis.c (revision 0)
@@ -0,0 +1,44 @@
+
+
+int glui_img_radiobutton_0_dis[] = { 14, 14, /* width, height */
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 255,255,255, 255,255,255, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 255,255,255, 255,255,255, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 128,128,128,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 255,255,255, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 128,128,128, 64, 64, 64,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 255,255,255, 192,192,192, 192,192,192,
+ 192,192,192, 128,128,128, 64, 64, 64, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 255,255,255, 192,192,192, 192,192,192,
+ 128,128,128, 64, 64, 64, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 255,255,255, 192,192,192, 192,192,192, 128,128,128,
+ 64, 64, 64, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 255,255,255, 192,192,192, 192,192,192, 128,128,128, 64, 64, 64,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 255,255,255,
+ 192,192,192, 192,192,192, 192,192,192, 128,128,128, 64, 64, 64,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 255,255,255, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 128,128,128, 64, 64, 64, 64, 64, 64,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 64, 64, 64,
+ 64, 64, 64, 255,255,255, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 128,128,128, 128,128,128, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 128,128,128, 128,128,128,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 128,128,128, 128,128,128,
+ 128,128,128, 128,128,128, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192,
+};
Index: external/trimesh/gluit/glui_img_listbox_down.c
--- external/trimesh/gluit/glui_img_listbox_down.c (revision 0)
+++ external/trimesh/gluit/glui_img_listbox_down.c (revision 0)
@@ -0,0 +1,42 @@
+
+
+int glui_img_listbox_down[] = { 11, 17, /* width, height */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 127,127,127, 127,127,127, 127,127,127, 127,127,127,
+ 127,127,127, 127,127,127, 127,127,127, 127,127,127, 127,127,127,
+ 127,127,127, 0, 0, 0, 127,127,127, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 127,127,127, 0, 0, 0, 127,127,127, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 127,127,127, 0, 0, 0, 127,127,127,
+ 191,191,191, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 127,127,127, 0, 0, 0,
+ 127,127,127, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 191,191,191, 127,127,127,
+ 0, 0, 0, 127,127,127, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 127,127,127, 0, 0, 0, 127,127,127, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 127,127,127, 191,191,191, 191,191,191,
+ 191,191,191, 127,127,127, 0, 0, 0, 127,127,127, 191,191,191,
+ 191,191,191, 191,191,191, 127,127,127, 127,127,127, 127,127,127,
+ 191,191,191, 191,191,191, 127,127,127, 0, 0, 0, 127,127,127,
+ 191,191,191, 191,191,191, 127,127,127, 127,127,127, 127,127,127,
+ 127,127,127, 127,127,127, 191,191,191, 127,127,127, 0, 0, 0,
+ 127,127,127, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 191,191,191, 127,127,127,
+ 0, 0, 0, 127,127,127, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 127,127,127, 0, 0, 0, 127,127,127, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 127,127,127, 0, 0, 0, 127,127,127, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 127,127,127, 0, 0, 0, 127,127,127,
+ 191,191,191, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 127,127,127, 0, 0, 0,
+ 127,127,127, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 191,191,191, 127,127,127,
+ 0, 0, 0, 127,127,127, 127,127,127, 127,127,127, 127,127,127,
+ 127,127,127, 127,127,127, 127,127,127, 127,127,127, 127,127,127,
+ 127,127,127, 0, 0, 0,
+};
Index: external/trimesh/gluit/freeglut_teapot_data.h
--- external/trimesh/gluit/freeglut_teapot_data.h (revision 0)
+++ external/trimesh/gluit/freeglut_teapot_data.h (revision 0)
@@ -0,0 +1,2428 @@
+/*
+ * freeglut_teapot_data.h
+ *
+ * The freeglut library teapot data include file.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef FREEGLUT_TEAPOT_DATA_H
+#define FREEGLUT_TEAPOT_DATA_H
+
+#if TARGET_HOST_WINCE
+/*
+ * Submitted through the kind offices of Daniel Wagner (daniel(a)ims.tuwien.ac.at)
+ */
+
+/* 530 vertices */
+
+const int numVertices = 530;
+const float vertices[530][3] = {
+2.1f, 3.6f, 0.0f,
+2.071f, 3.711f, 0.0f,
+2.105f, 3.748f, 0.0f,
+2.174f, 3.711f, 0.0f,
+2.25f, 3.6f, 0.0f,
+1.937f, 3.6f, 0.8242f,
+1.91f, 3.711f, 0.8128f,
+1.942f, 3.748f, 0.8261f,
+2.005f, 3.711f, 0.8532f,
+2.076f, 3.6f, 0.8831f,
+1.491f, 3.6f, 1.491f,
+1.47f, 3.711f, 1.47f,
+1.494f, 3.748f, 1.494f,
+1.543f, 3.711f, 1.543f,
+1.597f, 3.6f, 1.597f,
+0.8242f, 3.6f, 1.937f,
+0.8128f, 3.711f, 1.91f,
+0.8261f, 3.748f, 1.942f,
+0.8532f, 3.711f, 2.005f,
+0.8831f, 3.6f, 2.076f,
+0.0f, 3.6f, 2.1f,
+0.0f, 3.711f, 2.071f,
+0.0f, 3.748f, 2.105f,
+0.0f, 3.711f, 2.174f,
+0.0f, 3.6f, 2.25f,
+-0.8812f, 3.6f, 1.937f,
+-0.8368f, 3.711f, 1.91f,
+-0.8332f, 3.748f, 1.942f,
+-0.8541f, 3.711f, 2.005f,
+-0.8831f, 3.6f, 2.076f,
+-1.542f, 3.6f, 1.491f,
+-1.492f, 3.711f, 1.47f,
+-1.501f, 3.748f, 1.494f,
+-1.544f, 3.711f, 1.543f,
+-1.597f, 3.6f, 1.597f,
+-1.956f, 3.6f, 0.8242f,
+-1.918f, 3.711f, 0.8128f,
+-1.944f, 3.748f, 0.8261f,
+-2.006f, 3.711f, 0.8532f,
+-2.076f, 3.6f, 0.8831f,
+-2.1f, 3.6f, 0.0f,
+-2.071f, 3.711f, 0.0f,
+-2.105f, 3.748f, 0.0f,
+-2.174f, 3.711f, 0.0f,
+-2.25f, 3.6f, 0.0f,
+-1.937f, 3.6f, -0.8242f,
+-1.91f, 3.711f, -0.8128f,
+-1.942f, 3.748f, -0.8261f,
+-2.005f, 3.711f, -0.8532f,
+-2.076f, 3.6f, -0.8831f,
+-1.491f, 3.6f, -1.491f,
+-1.47f, 3.711f, -1.47f,
+-1.494f, 3.748f, -1.494f,
+-1.543f, 3.711f, -1.543f,
+-1.597f, 3.6f, -1.597f,
+-0.8242f, 3.6f, -1.937f,
+-0.8128f, 3.711f, -1.91f,
+-0.8261f, 3.748f, -1.942f,
+-0.8532f, 3.711f, -2.005f,
+-0.8831f, 3.6f, -2.076f,
+0.0f, 3.6f, -2.1f,
+0.0f, 3.711f, -2.071f,
+0.0f, 3.748f, -2.105f,
+0.0f, 3.711f, -2.174f,
+0.0f, 3.6f, -2.25f,
+0.8242f, 3.6f, -1.937f,
+0.8128f, 3.711f, -1.91f,
+0.8261f, 3.748f, -1.942f,
+0.8532f, 3.711f, -2.005f,
+0.8831f, 3.6f, -2.076f,
+1.491f, 3.6f, -1.491f,
+1.47f, 3.711f, -1.47f,
+1.494f, 3.748f, -1.494f,
+1.543f, 3.711f, -1.543f,
+1.597f, 3.6f, -1.597f,
+1.937f, 3.6f, -0.8242f,
+1.91f, 3.711f, -0.8128f,
+1.942f, 3.748f, -0.8261f,
+2.005f, 3.711f, -0.8532f,
+2.076f, 3.6f, -0.8831f,
+2.525f, 3.011f, 0.0f,
+2.766f, 2.433f, 0.0f,
+2.936f, 1.876f, 0.0f,
+3.0f, 1.35f, 0.0f,
+2.33f, 3.011f, 0.9912f,
+2.551f, 2.433f, 1.086f,
+2.708f, 1.876f, 1.152f,
+2.767f, 1.35f, 1.178f,
+1.793f, 3.011f, 1.793f,
+1.964f, 2.433f, 1.964f,
+2.084f, 1.876f, 2.084f,
+2.13f, 1.35f, 2.13f,
+0.9912f, 3.011f, 2.33f,
+1.086f, 2.433f, 2.551f,
+1.152f, 1.876f, 2.708f,
+1.178f, 1.35f, 2.767f,
+0.0f, 3.011f, 2.525f,
+0.0f, 2.433f, 2.766f,
+0.0f, 1.876f, 2.936f,
+0.0f, 1.35f, 3.0f,
+-0.9912f, 3.011f, 2.33f,
+-1.086f, 2.433f, 2.551f,
+-1.152f, 1.876f, 2.708f,
+-1.178f, 1.35f, 2.767f,
+-1.793f, 3.011f, 1.793f,
+-1.964f, 2.433f, 1.964f,
+-2.084f, 1.876f, 2.084f,
+-2.13f, 1.35f, 2.13f,
+-2.33f, 3.011f, 0.9912f,
+-2.551f, 2.433f, 1.086f,
+-2.708f, 1.876f, 1.152f,
+-2.767f, 1.35f, 1.178f,
+-2.525f, 3.011f, 0.0f,
+-2.766f, 2.433f, 0.0f,
+-2.936f, 1.876f, 0.0f,
+-3.0f, 1.35f, 0.0f,
+-2.33f, 3.011f, -0.9912f,
+-2.551f, 2.433f, -1.086f,
+-2.708f, 1.876f, -1.152f,
+-2.767f, 1.35f, -1.178f,
+-1.793f, 3.011f, -1.793f,
+-1.964f, 2.433f, -1.964f,
+-2.084f, 1.876f, -2.084f,
+-2.13f, 1.35f, -2.13f,
+-0.9912f, 3.011f, -2.33f,
+-1.086f, 2.433f, -2.551f,
+-1.152f, 1.876f, -2.708f,
+-1.178f, 1.35f, -2.767f,
+0.0f, 3.011f, -2.525f,
+0.0f, 2.433f, -2.766f,
+0.0f, 1.876f, -2.936f,
+0.0f, 1.35f, -3.0f,
+0.9912f, 3.011f, -2.33f,
+1.086f, 2.433f, -2.551f,
+1.152f, 1.876f, -2.708f,
+1.178f, 1.35f, -2.767f,
+1.793f, 3.011f, -1.793f,
+1.964f, 2.433f, -1.964f,
+2.084f, 1.876f, -2.084f,
+2.13f, 1.35f, -2.13f,
+2.33f, 3.011f, -0.9912f,
+2.551f, 2.433f, -1.086f,
+2.708f, 1.876f, -1.152f,
+2.767f, 1.35f, -1.178f,
+2.883f, 0.9053f, 0.0f,
+2.625f, 0.5766f, 0.0f,
+2.367f, 0.3533f, 0.0f,
+2.25f, 0.225f, 0.0f,
+2.659f, 0.9053f, 1.132f,
+2.422f, 0.5766f, 1.03f,
+2.184f, 0.3533f, 0.9291f,
+2.076f, 0.225f, 0.8831f,
+2.047f, 0.9053f, 2.047f,
+1.864f, 0.5766f, 1.864f,
+1.681f, 0.3533f, 1.681f,
+1.597f, 0.225f, 1.597f,
+1.132f, 0.9053f, 2.659f,
+1.03f, 0.5766f, 2.422f,
+0.9291f, 0.3533f, 2.184f,
+0.8831f, 0.225f, 2.076f,
+0.0f, 0.9053f, 2.883f,
+0.0f, 0.5766f, 2.625f,
+0.0f, 0.3533f, 2.367f,
+0.0f, 0.225f, 2.25f,
+-1.132f, 0.9053f, 2.659f,
+-1.03f, 0.5766f, 2.422f,
+-0.9291f, 0.3533f, 2.184f,
+-0.8831f, 0.225f, 2.076f,
+-2.047f, 0.9053f, 2.047f,
+-1.864f, 0.5766f, 1.864f,
+-1.681f, 0.3533f, 1.681f,
+-1.597f, 0.225f, 1.597f,
+-2.659f, 0.9053f, 1.132f,
+-2.422f, 0.5766f, 1.03f,
+-2.184f, 0.3533f, 0.9291f,
+-2.076f, 0.225f, 0.8831f,
+-2.883f, 0.9053f, 0.0f,
+-2.625f, 0.5766f, 0.0f,
+-2.367f, 0.3533f, 0.0f,
+-2.25f, 0.225f, 0.0f,
+-2.659f, 0.9053f, -1.132f,
+-2.422f, 0.5766f, -1.03f,
+-2.184f, 0.3533f, -0.9291f,
+-2.076f, 0.225f, -0.8831f,
+-2.047f, 0.9053f, -2.047f,
+-1.864f, 0.5766f, -1.864f,
+-1.681f, 0.3533f, -1.681f,
+-1.597f, 0.225f, -1.597f,
+-1.132f, 0.9053f, -2.659f,
+-1.03f, 0.5766f, -2.422f,
+-0.9291f, 0.3533f, -2.184f,
+-0.8831f, 0.225f, -2.076f,
+0.0f, 0.9053f, -2.883f,
+0.0f, 0.5766f, -2.625f,
+0.0f, 0.3533f, -2.367f,
+0.0f, 0.225f, -2.25f,
+1.132f, 0.9053f, -2.659f,
+1.03f, 0.5766f, -2.422f,
+0.9291f, 0.3533f, -2.184f,
+0.8831f, 0.225f, -2.076f,
+2.047f, 0.9053f, -2.047f,
+1.864f, 0.5766f, -1.864f,
+1.681f, 0.3533f, -1.681f,
+1.597f, 0.225f, -1.597f,
+2.659f, 0.9053f, -1.132f,
+2.422f, 0.5766f, -1.03f,
+2.184f, 0.3533f, -0.9291f,
+2.076f, 0.225f, -0.8831f,
+2.199f, 0.1424f, 0.0f,
+1.927f, 0.07031f, 0.0f,
+1.253f, 0.01934f, 0.0f,
+0.0f, 0.0f, 0.0f,
+2.029f, 0.1424f, 0.8631f,
+1.777f, 0.07031f, 0.7562f,
+1.156f, 0.01934f, 0.4919f,
+1.561f, 0.1424f, 1.561f,
+1.368f, 0.07031f, 1.368f,
+0.8899f, 0.01934f, 0.8899f,
+0.8631f, 0.1424f, 2.029f,
+0.7562f, 0.07031f, 1.777f,
+0.4919f, 0.01934f, 1.156f,
+0.0f, 0.1424f, 2.199f,
+0.0f, 0.07031f, 1.927f,
+0.0f, 0.01934f, 1.253f,
+-0.8631f, 0.1424f, 2.029f,
+-0.7562f, 0.07031f, 1.777f,
+-0.4919f, 0.01934f, 1.156f,
+-1.561f, 0.1424f, 1.561f,
+-1.368f, 0.07031f, 1.368f,
+-0.8899f, 0.01934f, 0.8899f,
+-2.029f, 0.1424f, 0.8631f,
+-1.777f, 0.07031f, 0.7562f,
+-1.156f, 0.01934f, 0.4919f,
+-2.199f, 0.1424f, 0.0f,
+-1.927f, 0.07031f, 0.0f,
+-1.253f, 0.01934f, 0.0f,
+-2.029f, 0.1424f, -0.8631f,
+-1.777f, 0.07031f, -0.7562f,
+-1.156f, 0.01934f, -0.4919f,
+-1.561f, 0.1424f, -1.561f,
+-1.368f, 0.07031f, -1.368f,
+-0.8899f, 0.01934f, -0.8899f,
+-0.8631f, 0.1424f, -2.029f,
+-0.7562f, 0.07031f, -1.777f,
+-0.4919f, 0.01934f, -1.156f,
+0.0f, 0.1424f, -2.199f,
+0.0f, 0.07031f, -1.927f,
+0.0f, 0.01934f, -1.253f,
+0.8631f, 0.1424f, -2.029f,
+0.7562f, 0.07031f, -1.777f,
+0.4919f, 0.01934f, -1.156f,
+1.561f, 0.1424f, -1.561f,
+1.368f, 0.07031f, -1.368f,
+0.8899f, 0.01934f, -0.8899f,
+2.029f, 0.1424f, -0.8631f,
+1.777f, 0.07031f, -0.7562f,
+1.156f, 0.01934f, -0.4919f,
+-2.4f, 3.038f, 0.0f,
+-3.101f, 3.032f, 0.0f,
+-3.619f, 2.995f, 0.0f,
+-3.94f, 2.895f, 0.0f,
+-4.05f, 2.7f, 0.0f,
+-2.377f, 3.09f, 0.2531f,
+-3.122f, 3.084f, 0.2531f,
+-3.669f, 3.041f, 0.2531f,
+-4.005f, 2.926f, 0.2531f,
+-4.12f, 2.7f, 0.2531f,
+-2.325f, 3.206f, 0.3375f,
+-3.168f, 3.198f, 0.3375f,
+-3.778f, 3.143f, 0.3375f,
+-4.15f, 2.993f, 0.3375f,
+-4.275f, 2.7f, 0.3375f,
+-2.273f, 3.322f, 0.2531f,
+-3.214f, 3.313f, 0.2531f,
+-3.888f, 3.244f, 0.2531f,
+-4.294f, 3.06f, 0.2531f,
+-4.43f, 2.7f, 0.2531f,
+-2.25f, 3.375f, 0.0f,
+-3.234f, 3.364f, 0.0f,
+-3.938f, 3.291f, 0.0f,
+-4.359f, 3.09f, 0.0f,
+-4.5f, 2.7f, 0.0f,
+-2.273f, 3.322f, -0.2531f,
+-3.214f, 3.313f, -0.2531f,
+-3.888f, 3.244f, -0.2531f,
+-4.294f, 3.06f, -0.2531f,
+-4.43f, 2.7f, -0.2531f,
+-2.325f, 3.206f, -0.3375f,
+-3.168f, 3.198f, -0.3375f,
+-3.778f, 3.143f, -0.3375f,
+-4.15f, 2.993f, -0.3375f,
+-4.275f, 2.7f, -0.3375f,
+-2.377f, 3.09f, -0.2531f,
+-3.122f, 3.084f, -0.2531f,
+-3.669f, 3.041f, -0.2531f,
+-4.005f, 2.926f, -0.2531f,
+-4.12f, 2.7f, -0.2531f,
+-3.991f, 2.394f, 0.0f,
+-3.806f, 2.025f, 0.0f,
+-3.48f, 1.656f, 0.0f,
+-3.0f, 1.35f, 0.0f,
+-4.055f, 2.365f, 0.2531f,
+-3.852f, 1.98f, 0.2531f,
+-3.496f, 1.6f, 0.2531f,
+-2.977f, 1.28f, 0.2531f,
+-4.196f, 2.3f, 0.3375f,
+-3.952f, 1.881f, 0.3375f,
+-3.531f, 1.478f, 0.3375f,
+-2.925f, 1.125f, 0.3375f,
+-4.336f, 2.235f, 0.2531f,
+-4.051f, 1.782f, 0.2531f,
+-3.566f, 1.356f, 0.2531f,
+-2.873f, 0.9703f, 0.2531f,
+-4.4f, 2.205f, 0.0f,
+-4.097f, 1.737f, 0.0f,
+-3.582f, 1.3f, 0.0f,
+-2.85f, 0.9f, 0.0f,
+-4.336f, 2.235f, -0.2531f,
+-4.051f, 1.782f, -0.2531f,
+-3.566f, 1.356f, -0.2531f,
+-2.873f, 0.9703f, -0.2531f,
+-4.196f, 2.3f, -0.3375f,
+-3.952f, 1.881f, -0.3375f,
+-3.531f, 1.478f, -0.3375f,
+-2.925f, 1.125f, -0.3375f,
+-4.055f, 2.365f, -0.2531f,
+-3.852f, 1.98f, -0.2531f,
+-3.496f, 1.6f, -0.2531f,
+-2.977f, 1.28f, -0.2531f,
+2.55f, 2.137f, 0.0f,
+3.27f, 2.303f, 0.0f,
+3.581f, 2.7f, 0.0f,
+3.752f, 3.182f, 0.0f,
+4.05f, 3.6f, 0.0f,
+2.55f, 1.944f, 0.5569f,
+3.324f, 2.159f, 0.5028f,
+3.652f, 2.617f, 0.3839f,
+3.838f, 3.151f, 0.265f,
+4.191f, 3.6f, 0.2109f,
+2.55f, 1.519f, 0.7425f,
+3.445f, 1.844f, 0.6704f,
+3.806f, 2.433f, 0.5119f,
+4.027f, 3.085f, 0.3533f,
+4.5f, 3.6f, 0.2813f,
+2.55f, 1.093f, 0.5569f,
+3.566f, 1.529f, 0.5028f,
+3.961f, 2.249f, 0.3839f,
+4.215f, 3.018f, 0.265f,
+4.809f, 3.6f, 0.2109f,
+2.55f, 0.9f, 0.0f,
+3.621f, 1.385f, 0.0f,
+4.031f, 2.166f, 0.0f,
+4.301f, 2.988f, 0.0f,
+4.95f, 3.6f, 0.0f,
+2.55f, 1.093f, -0.5569f,
+3.566f, 1.529f, -0.5028f,
+3.961f, 2.249f, -0.3839f,
+4.215f, 3.018f, -0.265f,
+4.809f, 3.6f, -0.2109f,
+2.55f, 1.519f, -0.7425f,
+3.445f, 1.844f, -0.6704f,
+3.806f, 2.433f, -0.5119f,
+4.027f, 3.085f, -0.3533f,
+4.5f, 3.6f, -0.2813f,
+2.55f, 1.944f, -0.5569f,
+3.324f, 2.159f, -0.5028f,
+3.652f, 2.617f, -0.3839f,
+3.838f, 3.151f, -0.265f,
+4.191f, 3.6f, -0.2109f,
+4.158f, 3.663f, 0.0f,
+4.238f, 3.684f, 0.0f,
+4.261f, 3.663f, 0.0f,
+4.2f, 3.6f, 0.0f,
+4.308f, 3.666f, 0.1978f,
+4.379f, 3.689f, 0.1687f,
+4.381f, 3.668f, 0.1397f,
+4.294f, 3.6f, 0.1266f,
+4.64f, 3.673f, 0.2637f,
+4.69f, 3.7f, 0.225f,
+4.645f, 3.677f, 0.1863f,
+4.5f, 3.6f, 0.1688f,
+4.971f, 3.68f, 0.1978f,
+5.001f, 3.711f, 0.1687f,
+4.909f, 3.687f, 0.1397f,
+4.706f, 3.6f, 0.1266f,
+5.122f, 3.683f, 0.0f,
+5.142f, 3.716f, 0.0f,
+5.029f, 3.691f, 0.0f,
+4.8f, 3.6f, 0.0f,
+4.971f, 3.68f, -0.1978f,
+5.001f, 3.711f, -0.1687f,
+4.909f, 3.687f, -0.1397f,
+4.706f, 3.6f, -0.1266f,
+4.64f, 3.673f, -0.2637f,
+4.69f, 3.7f, -0.225f,
+4.645f, 3.677f, -0.1863f,
+4.5f, 3.6f, -0.1688f,
+4.308f, 3.666f, -0.1978f,
+4.379f, 3.689f, -0.1687f,
+4.381f, 3.668f, -0.1397f,
+4.294f, 3.6f, -0.1266f,
+0.0f, 4.725f, 0.0f,
+0.5109f, 4.651f, 0.0f,
+0.4875f, 4.472f, 0.0f,
+0.2953f, 4.25f, 0.0f,
+0.3f, 4.05f, 0.0f,
+0.4715f, 4.651f, 0.2011f,
+0.4499f, 4.472f, 0.1918f,
+0.2725f, 4.25f, 0.1161f,
+0.2768f, 4.05f, 0.1178f,
+0.3632f, 4.651f, 0.3632f,
+0.3465f, 4.472f, 0.3465f,
+0.2098f, 4.25f, 0.2098f,
+0.213f, 4.05f, 0.213f,
+0.2011f, 4.651f, 0.4715f,
+0.1918f, 4.472f, 0.4499f,
+0.1161f, 4.25f, 0.2725f,
+0.1178f, 4.05f, 0.2768f,
+0.0f, 4.651f, 0.5109f,
+0.0f, 4.472f, 0.4875f,
+0.0f, 4.25f, 0.2953f,
+0.0f, 4.05f, 0.3f,
+-0.2011f, 4.651f, 0.4715f,
+-0.1918f, 4.472f, 0.4499f,
+-0.1161f, 4.25f, 0.2725f,
+-0.1178f, 4.05f, 0.2768f,
+-0.3632f, 4.651f, 0.3632f,
+-0.3465f, 4.472f, 0.3465f,
+-0.2098f, 4.25f, 0.2098f,
+-0.213f, 4.05f, 0.213f,
+-0.4715f, 4.651f, 0.2011f,
+-0.4499f, 4.472f, 0.1918f,
+-0.2725f, 4.25f, 0.1161f,
+-0.2768f, 4.05f, 0.1178f,
+-0.5109f, 4.651f, 0.0f,
+-0.4875f, 4.472f, 0.0f,
+-0.2953f, 4.25f, 0.0f,
+-0.3f, 4.05f, 0.0f,
+-0.4715f, 4.651f, -0.2011f,
+-0.4499f, 4.472f, -0.1918f,
+-0.2725f, 4.25f, -0.1161f,
+-0.2768f, 4.05f, -0.1178f,
+-0.3632f, 4.651f, -0.3632f,
+-0.3465f, 4.472f, -0.3465f,
+-0.2098f, 4.25f, -0.2098f,
+-0.213f, 4.05f, -0.213f,
+-0.2011f, 4.651f, -0.4715f,
+-0.1918f, 4.472f, -0.4499f,
+-0.1161f, 4.25f, -0.2725f,
+-0.1178f, 4.05f, -0.2768f,
+0.0f, 4.651f, -0.5109f,
+0.0f, 4.472f, -0.4875f,
+0.0f, 4.25f, -0.2953f,
+0.0f, 4.05f, -0.3f,
+0.2011f, 4.651f, -0.4715f,
+0.1918f, 4.472f, -0.4499f,
+0.1161f, 4.25f, -0.2725f,
+0.1178f, 4.05f, -0.2768f,
+0.3632f, 4.651f, -0.3632f,
+0.3465f, 4.472f, -0.3465f,
+0.2098f, 4.25f, -0.2098f,
+0.213f, 4.05f, -0.213f,
+0.4715f, 4.651f, -0.2011f,
+0.4499f, 4.472f, -0.1918f,
+0.2725f, 4.25f, -0.1161f,
+0.2768f, 4.05f, -0.1178f,
+0.6844f, 3.916f, 0.0f,
+1.237f, 3.825f, 0.0f,
+1.734f, 3.734f, 0.0f,
+1.95f, 3.6f, 0.0f,
+0.6313f, 3.916f, 0.2686f,
+1.142f, 3.825f, 0.4857f,
+1.6f, 3.734f, 0.6807f,
+1.799f, 3.6f, 0.7654f,
+0.4859f, 3.916f, 0.4859f,
+0.8786f, 3.825f, 0.8786f,
+1.231f, 3.734f, 1.231f,
+1.385f, 3.6f, 1.385f,
+0.2686f, 3.916f, 0.6313f,
+0.4857f, 3.825f, 1.142f,
+0.6807f, 3.734f, 1.6f,
+0.7654f, 3.6f, 1.799f,
+0.0f, 3.916f, 0.6844f,
+0.0f, 3.825f, 1.237f,
+0.0f, 3.734f, 1.734f,
+0.0f, 3.6f, 1.95f,
+-0.2686f, 3.916f, 0.6313f,
+-0.4857f, 3.825f, 1.142f,
+-0.6807f, 3.734f, 1.6f,
+-0.7654f, 3.6f, 1.799f,
+-0.4859f, 3.916f, 0.4859f,
+-0.8786f, 3.825f, 0.8786f,
+-1.231f, 3.734f, 1.231f,
+-1.385f, 3.6f, 1.385f,
+-0.6313f, 3.916f, 0.2686f,
+-1.142f, 3.825f, 0.4857f,
+-1.6f, 3.734f, 0.6807f,
+-1.799f, 3.6f, 0.7654f,
+-0.6844f, 3.916f, 0.0f,
+-1.237f, 3.825f, 0.0f,
+-1.734f, 3.734f, 0.0f,
+-1.95f, 3.6f, 0.0f,
+-0.6313f, 3.916f, -0.2686f,
+-1.142f, 3.825f, -0.4857f,
+-1.6f, 3.734f, -0.6807f,
+-1.799f, 3.6f, -0.7654f,
+-0.4859f, 3.916f, -0.4859f,
+-0.8786f, 3.825f, -0.8786f,
+-1.231f, 3.734f, -1.231f,
+-1.385f, 3.6f, -1.385f,
+-0.2686f, 3.916f, -0.6313f,
+-0.4857f, 3.825f, -1.142f,
+-0.6807f, 3.734f, -1.6f,
+-0.7654f, 3.6f, -1.799f,
+0.0f, 3.916f, -0.6844f,
+0.0f, 3.825f, -1.237f,
+0.0f, 3.734f, -1.734f,
+0.0f, 3.6f, -1.95f,
+0.2686f, 3.916f, -0.6313f,
+0.4857f, 3.825f, -1.142f,
+0.6807f, 3.734f, -1.6f,
+0.7654f, 3.6f, -1.799f,
+0.4859f, 3.916f, -0.4859f,
+0.8786f, 3.825f, -0.8786f,
+1.231f, 3.734f, -1.231f,
+1.385f, 3.6f, -1.385f,
+0.6313f, 3.916f, -0.2686f,
+1.142f, 3.825f, -0.4857f,
+1.6f, 3.734f, -0.6807f,
+1.799f, 3.6f, -0.7654f
+};
+
+
+// 530 normals
+const int numNormals = 530;
+const float normals[530][3] = {
+0.0486f, -0.9986f, 0.0168f,
+0.9976f, -0.0678f, -0.0008f,
+-0.233f, 0.8502f, -0.4719f,
+-0.2299f, 0.9679f, 0.1004f,
+-0.1648f, 0.985f, 0.0501f,
+-0.0117f, 0.7461f, 0.6656f,
+-0.0888f, 0.9692f, 0.2294f,
+0.6449f, -0.7172f, -0.2637f,
+-0.066f, 0.9851f, 0.1583f,
+-0.6585f, -0.342f, -0.6703f,
+-0.293f, 0.9558f, 0.0209f,
+0.179f, 0.9825f, -0.0513f,
+-0.0094f, 0.903f, 0.4295f,
+-0.0059f, -0.986f, -0.1662f,
+-0.7355f, 0.6774f, -0.0026f,
+-0.997f, 0.0763f, 0.0019f,
+-0.1478f, 0.9333f, 0.3271f,
+-0.3014f, -0.6034f, -0.7382f,
+-0.7048f, -0.0681f, 0.706f,
+-0.3361f, 0.9332f, 0.1263f,
+0.3709f, 0.1524f, -0.916f,
+-0.3399f, -0.4121f, 0.8453f,
+0.1921f, 0.9724f, -0.1316f,
+-0.2671f, 0.7429f, 0.6137f,
+0.0888f, 0.9692f, -0.2294f,
+0.066f, 0.9851f, -0.1583f,
+0.9411f, 0.338f, 0.001f,
+0.8666f, -0.2559f, 0.4282f,
+-0.8029f, 0.4968f, 0.3293f,
+-0.0008f, -0.0678f, -0.9976f,
+-0.8453f, -0.4121f, -0.3399f,
+-0.4801f, -0.8741f, 0.0733f,
+0.6355f, -0.772f, 0.0006f,
+-0.9215f, -0.0678f, 0.3822f,
+-0.6698f, -0.6907f, -0.2723f,
+0.3734f, 0.876f, -0.3051f,
+0.3548f, -0.4118f, 0.8393f,
+-0.3629f, 0.2429f, 0.8995f,
+0.9033f, 0.2079f, 0.375f,
+-0.2824f, 0.5939f, 0.7532f,
+0.8938f, 0.4452f, 0.0532f,
+0.1478f, 0.9333f, -0.3271f,
+0.0085f, -0.0031f, -0.9999f,
+0.3595f, 0.933f, 0.0115f,
+0.8995f, 0.2429f, 0.3629f,
+0.7048f, -0.0681f, -0.706f,
+-0.6428f, -0.7172f, -0.2688f,
+0.6366f, -0.447f, 0.6283f,
+-0.1213f, -0.9861f, -0.1128f,
+0.8003f, 0.4978f, 0.334f,
+0.3361f, 0.9332f, -0.1263f,
+0.3399f, -0.4121f, -0.8453f,
+-0.3909f, 0.4452f, 0.8055f,
+0.0117f, 0.7462f, -0.6655f,
+0.9215f, -0.0678f, -0.3822f,
+0.3582f, -0.7656f, 0.5343f,
+-0.9782f, 0.2075f, -0.0011f,
+0.2824f, 0.5939f, -0.7532f,
+0.035f, -0.8413f, 0.5393f,
+-0.8044f, 0.5934f, 0.0262f,
+-0.1128f, -0.9861f, 0.1213f,
+0.13f, -0.1396f, 0.9816f,
+0.6644f, 0.3392f, 0.6659f,
+-0.0042f, -0.6898f, -0.7239f,
+-0.1587f, 0.9851f, 0.065f,
+-0.8719f, -0.3415f, 0.3508f,
+0.6486f, 0.4756f, -0.5941f,
+-0.4991f, 0.8499f, -0.1684f,
+-0.3969f, 0.6342f, -0.6634f,
+0.7041f, -0.3863f, -0.5956f,
+0.3909f, 0.4452f, -0.8055f,
+-0.0391f, -0.0113f, 0.9991f,
+-0.3321f, 0.5936f, -0.733f,
+0.8523f, -0.5219f, -0.0338f,
+0.329f, 0.4978f, 0.8023f,
+0.8044f, 0.5934f, -0.0262f,
+0.1128f, -0.9861f, -0.1213f,
+0.0178f, 0.9861f, -0.1651f,
+0.3491f, 0.4045f, 0.8452f,
+-0.2727f, 0.8505f, 0.4496f,
+0.065f, 0.9851f, 0.1587f,
+-0.0005f, 0.4037f, 0.9148f,
+-0.0077f, -0.4109f, -0.9116f,
+0.5609f, -0.604f, 0.5661f,
+0.8236f, 0.5668f, -0.0138f,
+0.1587f, 0.9851f, -0.065f,
+0.8719f, -0.3415f, -0.3508f,
+-0.7382f, -0.6034f, 0.3014f,
+0.0346f, 0.8495f, 0.5263f,
+-0.4373f, -0.7921f, -0.4257f,
+-0.0532f, 0.4452f, 0.8938f,
+0.0689f, -0.9861f, 0.1509f,
+-0.1509f, -0.9861f, 0.0689f,
+0.7706f, -0.2424f, -0.5893f,
+-0.7543f, -0.6564f, 0.0105f,
+0.0005f, 0.4037f, -0.9148f,
+-0.9116f, -0.4109f, 0.0077f,
+0.0058f, -0.0438f, 0.999f,
+0.1719f, 0.985f, 0.0005f,
+-0.1697f, 0.9693f, 0.1774f,
+0.5874f, -0.5124f, 0.6263f,
+0.7382f, -0.6034f, -0.3014f,
+-0.1518f, 0.985f, -0.081f,
+0.646f, 0.4051f, 0.6468f,
+0.334f, 0.4978f, -0.8003f,
+-0.7354f, -0.6034f, -0.3082f,
+-0.6919f, 0.2428f, -0.6798f,
+0.0532f, 0.4452f, -0.8938f,
+0.3547f, -0.3173f, 0.8794f,
+0.9879f, -0.1547f, -0.0033f,
+-0.0462f, -0.9986f, 0.0223f,
+-0.6088f, 0.4806f, 0.6311f,
+-0.109f, -0.1969f, -0.9743f,
+0.1509f, -0.9861f, -0.0689f,
+-0.0568f, 0.9983f, 0.0009f,
+0.9074f, -0.3096f, -0.2839f,
+0.8677f, 0.4969f, 0.0026f,
+-0.2723f, -0.6907f, 0.6698f,
+-0.4734f, -0.6798f, 0.5599f,
+0.9116f, -0.4109f, -0.0077f,
+0.1697f, 0.9693f, -0.1774f,
+0.5875f, 0.5937f, 0.5497f,
+-0.3232f, 0.6846f, 0.6533f,
+-0.5078f, -0.6913f, 0.5139f,
+-0.4612f, 0.7474f, -0.478f,
+-0.2071f, -0.8049f, 0.556f,
+-0.6976f, -0.7164f, -0.0027f,
+-0.8697f, 0.3388f, 0.3587f,
+0.0462f, -0.9986f, -0.0223f,
+0.2723f, -0.6907f, -0.6698f,
+-0.829f, -0.4466f, -0.3365f,
+0.9148f, 0.4037f, 0.0005f,
+-0.1583f, 0.9851f, -0.066f,
+0.148f, 0.9838f, 0.1002f,
+-0.1717f, 0.985f, -0.0162f,
+-0.4282f, -0.2559f, 0.8666f,
+0.3094f, -0.2556f, 0.9159f,
+0.2803f, -0.6907f, 0.6665f,
+-0.6154f, 0.497f, 0.6117f,
+-0.0262f, 0.5934f, -0.8044f,
+0.0286f, 0.1639f, -0.986f,
+-0.6924f, 0.2083f, 0.6907f,
+-0.0105f, 0.9975f, -0.0685f,
+0.5078f, -0.6913f, -0.5139f,
+0.2071f, -0.8049f, -0.556f,
+-0.4903f, -0.7178f, -0.4942f,
+-0.2637f, -0.7172f, -0.6449f,
+-0.3822f, -0.0678f, -0.9215f,
+0.8697f, 0.3388f, -0.3587f,
+0.2461f, -0.805f, 0.5397f,
+-0.2615f, 0.9334f, 0.2452f,
+0.6187f, 0.747f, -0.243f,
+0.0375f, -0.8401f, -0.5411f,
+0.0054f, 0.9691f, 0.2464f,
+0.3587f, 0.3388f, 0.8697f,
+0.3993f, 0.6582f, -0.6381f,
+-0.3476f, -0.4464f, -0.8245f,
+0.099f, 0.9692f, 0.2251f,
+-0.3666f, -0.3412f, 0.8655f,
+0.0396f, 0.153f, -0.9874f,
+0.0349f, 0.9969f, -0.0698f,
+0.1096f, 0.985f, 0.1324f,
+-0.0578f, -0.9861f, 0.1556f,
+0.4479f, -0.5145f, -0.7311f,
+0.6924f, 0.2083f, -0.6907f,
+0.6096f, 0.747f, 0.265f,
+-0.3508f, -0.3415f, -0.8719f,
+-0.6215f, 0.4454f, -0.6443f,
+-0.4942f, -0.7178f, 0.4903f,
+-0.9402f, -0.3403f, -0.0085f,
+0.0056f, -0.0358f, 0.9993f,
+0.2615f, 0.9334f, -0.2452f,
+-0.0024f, 0.0291f, -0.9995f,
+-0.2667f, 0.9637f, -0.001f,
+0.0569f, -0.2712f, -0.9608f,
+0.7463f, 0.254f, 0.615f,
+0.5153f, 0.6516f, -0.5564f,
+0.0223f, -0.9986f, 0.0462f,
+0.3666f, -0.3412f, -0.8655f,
+0.0578f, -0.9861f, -0.1556f,
+0.6111f, 0.4984f, 0.6148f,
+-0.243f, 0.747f, -0.6187f,
+-0.0092f, 0.2338f, -0.9722f,
+0.478f, 0.7474f, -0.4612f,
+-0.0058f, -0.4457f, -0.8951f,
+-0.4856f, -0.6774f, -0.5524f,
+0.54f, 0.6414f, 0.5448f,
+-0.3365f, -0.4466f, 0.829f,
+-0.2257f, 0.795f, 0.5629f,
+0.8055f, 0.4452f, 0.3909f,
+0.3729f, 0.208f, 0.9042f,
+-0.727f, -0.2562f, 0.6369f,
+-0.0514f, -0.9986f, 0.0029f,
+0.9159f, 0.1555f, -0.3699f,
+0.0019f, -0.2377f, -0.9713f,
+0.4942f, -0.7178f, -0.4903f,
+0.6497f, -0.4127f, 0.6383f,
+0.0089f, 0.0486f, -0.9987f,
+-0.0213f, 0.6301f, -0.7761f,
+-0.9269f, -0.3751f, 0.0038f,
+-0.1215f, 0.9852f, 0.1207f,
+-0.5856f, 0.5198f, 0.6218f,
+0.8655f, -0.3412f, 0.3666f,
+-0.2464f, 0.9691f, 0.0054f,
+0.0123f, 0.1386f, 0.9902f,
+0.0179f, -0.0369f, 0.9991f,
+-0.1207f, 0.9852f, -0.1215f,
+-0.0081f, 0.5671f, 0.8235f,
+-0.8689f, 0.3387f, -0.3607f,
+0.0062f, 0.0309f, -0.9995f,
+0.3365f, -0.4466f, -0.829f,
+-0.3787f, 0.2424f, -0.8931f,
+-0.2904f, 0.4454f, -0.8468f,
+-0.8707f, 0.4915f, 0.0133f,
+0.163f, -0.8182f, 0.5512f,
+0.4337f, -0.8052f, 0.4041f,
+0.0514f, -0.9986f, -0.0029f,
+-0.0084f, 0.1303f, 0.9914f,
+-0.706f, -0.0681f, -0.7048f,
+-0.556f, -0.8049f, -0.2071f,
+0.8448f, 0.4045f, 0.3501f,
+0.4259f, -0.5474f, 0.7203f,
+-0.6907f, 0.2083f, -0.6924f,
+0.1215f, 0.9852f, -0.1207f,
+-0.1263f, 0.9332f, -0.3361f,
+0.7711f, -0.0741f, -0.6323f,
+0.2464f, 0.9691f, -0.0054f,
+0.1774f, 0.9693f, 0.1697f,
+-0.9042f, 0.208f, 0.3729f,
+-0.8393f, -0.4118f, 0.3548f,
+0.6888f, -0.7219f, -0.0648f,
+0.1556f, -0.9861f, 0.0578f,
+0.3271f, 0.9333f, 0.1478f,
+-0.0024f, 0.2379f, 0.9712f,
+-0.0026f, 0.4969f, 0.8677f,
+0.0f, 1.0f, 0.0f,
+0.1912f, -0.9815f, -0.0025f,
+-0.3762f, -0.6681f, 0.6418f,
+-0.7759f, 0.0432f, 0.6292f,
+-0.0208f, -0.8044f, -0.5936f,
+-0.2274f, 0.8822f, -0.4122f,
+0.7532f, 0.5939f, 0.2824f,
+-0.9221f, -0.0681f, -0.3807f,
+-0.2198f, 0.8494f, 0.4796f,
+0.0065f, -0.7656f, 0.6431f,
+-0.5876f, 0.4472f, -0.6742f,
+0.7981f, -0.6024f, 0.0036f,
+-0.0383f, -0.9986f, -0.0341f,
+-0.6369f, -0.2562f, -0.727f,
+-0.5497f, 0.5937f, 0.5875f,
+0.1084f, 0.9431f, 0.314f,
+0.9042f, 0.208f, -0.3729f,
+-0.6659f, 0.3392f, 0.6644f,
+0.8393f, -0.4118f, -0.3548f,
+0.0029f, -0.9986f, 0.0514f,
+-0.9647f, -0.2552f, -0.0635f,
+-0.2294f, 0.9692f, -0.0888f,
+0.0026f, 0.4969f, -0.8677f,
+0.2452f, 0.9334f, 0.2615f,
+0.5171f, -0.4876f, -0.7033f,
+-0.8951f, -0.4457f, 0.0058f,
+-0.5936f, -0.8044f, 0.0208f,
+0.5642f, -0.5426f, -0.6222f,
+0.5938f, 0.4451f, 0.6702f,
+0.5497f, 0.5937f, -0.5875f,
+0.6657f, 0.4653f, 0.5832f,
+0.4857f, -0.6243f, 0.6117f,
+-0.0486f, -0.9986f, -0.0168f,
+-0.6468f, 0.4051f, 0.646f,
+0.6659f, 0.3392f, -0.6644f,
+0.1833f, 0.9735f, -0.1365f,
+0.3955f, 0.8505f, 0.3465f,
+0.5139f, -0.6913f, 0.5078f,
+0.8023f, 0.4978f, -0.329f,
+-0.001f, 0.338f, 0.9411f,
+-0.2496f, 0.8321f, -0.4951f,
+0.8951f, -0.4457f, -0.0058f,
+0.233f, 0.8502f, 0.4719f,
+-0.0168f, -0.9986f, 0.0486f,
+0.5936f, -0.8044f, -0.0208f,
+-0.05f, 0.3155f, 0.9475f,
+0.6585f, -0.342f, 0.6703f,
+0.4909f, -0.1864f, -0.8509f,
+-0.37f, 0.9238f, -0.0973f,
+0.6468f, 0.4051f, -0.646f,
+0.0059f, -0.986f, 0.1662f,
+-0.3724f, 0.9278f, -0.0202f,
+-0.3501f, 0.4045f, 0.8448f,
+-0.0425f, 0.8398f, -0.5411f,
+-0.1684f, 0.8499f, 0.4991f,
+-0.6665f, -0.6907f, 0.2803f,
+-0.2251f, 0.9692f, 0.099f,
+0.9241f, -0.3816f, -0.0169f,
+0.001f, 0.338f, -0.9411f,
+-0.9411f, 0.338f, -0.001f,
+-0.8666f, -0.2559f, -0.4282f,
+0.0262f, 0.5183f, -0.8547f,
+0.3014f, -0.6034f, 0.7382f,
+0.0168f, -0.9986f, -0.0486f,
+-0.3548f, -0.4118f, -0.8393f,
+-0.6023f, -0.5297f, 0.5971f,
+-0.9033f, 0.2079f, -0.375f,
+-0.8938f, 0.4452f, -0.0532f,
+0.6044f, 0.7397f, 0.2957f,
+0.0008f, -0.0678f, 0.9976f,
+0.7058f, 0.0906f, -0.7025f,
+0.8453f, -0.4121f, 0.3399f,
+-0.3595f, 0.933f, -0.0115f,
+0.6698f, -0.6907f, 0.2723f,
+-0.8995f, 0.2429f, -0.3629f,
+-0.6366f, -0.447f, -0.6283f,
+0.3501f, 0.4045f, -0.8448f,
+-0.01f, -0.0605f, 0.9981f,
+-0.8003f, 0.4978f, -0.334f,
+0.1684f, 0.8499f, -0.4991f,
+0.6665f, -0.6907f, -0.2803f,
+0.2251f, 0.9692f, -0.099f,
+-0.0036f, -0.6024f, 0.7981f,
+0.6637f, -0.2967f, -0.6865f,
+-0.081f, 0.985f, 0.1518f,
+0.0084f, 0.2423f, 0.9701f,
+0.0071f, -0.9029f, -0.4296f,
+-0.8679f, 0.4966f, -0.0026f,
+0.0123f, 0.5735f, 0.819f,
+-0.0005f, 0.985f, 0.1719f,
+0.6428f, -0.7172f, 0.2688f,
+0.6588f, -0.3366f, 0.6727f,
+0.1213f, -0.9861f, 0.1128f,
+-0.8931f, 0.2424f, 0.3787f,
+-0.1662f, -0.986f, 0.0059f,
+0.9994f, 0.0313f, 0.0095f,
+0.762f, -0.146f, 0.6308f,
+-0.7731f, 0.0861f, -0.6283f,
+-0.6644f, 0.3392f, -0.6659f,
+-0.0027f, -0.7164f, 0.6976f,
+0.0036f, -0.6024f, -0.7981f,
+0.9782f, 0.2075f, 0.0011f,
+0.0405f, -0.9991f, -0.0018f,
+0.6882f, -0.703f, 0.179f,
+-0.0115f, 0.933f, 0.3595f,
+0.0911f, 0.0518f, -0.9944f,
+0.0005f, 0.985f, -0.1719f,
+0.5337f, -0.5852f, -0.6104f,
+0.0042f, -0.6898f, 0.7239f,
+0.4863f, 0.2366f, 0.8411f,
+0.4991f, 0.8499f, 0.1684f,
+-0.6543f, 0.7561f, 0.0071f,
+0.265f, 0.747f, -0.6096f,
+-0.329f, 0.4978f, -0.8023f,
+0.1662f, -0.986f, -0.0059f,
+-0.3491f, 0.4045f, -0.8452f,
+0.3321f, 0.5936f, 0.733f,
+-0.065f, 0.9851f, -0.1587f,
+-0.6283f, -0.447f, 0.6366f,
+0.0027f, -0.7164f, -0.6976f,
+-0.1316f, 0.6339f, 0.762f,
+-0.5609f, -0.604f, -0.5661f,
+-0.8452f, 0.4045f, 0.3491f,
+-0.5263f, 0.8495f, 0.0346f,
+0.0115f, 0.933f, -0.3595f,
+-0.0346f, 0.8495f, -0.5263f,
+0.0077f, -0.4109f, 0.9116f,
+0.5758f, -0.8175f, -0.0017f,
+-0.0011f, 0.2075f, 0.9782f,
+-0.0689f, -0.9861f, -0.1509f,
+0.2934f, -0.5928f, -0.7499f,
+0.0724f, 0.1198f, -0.9901f,
+-0.7367f, -0.275f, -0.6176f,
+-0.3131f, 0.8154f, 0.4868f,
+-0.0114f, 0.0022f, 0.9999f,
+0.6283f, -0.447f, -0.6366f,
+0.8452f, 0.4045f, -0.3491f,
+0.5263f, 0.8495f, -0.0346f,
+-0.6383f, -0.4127f, 0.6497f,
+-0.1719f, 0.985f, -0.0005f,
+-0.6703f, -0.342f, 0.6585f,
+-0.0085f, -0.3403f, 0.9402f,
+-0.646f, 0.4051f, -0.6468f,
+0.0011f, 0.2075f, -0.9782f,
+-0.7216f, -0.3071f, 0.6204f,
+0.0282f, 0.0023f, -0.9995f,
+-0.2483f, 0.6806f, -0.6892f,
+0.1518f, 0.985f, 0.081f,
+0.047f, 0.0466f, -0.9978f,
+0.7354f, -0.6034f, 0.3082f,
+0.6919f, 0.2428f, 0.6798f,
+0.4086f, -0.3626f, -0.8375f,
+0.6383f, -0.4127f, -0.6497f,
+-0.5875f, 0.5937f, -0.5497f,
+0.6703f, -0.342f, -0.6585f,
+-0.8245f, -0.4464f, 0.3476f,
+0.0085f, -0.3403f, -0.9402f,
+-0.0591f, -0.0663f, 0.996f,
+0.0f, -1.0f, 0.0f,
+0.4612f, 0.7474f, 0.478f,
+0.6976f, -0.7164f, 0.0027f,
+-0.9148f, 0.4037f, -0.0005f,
+0.173f, -0.8158f, -0.5518f,
+-0.3607f, 0.3387f, 0.8689f,
+0.7836f, -0.2411f, 0.5724f,
+-0.1985f, 0.8026f, -0.5623f,
+-0.3094f, -0.2556f, -0.9159f,
+-0.2803f, -0.6907f, -0.6665f,
+0.8245f, -0.4464f, -0.3476f,
+0.829f, -0.4466f, 0.3365f,
+-0.4848f, 0.7385f, 0.4683f,
+0.1583f, 0.9851f, 0.066f,
+-0.0077f, 0.7656f, -0.6432f,
+-0.0162f, 0.985f, 0.1717f,
+0.1717f, 0.985f, 0.0162f,
+0.0244f, 0.9805f, -0.1949f,
+-0.2461f, -0.805f, -0.5397f,
+0.0262f, 0.5934f, 0.8044f,
+0.142f, 0.1881f, 0.9718f,
+0.1846f, 0.1002f, 0.9776f,
+0.4903f, -0.7178f, 0.4942f,
+0.2637f, -0.7172f, 0.6449f,
+0.3822f, -0.0678f, 0.9215f,
+-0.0054f, 0.9691f, -0.2464f,
+0.3607f, 0.3387f, -0.8689f,
+-0.3587f, 0.3388f, -0.8697f,
+-0.5694f, -0.8219f, 0.0081f,
+-0.1324f, 0.985f, 0.1096f,
+-0.099f, 0.9692f, -0.2251f,
+-0.6702f, 0.4451f, 0.5938f,
+0.0077f, -0.9976f, 0.0684f,
+-0.5661f, -0.604f, 0.5609f,
+-0.1096f, 0.985f, -0.1324f,
+-0.6096f, 0.747f, -0.265f,
+-0.0015f, 0.0295f, -0.9995f,
+0.3476f, -0.4464f, 0.8245f,
+-0.0635f, -0.2552f, 0.9647f,
+-0.8468f, 0.4454f, 0.2904f,
+-0.4719f, 0.8502f, 0.233f,
+-0.0502f, 0.8385f, 0.5425f,
+-0.6671f, 0.7448f, -0.0116f,
+0.3508f, -0.3415f, 0.8719f,
+-0.4119f, 0.6135f, -0.6736f,
+-0.2688f, -0.7172f, 0.6428f,
+-0.4041f, -0.8052f, 0.4337f,
+-0.375f, 0.2079f, 0.9033f,
+-0.0223f, -0.9986f, -0.0462f,
+0.6702f, 0.4451f, -0.5938f,
+0.9402f, -0.3403f, 0.0085f,
+0.5661f, -0.604f, -0.5609f,
+-0.6252f, 0.7406f, 0.246f,
+-0.0341f, -0.9986f, 0.0383f,
+-0.6111f, 0.4984f, -0.6148f,
+0.6655f, 0.7462f, 0.0117f,
+0.1233f, 0.199f, 0.9722f,
+0.8468f, 0.4454f, -0.2904f,
+0.7383f, 0.2702f, -0.6179f,
+-0.8055f, 0.4452f, -0.3909f,
+-0.3729f, 0.208f, -0.9042f,
+0.4719f, 0.8502f, -0.233f,
+0.243f, 0.747f, 0.6187f,
+-0.6497f, -0.4127f, -0.6383f,
+-0.5406f, 0.5651f, -0.623f,
+0.0058f, -0.4457f, 0.8951f,
+-0.3082f, -0.6034f, 0.7354f,
+-0.8655f, -0.3412f, -0.3666f,
+0.2688f, -0.7172f, -0.6428f,
+0.4041f, -0.8052f, -0.4337f,
+0.375f, 0.2079f, -0.9033f,
+0.0341f, -0.9986f, -0.0383f,
+-0.9701f, 0.2423f, 0.0084f,
+-0.3807f, -0.0681f, 0.9221f,
+0.9643f, -0.2551f, 0.0705f,
+-0.8758f, 0.4808f, 0.0415f,
+0.1207f, 0.9852f, 0.1215f,
+0.4821f, 0.7724f, 0.4133f,
+-0.0522f, 0.9982f, 0.0278f,
+-0.4337f, -0.8052f, -0.4041f,
+-0.6164f, 0.4198f, 0.6661f,
+-0.8448f, 0.4045f, -0.3501f,
+0.3082f, -0.6034f, -0.7354f,
+0.8689f, 0.3387f, 0.3607f,
+0.6894f, -0.7242f, 0.0091f,
+0.3787f, 0.2424f, 0.8931f,
+0.2904f, 0.4454f, 0.8468f,
+0.6148f, 0.4984f, -0.6111f,
+0.0501f, 0.985f, 0.1648f,
+-0.5397f, -0.805f, 0.2461f,
+-0.9159f, -0.2556f, 0.3094f,
+0.706f, -0.0681f, 0.7048f,
+-0.3341f, 0.4972f, 0.8006f,
+0.556f, -0.8049f, 0.2071f,
+-0.1774f, 0.9693f, -0.1697f,
+0.6907f, 0.2083f, 0.6924f,
+0.1263f, 0.9332f, 0.3361f,
+0.3807f, -0.0681f, -0.9221f,
+-0.1556f, -0.9861f, -0.0578f,
+-0.3271f, 0.9333f, -0.1478f,
+-0.3465f, 0.8505f, 0.3955f,
+0.5315f, 0.8438f, -0.0735f,
+0.9737f, 0.2276f, -0.0003f,
+0.6441f, 0.7648f, -0.0112f,
+-0.7239f, -0.6898f, 0.0042f,
+-0.7532f, 0.5939f, -0.2824f,
+0.1093f, 0.1415f, -0.9838f,
+0.5397f, -0.805f, -0.2461f,
+-0.7981f, -0.6024f, -0.0036f,
+0.9456f, 0.3251f, -0.0052f,
+0.1278f, 0.9696f, -0.2085f,
+0.0208f, -0.8044f, 0.5936f,
+0.1635f, 0.1348f, -0.9772f,
+-0.733f, 0.5936f, 0.3321f,
+-0.0505f, 0.9852f, -0.1635f,
+0.4089f, -0.9069f, -0.1015f,
+-0.0029f, -0.9986f, -0.0514f,
+-0.1796f, 0.814f, -0.5522f,
+0.9221f, -0.0681f, 0.3807f,
+0.0383f, -0.9986f, 0.0341f,
+0.6369f, -0.2562f, 0.727f,
+0.3465f, 0.8505f, -0.3955f,
+-0.2452f, 0.9334f, -0.2615f,
+0.4921f, -0.247f, 0.8346f,
+-0.9976f, -0.0678f, 0.0008f,
+-0.5396f, 0.8418f, -0.0094f,
+0.2294f, 0.9692f, 0.0888f,
+0.7239f, -0.6898f, -0.0042f,
+-0.4472f, 0.5952f, 0.6675f,
+-0.6449f, -0.7172f, 0.2637f,
+0.4543f, 0.2732f, -0.8478f,
+-0.6798f, 0.2428f, 0.6919f,
+-0.5938f, 0.4451f, -0.6702f,
+0.733f, 0.5936f, -0.3321f,
+-0.3955f, 0.8505f, -0.3465f,
+-0.5139f, -0.6913f, -0.5078f,
+-0.623f, -0.5156f, -0.5881f
+};
+
+// 1 color
+//255 255 0
+
+// 1024 faces
+// numIdx fidx0 fidx1 fidx2 nidx0 nidx1 nidx2 coloridx
+
+const int numFaces = 1024;
+const int faces[1024][8] = {
+3, 0, 5, 6, 255, 295, 309, 0,
+3, 6, 1, 0, 309, 465, 255, 0,
+3, 1, 6, 7, 465, 309, 134, 0,
+3, 7, 2, 1, 134, 4, 465, 0,
+3, 2, 7, 8, 4, 134, 165, 0,
+3, 8, 3, 2, 165, 448, 4, 0,
+3, 3, 8, 9, 448, 165, 49, 0,
+3, 9, 4, 3, 49, 116, 448, 0,
+3, 5, 10, 11, 295, 248, 106, 0,
+3, 11, 6, 5, 106, 309, 295, 0,
+3, 6, 11, 12, 309, 106, 102, 0,
+3, 12, 7, 6, 102, 134, 309, 0,
+3, 7, 12, 13, 134, 102, 394, 0,
+3, 13, 8, 7, 394, 165, 134, 0,
+3, 8, 13, 14, 165, 394, 180, 0,
+3, 14, 9, 8, 180, 49, 165, 0,
+3, 10, 15, 16, 248, 401, 211, 0,
+3, 16, 11, 10, 211, 106, 248, 0,
+3, 11, 16, 17, 106, 211, 427, 0,
+3, 17, 12, 11, 427, 102, 106, 0,
+3, 12, 17, 18, 102, 427, 455, 0,
+3, 18, 13, 12, 455, 394, 102, 0,
+3, 13, 18, 19, 394, 455, 74, 0,
+3, 19, 14, 13, 74, 180, 394, 0,
+3, 15, 20, 21, 401, 174, 182, 0,
+3, 21, 16, 15, 182, 211, 401, 0,
+3, 16, 21, 22, 211, 182, 507, 0,
+3, 22, 17, 16, 507, 427, 211, 0,
+3, 17, 22, 23, 427, 507, 5, 0,
+3, 23, 18, 17, 5, 455, 427, 0,
+3, 18, 23, 24, 455, 5, 234, 0,
+3, 24, 19, 18, 234, 74, 455, 0,
+3, 20, 25, 26, 174, 386, 20, 0,
+3, 26, 21, 20, 20, 182, 174, 0,
+3, 21, 26, 27, 182, 20, 410, 0,
+3, 27, 22, 21, 410, 507, 182, 0,
+3, 22, 27, 28, 507, 410, 23, 0,
+3, 28, 23, 22, 23, 5, 507, 0,
+3, 23, 28, 29, 5, 23, 485, 0,
+3, 29, 24, 23, 485, 234, 5, 0,
+3, 25, 30, 31, 386, 69, 305, 0,
+3, 31, 26, 25, 305, 20, 386, 0,
+3, 26, 31, 32, 20, 305, 503, 0,
+3, 32, 27, 26, 503, 410, 20, 0,
+3, 27, 32, 33, 410, 503, 405, 0,
+3, 33, 28, 27, 405, 23, 410, 0,
+3, 28, 33, 34, 23, 405, 138, 0,
+3, 34, 29, 28, 138, 485, 23, 0,
+3, 30, 35, 36, 69, 115, 193, 0,
+3, 36, 31, 30, 193, 305, 69, 0,
+3, 31, 36, 37, 305, 193, 270, 0,
+3, 37, 32, 31, 270, 503, 305, 0,
+3, 32, 37, 38, 503, 270, 445, 0,
+3, 38, 33, 32, 445, 405, 503, 0,
+3, 33, 38, 39, 405, 445, 28, 0,
+3, 39, 34, 33, 28, 138, 405, 0,
+3, 35, 40, 41, 115, 467, 495, 0,
+3, 41, 36, 35, 495, 193, 115, 0,
+3, 36, 41, 42, 193, 495, 11, 0,
+3, 42, 37, 36, 11, 270, 193, 0,
+3, 37, 42, 43, 270, 11, 435, 0,
+3, 43, 38, 37, 435, 445, 270, 0,
+3, 38, 43, 44, 445, 435, 322, 0,
+3, 44, 39, 38, 322, 28, 445, 0,
+3, 40, 45, 46, 467, 27, 44, 0,
+3, 46, 41, 40, 44, 495, 467, 0,
+3, 41, 46, 47, 495, 44, 409, 0,
+3, 47, 42, 41, 409, 11, 495, 0,
+3, 42, 47, 48, 11, 409, 428, 0,
+3, 48, 43, 42, 428, 435, 11, 0,
+3, 43, 48, 49, 435, 428, 313, 0,
+3, 49, 44, 43, 313, 322, 435, 0,
+3, 45, 50, 51, 27, 513, 385, 0,
+3, 51, 46, 45, 385, 44, 27, 0,
+3, 46, 51, 52, 44, 385, 382, 0,
+3, 52, 47, 46, 382, 409, 44, 0,
+3, 47, 52, 53, 409, 382, 124, 0,
+3, 53, 48, 47, 124, 428, 409, 0,
+3, 48, 53, 54, 428, 124, 447, 0,
+3, 54, 49, 48, 447, 313, 428, 0,
+3, 50, 55, 56, 513, 136, 478, 0,
+3, 56, 51, 50, 478, 385, 513, 0,
+3, 51, 56, 57, 385, 478, 161, 0,
+3, 57, 52, 51, 161, 382, 385, 0,
+3, 52, 57, 58, 382, 161, 181, 0,
+3, 58, 53, 52, 181, 124, 382, 0,
+3, 53, 58, 59, 124, 181, 348, 0,
+3, 59, 54, 53, 348, 447, 124, 0,
+3, 55, 60, 61, 136, 431, 320, 0,
+3, 61, 56, 55, 320, 478, 136, 0,
+3, 56, 61, 62, 478, 320, 481, 0,
+3, 62, 57, 56, 481, 161, 478, 0,
+3, 57, 62, 63, 161, 481, 53, 0,
+3, 63, 58, 57, 53, 181, 161, 0,
+3, 58, 63, 64, 181, 53, 257, 0,
+3, 64, 59, 58, 257, 348, 181, 0,
+3, 60, 65, 66, 431, 135, 37, 0,
+3, 66, 61, 60, 37, 320, 431, 0,
+3, 61, 66, 67, 320, 37, 408, 0,
+3, 67, 62, 61, 408, 481, 320, 0,
+3, 62, 67, 68, 481, 408, 347, 0,
+3, 68, 63, 62, 347, 53, 481, 0,
+3, 63, 68, 69, 53, 347, 104, 0,
+3, 69, 64, 63, 104, 257, 53, 0,
+3, 65, 70, 71, 135, 191, 524, 0,
+3, 71, 66, 65, 524, 37, 135, 0,
+3, 66, 71, 72, 37, 524, 319, 0,
+3, 72, 67, 66, 319, 408, 37, 0,
+3, 67, 72, 73, 408, 319, 183, 0,
+3, 73, 68, 67, 183, 347, 408, 0,
+3, 68, 73, 74, 347, 183, 480, 0,
+3, 74, 69, 68, 480, 104, 347, 0,
+3, 70, 75, 76, 191, 483, 328, 0,
+3, 76, 71, 70, 328, 524, 191, 0,
+3, 71, 76, 77, 524, 328, 422, 0,
+3, 77, 72, 71, 422, 319, 524, 0,
+3, 72, 77, 78, 319, 422, 151, 0,
+3, 78, 73, 72, 151, 183, 319, 0,
+3, 73, 78, 79, 183, 151, 273, 0,
+3, 79, 74, 73, 273, 480, 183, 0,
+3, 75, 0, 1, 483, 255, 465, 0,
+3, 1, 76, 75, 465, 328, 483, 0,
+3, 76, 1, 2, 328, 465, 4, 0,
+3, 2, 77, 76, 4, 422, 328, 0,
+3, 77, 2, 3, 422, 4, 448, 0,
+3, 3, 78, 77, 448, 151, 422, 0,
+3, 78, 3, 4, 151, 448, 116, 0,
+3, 4, 79, 78, 116, 273, 151, 0,
+3, 4, 9, 84, 116, 49, 220, 0,
+3, 84, 80, 4, 220, 131, 116, 0,
+3, 80, 84, 85, 131, 220, 476, 0,
+3, 85, 81, 80, 476, 26, 131, 0,
+3, 81, 85, 86, 26, 476, 38, 0,
+3, 86, 82, 81, 38, 336, 26, 0,
+3, 82, 86, 87, 336, 38, 511, 0,
+3, 87, 83, 82, 511, 1, 336, 0,
+3, 9, 14, 88, 49, 180, 103, 0,
+3, 88, 84, 9, 103, 220, 49, 0,
+3, 84, 88, 89, 220, 103, 62, 0,
+3, 89, 85, 84, 62, 476, 220, 0,
+3, 85, 89, 90, 476, 62, 488, 0,
+3, 90, 86, 85, 488, 38, 476, 0,
+3, 86, 90, 91, 38, 488, 484, 0,
+3, 91, 87, 86, 484, 511, 38, 0,
+3, 14, 19, 92, 180, 74, 78, 0,
+3, 92, 88, 14, 78, 103, 180, 0,
+3, 88, 92, 93, 103, 78, 154, 0,
+3, 93, 89, 88, 154, 62, 103, 0,
+3, 89, 93, 94, 62, 154, 190, 0,
+3, 94, 90, 89, 190, 488, 62, 0,
+3, 90, 94, 95, 488, 190, 417, 0,
+3, 95, 91, 90, 417, 484, 488, 0,
+3, 19, 24, 96, 74, 234, 81, 0,
+3, 96, 92, 19, 81, 78, 74, 0,
+3, 92, 96, 97, 78, 81, 274, 0,
+3, 97, 93, 92, 274, 154, 78, 0,
+3, 93, 97, 98, 154, 274, 363, 0,
+3, 98, 94, 93, 363, 190, 154, 0,
+3, 94, 98, 99, 190, 363, 304, 0,
+3, 99, 95, 94, 304, 417, 190, 0,
+3, 24, 29, 100, 234, 485, 287, 0,
+3, 100, 96, 24, 287, 81, 234, 0,
+3, 96, 100, 101, 81, 287, 398, 0,
+3, 101, 97, 96, 398, 274, 81, 0,
+3, 97, 101, 102, 274, 398, 440, 0,
+3, 102, 98, 97, 440, 363, 274, 0,
+3, 98, 102, 103, 363, 440, 466, 0,
+3, 103, 99, 98, 466, 304, 363, 0,
+3, 29, 34, 104, 485, 138, 268, 0,
+3, 104, 100, 29, 268, 287, 485, 0,
+3, 100, 104, 105, 287, 268, 252, 0,
+3, 105, 101, 100, 252, 398, 287, 0,
+3, 101, 105, 106, 398, 252, 141, 0,
+3, 106, 102, 101, 141, 440, 398, 0,
+3, 102, 106, 107, 440, 141, 18, 0,
+3, 107, 103, 102, 18, 466, 440, 0,
+3, 34, 39, 108, 138, 28, 357, 0,
+3, 108, 104, 34, 357, 268, 138, 0,
+3, 104, 108, 109, 268, 357, 127, 0,
+3, 109, 105, 104, 127, 252, 268, 0,
+3, 105, 109, 110, 252, 127, 228, 0,
+3, 110, 106, 105, 228, 141, 252, 0,
+3, 106, 110, 111, 141, 228, 33, 0,
+3, 111, 107, 106, 33, 18, 141, 0,
+3, 39, 44, 112, 28, 322, 396, 0,
+3, 112, 108, 39, 396, 357, 28, 0,
+3, 108, 112, 113, 357, 396, 294, 0,
+3, 113, 109, 108, 294, 127, 357, 0,
+3, 109, 113, 114, 127, 294, 56, 0,
+3, 114, 110, 109, 56, 228, 127, 0,
+3, 110, 114, 115, 228, 56, 517, 0,
+3, 115, 111, 110, 517, 33, 228, 0,
+3, 44, 49, 116, 322, 313, 474, 0,
+3, 116, 112, 44, 474, 396, 322, 0,
+3, 112, 116, 117, 396, 474, 208, 0,
+3, 117, 113, 112, 208, 294, 396, 0,
+3, 113, 117, 118, 294, 208, 301, 0,
+3, 118, 114, 113, 301, 56, 294, 0,
+3, 114, 118, 119, 56, 301, 242, 0,
+3, 119, 115, 114, 242, 517, 56, 0,
+3, 49, 54, 120, 313, 447, 377, 0,
+3, 120, 116, 49, 377, 474, 313, 0,
+3, 116, 120, 121, 474, 377, 333, 0,
+3, 121, 117, 116, 333, 208, 474, 0,
+3, 117, 121, 122, 208, 333, 222, 0,
+3, 122, 118, 117, 222, 301, 208, 0,
+3, 118, 122, 123, 301, 222, 218, 0,
+3, 123, 119, 118, 218, 242, 301, 0,
+3, 54, 59, 124, 447, 348, 350, 0,
+3, 124, 120, 54, 350, 377, 447, 0,
+3, 120, 124, 125, 377, 350, 420, 0,
+3, 125, 121, 120, 420, 333, 377, 0,
+3, 121, 125, 126, 333, 420, 453, 0,
+3, 126, 122, 121, 453, 222, 333, 0,
+3, 122, 126, 127, 222, 453, 147, 0,
+3, 127, 123, 122, 147, 218, 222, 0,
+3, 59, 64, 128, 348, 257, 95, 0,
+3, 128, 124, 59, 95, 350, 348, 0,
+3, 124, 128, 129, 350, 95, 293, 0,
+3, 129, 125, 124, 293, 420, 350, 0,
+3, 125, 129, 130, 420, 293, 378, 0,
+3, 130, 126, 125, 378, 453, 420, 0,
+3, 126, 130, 131, 453, 378, 29, 0,
+3, 131, 127, 126, 29, 147, 453, 0,
+3, 64, 69, 132, 257, 104, 311, 0,
+3, 132, 128, 64, 311, 95, 257, 0,
+3, 128, 132, 133, 95, 311, 419, 0,
+3, 133, 129, 128, 419, 293, 95, 0,
+3, 129, 133, 134, 293, 419, 463, 0,
+3, 134, 130, 129, 463, 378, 293, 0,
+3, 130, 134, 135, 378, 463, 490, 0,
+3, 135, 131, 130, 490, 29, 378, 0,
+3, 69, 74, 136, 104, 480, 284, 0,
+3, 136, 132, 69, 284, 311, 104, 0,
+3, 132, 136, 137, 311, 284, 269, 0,
+3, 137, 133, 132, 269, 419, 311, 0,
+3, 133, 137, 138, 419, 269, 164, 0,
+3, 138, 134, 133, 164, 463, 419, 0,
+3, 134, 138, 139, 463, 164, 45, 0,
+3, 139, 135, 134, 45, 490, 463, 0,
+3, 74, 79, 140, 480, 273, 371, 0,
+3, 140, 136, 74, 371, 284, 480, 0,
+3, 136, 140, 141, 284, 371, 148, 0,
+3, 141, 137, 136, 148, 269, 284, 0,
+3, 137, 141, 142, 269, 148, 251, 0,
+3, 142, 138, 137, 251, 164, 269, 0,
+3, 138, 142, 143, 164, 251, 54, 0,
+3, 143, 139, 138, 54, 45, 164, 0,
+3, 79, 4, 80, 273, 116, 131, 0,
+3, 80, 140, 79, 131, 371, 273, 0,
+3, 140, 80, 81, 371, 131, 26, 0,
+3, 81, 141, 140, 26, 148, 371, 0,
+3, 141, 81, 82, 148, 26, 336, 0,
+3, 82, 142, 141, 336, 251, 148, 0,
+3, 142, 82, 83, 251, 336, 1, 0,
+3, 83, 143, 142, 1, 54, 251, 0,
+3, 83, 87, 148, 1, 511, 404, 0,
+3, 148, 144, 83, 404, 276, 1, 0,
+3, 144, 148, 149, 276, 404, 308, 0,
+3, 149, 145, 144, 308, 520, 276, 0,
+3, 145, 149, 150, 520, 308, 325, 0,
+3, 150, 146, 145, 325, 395, 520, 0,
+3, 146, 150, 151, 395, 325, 384, 0,
+3, 151, 147, 146, 384, 246, 395, 0,
+3, 87, 91, 152, 511, 484, 47, 0,
+3, 152, 148, 87, 47, 404, 511, 0,
+3, 148, 152, 153, 404, 47, 272, 0,
+3, 153, 149, 148, 272, 308, 404, 0,
+3, 149, 153, 154, 308, 272, 415, 0,
+3, 154, 150, 149, 415, 325, 308, 0,
+3, 150, 154, 155, 325, 415, 83, 0,
+3, 155, 151, 150, 83, 384, 325, 0,
+3, 91, 95, 156, 484, 417, 430, 0,
+3, 156, 152, 91, 430, 47, 484, 0,
+3, 152, 156, 157, 47, 430, 137, 0,
+3, 157, 153, 152, 137, 272, 47, 0,
+3, 153, 157, 158, 272, 137, 416, 0,
+3, 158, 154, 153, 416, 415, 272, 0,
+3, 154, 158, 159, 415, 416, 297, 0,
+3, 159, 155, 154, 297, 83, 415, 0,
+3, 95, 99, 160, 417, 304, 458, 0,
+3, 160, 156, 95, 458, 430, 417, 0,
+3, 156, 160, 161, 430, 458, 343, 0,
+3, 161, 157, 156, 343, 137, 430, 0,
+3, 157, 161, 162, 137, 343, 334, 0,
+3, 162, 158, 157, 334, 416, 137, 0,
+3, 158, 162, 163, 416, 334, 317, 0,
+3, 163, 159, 158, 317, 297, 416, 0,
+3, 99, 103, 164, 304, 466, 187, 0,
+3, 164, 160, 99, 187, 458, 304, 0,
+3, 160, 164, 165, 458, 187, 117, 0,
+3, 165, 161, 160, 117, 343, 458, 0,
+3, 161, 165, 166, 343, 117, 438, 0,
+3, 166, 162, 161, 438, 334, 343, 0,
+3, 162, 166, 167, 334, 438, 459, 0,
+3, 167, 163, 162, 459, 317, 334, 0,
+3, 103, 107, 168, 466, 18, 353, 0,
+3, 168, 164, 103, 353, 187, 466, 0,
+3, 164, 168, 169, 187, 353, 123, 0,
+3, 169, 165, 164, 123, 117, 187, 0,
+3, 165, 169, 170, 117, 123, 168, 0,
+3, 170, 166, 165, 168, 438, 117, 0,
+3, 166, 170, 171, 438, 168, 426, 0,
+3, 171, 167, 166, 426, 459, 438, 0,
+3, 107, 111, 172, 18, 33, 390, 0,
+3, 172, 168, 107, 390, 353, 18, 0,
+3, 168, 172, 173, 353, 390, 290, 0,
+3, 173, 169, 168, 290, 123, 353, 0,
+3, 169, 173, 174, 123, 290, 522, 0,
+3, 174, 170, 169, 522, 168, 123, 0,
+3, 170, 174, 175, 168, 522, 87, 0,
+3, 175, 171, 170, 87, 426, 168, 0,
+3, 111, 115, 176, 33, 517, 260, 0,
+3, 176, 172, 111, 260, 390, 33, 0,
+3, 172, 176, 177, 390, 260, 497, 0,
+3, 177, 173, 172, 497, 290, 390, 0,
+3, 173, 177, 178, 290, 497, 126, 0,
+3, 178, 174, 173, 126, 522, 290, 0,
+3, 174, 178, 179, 522, 126, 501, 0,
+3, 179, 175, 174, 501, 87, 522, 0,
+3, 115, 119, 180, 517, 242, 130, 0,
+3, 180, 176, 115, 130, 260, 517, 0,
+3, 176, 180, 181, 260, 130, 34, 0,
+3, 181, 177, 176, 34, 497, 260, 0,
+3, 177, 181, 182, 497, 34, 46, 0,
+3, 182, 178, 177, 46, 126, 497, 0,
+3, 178, 182, 183, 126, 46, 105, 0,
+3, 183, 179, 178, 105, 501, 126, 0,
+3, 119, 123, 184, 242, 218, 310, 0,
+3, 184, 180, 119, 310, 130, 242, 0,
+3, 180, 184, 185, 130, 310, 528, 0,
+3, 185, 181, 180, 528, 34, 130, 0,
+3, 181, 185, 186, 34, 528, 145, 0,
+3, 186, 182, 181, 145, 46, 34, 0,
+3, 182, 186, 187, 46, 145, 356, 0,
+3, 187, 183, 182, 356, 105, 46, 0,
+3, 123, 127, 188, 218, 147, 156, 0,
+3, 188, 184, 123, 156, 310, 218, 0,
+3, 184, 188, 189, 310, 156, 402, 0,
+3, 189, 185, 184, 402, 528, 310, 0,
+3, 185, 189, 190, 528, 402, 146, 0,
+3, 190, 186, 185, 146, 145, 528, 0,
+3, 186, 190, 191, 145, 146, 17, 0,
+3, 191, 187, 186, 17, 356, 145, 0,
+3, 127, 131, 192, 147, 29, 184, 0,
+3, 192, 188, 127, 184, 156, 147, 0,
+3, 188, 192, 193, 156, 184, 63, 0,
+3, 193, 189, 188, 63, 402, 156, 0,
+3, 189, 193, 194, 402, 63, 354, 0,
+3, 194, 190, 189, 354, 146, 402, 0,
+3, 190, 194, 195, 146, 354, 335, 0,
+3, 195, 191, 190, 335, 17, 146, 0,
+3, 131, 135, 196, 29, 490, 210, 0,
+3, 196, 192, 131, 210, 184, 29, 0,
+3, 192, 196, 197, 184, 210, 129, 0,
+3, 197, 193, 192, 129, 63, 184, 0,
+3, 193, 197, 198, 63, 129, 461, 0,
+3, 198, 194, 193, 461, 354, 63, 0,
+3, 194, 198, 199, 354, 461, 475, 0,
+3, 199, 195, 194, 475, 335, 354, 0,
+3, 135, 139, 200, 490, 45, 370, 0,
+3, 200, 196, 135, 370, 210, 490, 0,
+3, 196, 200, 201, 210, 370, 143, 0,
+3, 201, 197, 196, 143, 129, 210, 0,
+3, 197, 201, 202, 129, 143, 195, 0,
+3, 202, 198, 197, 195, 461, 129, 0,
+3, 198, 202, 203, 461, 195, 444, 0,
+3, 203, 199, 198, 444, 475, 461, 0,
+3, 139, 143, 204, 45, 54, 403, 0,
+3, 204, 200, 139, 403, 370, 45, 0,
+3, 200, 204, 205, 370, 403, 315, 0,
+3, 205, 201, 200, 315, 143, 370, 0,
+3, 201, 205, 206, 143, 315, 7, 0,
+3, 206, 202, 201, 7, 195, 143, 0,
+3, 202, 206, 207, 195, 7, 101, 0,
+3, 207, 203, 202, 101, 444, 195, 0,
+3, 143, 83, 144, 54, 1, 276, 0,
+3, 144, 204, 143, 276, 403, 54, 0,
+3, 204, 144, 145, 403, 276, 520, 0,
+3, 145, 205, 204, 520, 315, 403, 0,
+3, 205, 145, 146, 315, 520, 395, 0,
+3, 146, 206, 205, 395, 7, 315, 0,
+3, 206, 146, 147, 7, 395, 246, 0,
+3, 147, 207, 206, 246, 101, 7, 0,
+3, 147, 151, 212, 246, 384, 486, 0,
+3, 212, 208, 147, 486, 279, 246, 0,
+3, 208, 212, 213, 279, 486, 231, 0,
+3, 213, 209, 208, 231, 349, 279, 0,
+3, 209, 213, 214, 349, 231, 0, 0,
+3, 214, 210, 209, 0, 216, 349, 0,
+3, 210, 214, 211, 216, 0, 393, 0,
+3, 211, 211, 210, 393, 393, 216, 0,
+3, 151, 155, 215, 384, 83, 215, 0,
+3, 215, 212, 151, 215, 486, 384, 0,
+3, 212, 215, 216, 486, 215, 327, 0,
+3, 216, 213, 212, 327, 231, 486, 0,
+3, 213, 216, 217, 231, 327, 512, 0,
+3, 217, 214, 213, 512, 0, 231, 0,
+3, 214, 217, 211, 0, 512, 393, 0,
+3, 211, 211, 214, 393, 393, 0, 0,
+3, 155, 159, 218, 83, 297, 149, 0,
+3, 218, 215, 155, 149, 215, 83, 0,
+3, 215, 218, 219, 215, 149, 91, 0,
+3, 219, 216, 215, 91, 327, 215, 0,
+3, 216, 219, 220, 327, 91, 177, 0,
+3, 220, 217, 216, 177, 512, 327, 0,
+3, 217, 220, 211, 512, 177, 393, 0,
+3, 211, 211, 217, 393, 393, 512, 0,
+3, 159, 163, 221, 297, 317, 504, 0,
+3, 221, 218, 159, 504, 149, 297, 0,
+3, 218, 221, 222, 149, 504, 285, 0,
+3, 222, 219, 218, 285, 91, 149, 0,
+3, 219, 222, 223, 91, 285, 254, 0,
+3, 223, 220, 219, 254, 177, 91, 0,
+3, 220, 223, 211, 177, 254, 393, 0,
+3, 211, 211, 220, 393, 393, 177, 0,
+3, 163, 167, 224, 317, 459, 125, 0,
+3, 224, 221, 163, 125, 504, 317, 0,
+3, 221, 224, 225, 504, 125, 162, 0,
+3, 225, 222, 221, 162, 285, 504, 0,
+3, 222, 225, 226, 285, 162, 278, 0,
+3, 226, 223, 222, 278, 254, 285, 0,
+3, 223, 226, 211, 254, 278, 393, 0,
+3, 211, 211, 223, 393, 393, 254, 0,
+3, 167, 171, 227, 459, 426, 439, 0,
+3, 227, 224, 167, 439, 125, 459, 0,
+3, 224, 227, 228, 125, 439, 60, 0,
+3, 228, 225, 224, 60, 162, 125, 0,
+3, 225, 228, 229, 162, 60, 446, 0,
+3, 229, 226, 225, 446, 278, 162, 0,
+3, 226, 229, 211, 278, 446, 393, 0,
+3, 211, 211, 226, 393, 393, 278, 0,
+3, 171, 175, 230, 426, 87, 482, 0,
+3, 230, 227, 171, 482, 439, 426, 0,
+3, 227, 230, 231, 439, 482, 92, 0,
+3, 231, 228, 227, 92, 60, 439, 0,
+3, 228, 231, 232, 60, 92, 110, 0,
+3, 232, 229, 228, 110, 446, 60, 0,
+3, 229, 232, 211, 446, 110, 393, 0,
+3, 211, 211, 229, 393, 393, 446, 0,
+3, 175, 179, 233, 87, 501, 261, 0,
+3, 233, 230, 175, 261, 482, 87, 0,
+3, 230, 233, 234, 482, 261, 329, 0,
+3, 234, 231, 230, 329, 92, 482, 0,
+3, 231, 234, 235, 92, 329, 192, 0,
+3, 235, 232, 231, 192, 110, 92, 0,
+3, 232, 235, 211, 110, 192, 393, 0,
+3, 211, 211, 232, 393, 393, 110, 0,
+3, 179, 183, 236, 501, 105, 219, 0,
+3, 236, 233, 179, 219, 261, 501, 0,
+3, 233, 236, 237, 261, 219, 491, 0,
+3, 237, 234, 233, 491, 329, 261, 0,
+3, 234, 237, 238, 329, 491, 267, 0,
+3, 238, 235, 234, 267, 192, 329, 0,
+3, 235, 238, 211, 192, 267, 393, 0,
+3, 211, 211, 235, 393, 393, 192, 0,
+3, 183, 187, 239, 105, 356, 472, 0,
+3, 239, 236, 183, 472, 219, 105, 0,
+3, 236, 239, 240, 219, 472, 48, 0,
+3, 240, 237, 236, 48, 491, 219, 0,
+3, 237, 240, 241, 491, 48, 247, 0,
+3, 241, 238, 237, 247, 267, 491, 0,
+3, 238, 241, 211, 267, 247, 393, 0,
+3, 211, 211, 238, 393, 393, 267, 0,
+3, 187, 191, 242, 356, 17, 411, 0,
+3, 242, 239, 187, 411, 472, 356, 0,
+3, 239, 242, 243, 472, 411, 364, 0,
+3, 243, 240, 239, 364, 48, 472, 0,
+3, 240, 243, 244, 48, 364, 441, 0,
+3, 244, 241, 240, 441, 247, 48, 0,
+3, 241, 244, 211, 247, 441, 393, 0,
+3, 211, 211, 241, 393, 393, 247, 0,
+3, 191, 195, 245, 17, 335, 239, 0,
+3, 245, 242, 191, 239, 411, 17, 0,
+3, 242, 245, 246, 411, 239, 13, 0,
+3, 246, 243, 242, 13, 364, 411, 0,
+3, 243, 246, 247, 364, 13, 509, 0,
+3, 247, 244, 243, 509, 441, 364, 0,
+3, 244, 247, 211, 441, 509, 393, 0,
+3, 211, 211, 244, 393, 393, 441, 0,
+3, 195, 199, 248, 335, 475, 144, 0,
+3, 248, 245, 195, 144, 239, 335, 0,
+3, 245, 248, 249, 239, 144, 179, 0,
+3, 249, 246, 245, 179, 13, 239, 0,
+3, 246, 249, 250, 13, 179, 298, 0,
+3, 250, 247, 246, 298, 509, 13, 0,
+3, 247, 250, 211, 509, 298, 393, 0,
+3, 211, 211, 247, 393, 393, 509, 0,
+3, 199, 203, 251, 475, 444, 462, 0,
+3, 251, 248, 199, 462, 144, 475, 0,
+3, 248, 251, 252, 144, 462, 76, 0,
+3, 252, 249, 248, 76, 179, 144, 0,
+3, 249, 252, 253, 179, 76, 464, 0,
+3, 253, 250, 249, 464, 298, 179, 0,
+3, 250, 253, 211, 298, 464, 393, 0,
+3, 211, 211, 250, 393, 393, 298, 0,
+3, 203, 207, 254, 444, 101, 500, 0,
+3, 254, 251, 203, 500, 462, 444, 0,
+3, 251, 254, 255, 462, 500, 113, 0,
+3, 255, 252, 251, 113, 76, 462, 0,
+3, 252, 255, 256, 76, 113, 128, 0,
+3, 256, 253, 252, 128, 464, 76, 0,
+3, 253, 256, 211, 464, 128, 393, 0,
+3, 211, 211, 253, 393, 393, 464, 0,
+3, 207, 147, 208, 101, 246, 279, 0,
+3, 208, 254, 207, 279, 500, 101, 0,
+3, 254, 208, 209, 500, 279, 349, 0,
+3, 209, 255, 254, 349, 113, 500, 0,
+3, 255, 209, 210, 113, 349, 216, 0,
+3, 210, 256, 255, 216, 128, 113, 0,
+3, 256, 210, 211, 128, 216, 393, 0,
+3, 211, 211, 256, 393, 393, 128, 0,
+3, 257, 262, 263, 425, 244, 58, 0,
+3, 263, 258, 257, 58, 337, 425, 0,
+3, 258, 263, 264, 337, 58, 214, 0,
+3, 264, 259, 258, 214, 236, 337, 0,
+3, 259, 264, 265, 236, 214, 266, 0,
+3, 265, 260, 259, 266, 32, 236, 0,
+3, 260, 265, 266, 32, 266, 331, 0,
+3, 266, 261, 260, 331, 109, 32, 0,
+3, 262, 267, 268, 244, 233, 369, 0,
+3, 268, 263, 262, 369, 58, 244, 0,
+3, 263, 268, 269, 58, 369, 71, 0,
+3, 269, 264, 263, 71, 214, 58, 0,
+3, 264, 269, 270, 214, 71, 392, 0,
+3, 270, 265, 264, 392, 266, 214, 0,
+3, 265, 270, 271, 266, 392, 312, 0,
+3, 271, 266, 265, 312, 331, 266, 0,
+3, 267, 272, 273, 233, 12, 434, 0,
+3, 273, 268, 267, 434, 369, 233, 0,
+3, 268, 273, 274, 369, 434, 188, 0,
+3, 274, 269, 268, 188, 71, 369, 0,
+3, 269, 274, 275, 71, 188, 201, 0,
+3, 275, 270, 269, 201, 392, 71, 0,
+3, 270, 275, 276, 392, 201, 238, 0,
+3, 276, 271, 270, 238, 312, 392, 0,
+3, 272, 277, 278, 12, 142, 114, 0,
+3, 278, 273, 272, 114, 434, 12, 0,
+3, 273, 278, 279, 434, 114, 173, 0,
+3, 279, 274, 273, 173, 188, 434, 0,
+3, 274, 279, 280, 188, 173, 14, 0,
+3, 280, 275, 274, 14, 201, 188, 0,
+3, 275, 280, 281, 201, 14, 15, 0,
+3, 281, 276, 275, 15, 238, 201, 0,
+3, 277, 282, 283, 142, 407, 288, 0,
+3, 283, 278, 277, 288, 114, 142, 0,
+3, 278, 283, 284, 114, 288, 400, 0,
+3, 284, 279, 278, 400, 173, 114, 0,
+3, 279, 284, 285, 173, 400, 457, 0,
+3, 285, 280, 279, 457, 14, 173, 0,
+3, 280, 285, 286, 14, 457, 332, 0,
+3, 286, 281, 280, 332, 15, 14, 0,
+3, 282, 287, 288, 407, 194, 42, 0,
+3, 288, 283, 282, 42, 288, 407, 0,
+3, 283, 288, 289, 288, 42, 380, 0,
+3, 289, 284, 283, 380, 400, 288, 0,
+3, 284, 289, 290, 400, 380, 383, 0,
+3, 290, 285, 284, 383, 457, 400, 0,
+3, 285, 290, 291, 457, 383, 197, 0,
+3, 291, 286, 285, 197, 332, 457, 0,
+3, 287, 292, 293, 194, 321, 152, 0,
+3, 293, 288, 287, 152, 42, 194, 0,
+3, 288, 293, 294, 42, 152, 397, 0,
+3, 294, 289, 288, 397, 380, 42, 0,
+3, 289, 294, 295, 380, 397, 342, 0,
+3, 295, 290, 289, 342, 383, 380, 0,
+3, 290, 295, 296, 383, 342, 225, 0,
+3, 296, 291, 290, 225, 197, 383, 0,
+3, 292, 257, 258, 321, 425, 337, 0,
+3, 258, 293, 292, 337, 152, 321, 0,
+3, 293, 258, 259, 152, 337, 236, 0,
+3, 259, 294, 293, 236, 397, 152, 0,
+3, 294, 259, 260, 397, 236, 32, 0,
+3, 260, 295, 294, 32, 342, 397, 0,
+3, 295, 260, 261, 342, 32, 109, 0,
+3, 261, 296, 295, 109, 225, 342, 0,
+3, 261, 266, 301, 109, 331, 175, 0,
+3, 301, 297, 261, 175, 502, 109, 0,
+3, 297, 301, 302, 502, 175, 265, 0,
+3, 302, 298, 297, 265, 84, 502, 0,
+3, 298, 302, 303, 84, 265, 186, 0,
+3, 303, 299, 298, 186, 496, 84, 0,
+3, 299, 303, 304, 496, 186, 470, 0,
+3, 304, 300, 299, 470, 494, 496, 0,
+3, 266, 271, 305, 331, 312, 170, 0,
+3, 305, 301, 266, 170, 175, 331, 0,
+3, 301, 305, 306, 175, 170, 97, 0,
+3, 306, 302, 301, 97, 265, 175, 0,
+3, 302, 306, 307, 265, 97, 205, 0,
+3, 307, 303, 302, 205, 186, 265, 0,
+3, 303, 307, 308, 186, 205, 449, 0,
+3, 308, 304, 303, 449, 470, 186, 0,
+3, 271, 276, 309, 312, 238, 379, 0,
+3, 309, 305, 271, 379, 170, 312, 0,
+3, 305, 309, 310, 170, 379, 300, 0,
+3, 310, 306, 305, 300, 97, 170, 0,
+3, 306, 310, 311, 97, 300, 118, 0,
+3, 311, 307, 306, 118, 205, 97, 0,
+3, 307, 311, 312, 205, 118, 237, 0,
+3, 312, 308, 307, 237, 449, 205, 0,
+3, 276, 281, 313, 238, 15, 199, 0,
+3, 313, 309, 276, 199, 379, 238, 0,
+3, 309, 313, 314, 379, 199, 94, 0,
+3, 314, 310, 309, 94, 300, 379, 0,
+3, 310, 314, 315, 300, 94, 421, 0,
+3, 315, 311, 310, 421, 118, 300, 0,
+3, 311, 315, 316, 118, 421, 31, 0,
+3, 316, 312, 311, 31, 237, 118, 0,
+3, 281, 286, 317, 15, 332, 367, 0,
+3, 317, 313, 281, 367, 199, 15, 0,
+3, 313, 317, 318, 199, 367, 529, 0,
+3, 318, 314, 313, 529, 94, 199, 0,
+3, 314, 318, 319, 94, 529, 185, 0,
+3, 319, 315, 314, 185, 421, 94, 0,
+3, 315, 319, 320, 421, 185, 89, 0,
+3, 320, 316, 315, 89, 31, 421, 0,
+3, 286, 291, 321, 332, 197, 172, 0,
+3, 321, 317, 286, 172, 367, 332, 0,
+3, 317, 321, 322, 367, 172, 209, 0,
+3, 322, 318, 317, 209, 529, 367, 0,
+3, 318, 322, 323, 529, 209, 429, 0,
+3, 323, 319, 318, 429, 185, 529, 0,
+3, 319, 323, 324, 185, 429, 112, 0,
+3, 324, 320, 319, 112, 89, 185, 0,
+3, 291, 296, 325, 197, 225, 451, 0,
+3, 325, 321, 291, 451, 172, 197, 0,
+3, 321, 325, 326, 172, 451, 66, 0,
+3, 326, 322, 321, 66, 209, 172, 0,
+3, 322, 326, 327, 209, 66, 176, 0,
+3, 327, 323, 322, 176, 429, 209, 0,
+3, 323, 327, 328, 429, 176, 155, 0,
+3, 328, 324, 323, 155, 112, 429, 0,
+3, 296, 261, 297, 225, 109, 502, 0,
+3, 297, 325, 296, 502, 451, 225, 0,
+3, 325, 297, 298, 451, 502, 84, 0,
+3, 298, 326, 325, 84, 66, 451, 0,
+3, 326, 298, 299, 66, 84, 496, 0,
+3, 299, 327, 326, 496, 176, 66, 0,
+3, 327, 299, 300, 176, 496, 494, 0,
+3, 300, 328, 327, 494, 155, 176, 0,
+3, 329, 334, 335, 3, 355, 122, 0,
+3, 335, 330, 329, 122, 518, 3, 0,
+3, 330, 335, 336, 518, 122, 111, 0,
+3, 336, 331, 330, 111, 213, 518, 0,
+3, 331, 336, 337, 213, 111, 473, 0,
+3, 337, 332, 331, 473, 468, 213, 0,
+3, 332, 337, 338, 468, 473, 521, 0,
+3, 338, 333, 332, 521, 346, 468, 0,
+3, 334, 339, 340, 355, 61, 414, 0,
+3, 340, 335, 334, 414, 122, 355, 0,
+3, 335, 340, 341, 122, 414, 413, 0,
+3, 341, 336, 335, 413, 111, 122, 0,
+3, 336, 341, 342, 111, 413, 204, 0,
+3, 342, 337, 336, 204, 473, 111, 0,
+3, 337, 342, 343, 473, 204, 217, 0,
+3, 343, 338, 337, 217, 521, 473, 0,
+3, 339, 344, 345, 61, 55, 100, 0,
+3, 345, 340, 339, 100, 414, 61, 0,
+3, 340, 345, 346, 414, 100, 399, 0,
+3, 346, 341, 340, 399, 413, 414, 0,
+3, 341, 346, 347, 413, 399, 326, 0,
+3, 347, 342, 341, 326, 204, 413, 0,
+3, 342, 347, 348, 204, 326, 221, 0,
+3, 348, 343, 342, 221, 217, 204, 0,
+3, 344, 349, 350, 55, 508, 477, 0,
+3, 350, 345, 344, 477, 100, 55, 0,
+3, 345, 350, 351, 100, 477, 292, 0,
+3, 351, 346, 345, 292, 399, 100, 0,
+3, 346, 351, 352, 399, 292, 73, 0,
+3, 352, 347, 346, 73, 326, 399, 0,
+3, 347, 352, 353, 326, 73, 362, 0,
+3, 353, 348, 347, 362, 221, 326, 0,
+3, 349, 354, 355, 508, 365, 262, 0,
+3, 355, 350, 349, 262, 477, 508, 0,
+3, 350, 355, 356, 477, 262, 93, 0,
+3, 356, 351, 350, 93, 292, 477, 0,
+3, 351, 356, 357, 292, 93, 318, 0,
+3, 357, 352, 351, 318, 73, 292, 0,
+3, 352, 357, 358, 73, 318, 163, 0,
+3, 358, 353, 352, 163, 362, 73, 0,
+3, 354, 359, 360, 365, 140, 340, 0,
+3, 360, 355, 354, 340, 262, 365, 0,
+3, 355, 360, 361, 262, 340, 505, 0,
+3, 361, 356, 355, 505, 93, 262, 0,
+3, 356, 361, 362, 93, 505, 499, 0,
+3, 362, 357, 356, 499, 318, 93, 0,
+3, 357, 362, 363, 318, 499, 159, 0,
+3, 363, 358, 357, 159, 163, 318, 0,
+3, 359, 364, 365, 140, 510, 68, 0,
+3, 365, 360, 359, 68, 340, 140, 0,
+3, 360, 365, 366, 340, 68, 167, 0,
+3, 366, 361, 360, 167, 505, 340, 0,
+3, 361, 366, 367, 505, 167, 245, 0,
+3, 367, 362, 361, 245, 499, 505, 0,
+3, 362, 367, 368, 499, 245, 437, 0,
+3, 368, 363, 362, 437, 159, 499, 0,
+3, 364, 329, 330, 510, 3, 518, 0,
+3, 330, 365, 364, 518, 68, 510, 0,
+3, 365, 330, 331, 68, 518, 213, 0,
+3, 331, 366, 365, 213, 167, 68, 0,
+3, 366, 331, 332, 167, 213, 468, 0,
+3, 332, 367, 366, 468, 245, 167, 0,
+3, 367, 332, 333, 245, 468, 346, 0,
+3, 333, 368, 367, 346, 437, 245, 0,
+3, 333, 338, 373, 346, 521, 79, 0,
+3, 373, 369, 333, 79, 286, 346, 0,
+3, 369, 373, 374, 286, 79, 77, 0,
+3, 374, 370, 369, 77, 22, 286, 0,
+3, 370, 374, 375, 22, 77, 523, 0,
+3, 375, 371, 370, 523, 330, 22, 0,
+3, 371, 375, 376, 330, 523, 259, 0,
+3, 376, 372, 371, 259, 338, 330, 0,
+3, 338, 343, 377, 521, 217, 207, 0,
+3, 377, 373, 338, 207, 79, 521, 0,
+3, 373, 377, 378, 79, 207, 471, 0,
+3, 378, 374, 373, 471, 77, 79, 0,
+3, 374, 378, 379, 77, 471, 198, 0,
+3, 379, 375, 374, 198, 523, 77, 0,
+3, 375, 379, 380, 523, 198, 366, 0,
+3, 380, 376, 375, 366, 259, 523, 0,
+3, 343, 348, 381, 217, 221, 516, 0,
+3, 381, 377, 343, 516, 207, 217, 0,
+3, 377, 381, 382, 207, 516, 250, 0,
+3, 382, 378, 377, 250, 471, 207, 0,
+3, 378, 382, 383, 471, 250, 240, 0,
+3, 383, 379, 378, 240, 198, 471, 0,
+3, 379, 383, 384, 198, 240, 381, 0,
+3, 384, 380, 379, 381, 366, 198, 0,
+3, 348, 353, 385, 221, 362, 230, 0,
+3, 385, 381, 348, 230, 516, 221, 0,
+3, 381, 385, 386, 516, 230, 303, 0,
+3, 386, 382, 381, 303, 250, 516, 0,
+3, 382, 386, 387, 250, 303, 10, 0,
+3, 387, 383, 382, 10, 240, 250, 0,
+3, 383, 387, 388, 240, 10, 283, 0,
+3, 388, 384, 383, 283, 381, 240, 0,
+3, 353, 358, 389, 362, 163, 282, 0,
+3, 389, 385, 353, 282, 230, 362, 0,
+3, 385, 389, 390, 230, 282, 35, 0,
+3, 390, 386, 385, 35, 303, 230, 0,
+3, 386, 390, 391, 303, 35, 243, 0,
+3, 391, 387, 386, 243, 10, 303, 0,
+3, 387, 391, 392, 10, 243, 368, 0,
+3, 392, 388, 387, 368, 283, 10, 0,
+3, 358, 363, 393, 163, 159, 296, 0,
+3, 393, 389, 358, 296, 282, 163, 0,
+3, 389, 393, 394, 282, 296, 160, 0,
+3, 394, 390, 389, 160, 35, 282, 0,
+3, 390, 394, 395, 35, 160, 323, 0,
+3, 395, 391, 390, 323, 243, 35, 0,
+3, 391, 395, 396, 243, 323, 280, 0,
+3, 396, 392, 391, 280, 368, 243, 0,
+3, 363, 368, 397, 159, 437, 275, 0,
+3, 397, 393, 363, 275, 296, 159, 0,
+3, 393, 397, 398, 296, 275, 133, 0,
+3, 398, 394, 393, 133, 160, 296, 0,
+3, 394, 398, 399, 160, 133, 344, 0,
+3, 399, 395, 394, 344, 323, 160, 0,
+3, 395, 399, 400, 323, 344, 108, 0,
+3, 400, 396, 395, 108, 280, 323, 0,
+3, 368, 333, 369, 437, 346, 286, 0,
+3, 369, 397, 368, 286, 275, 437, 0,
+3, 397, 369, 370, 275, 286, 22, 0,
+3, 370, 398, 397, 22, 133, 275, 0,
+3, 398, 370, 371, 133, 22, 330, 0,
+3, 371, 399, 398, 330, 344, 133, 0,
+3, 399, 371, 372, 344, 330, 338, 0,
+3, 372, 400, 399, 338, 108, 344, 0,
+3, 401, 401, 406, 235, 235, 189, 0,
+3, 406, 402, 401, 189, 40, 235, 0,
+3, 402, 406, 407, 40, 189, 306, 0,
+3, 407, 403, 402, 306, 119, 40, 0,
+3, 403, 407, 408, 119, 306, 202, 0,
+3, 408, 404, 403, 202, 443, 119, 0,
+3, 404, 408, 409, 443, 202, 241, 0,
+3, 409, 405, 404, 241, 75, 443, 0,
+3, 401, 401, 410, 235, 235, 263, 0,
+3, 410, 406, 401, 263, 189, 235, 0,
+3, 406, 410, 411, 189, 263, 196, 0,
+3, 411, 407, 406, 196, 306, 189, 0,
+3, 407, 411, 412, 306, 196, 281, 0,
+3, 412, 408, 407, 281, 202, 306, 0,
+3, 408, 412, 413, 202, 281, 121, 0,
+3, 413, 409, 408, 121, 241, 202, 0,
+3, 401, 401, 414, 235, 235, 479, 0,
+3, 414, 410, 401, 479, 263, 235, 0,
+3, 410, 414, 415, 263, 479, 36, 0,
+3, 415, 411, 410, 36, 196, 263, 0,
+3, 411, 415, 416, 196, 36, 436, 0,
+3, 416, 412, 411, 436, 281, 196, 0,
+3, 412, 416, 417, 281, 436, 351, 0,
+3, 417, 413, 412, 351, 121, 281, 0,
+3, 401, 401, 418, 235, 235, 90, 0,
+3, 418, 414, 401, 90, 479, 235, 0,
+3, 414, 418, 419, 479, 90, 361, 0,
+3, 419, 415, 414, 361, 36, 479, 0,
+3, 415, 419, 420, 36, 361, 376, 0,
+3, 420, 416, 415, 376, 436, 36, 0,
+3, 416, 420, 421, 436, 376, 412, 0,
+3, 421, 417, 416, 412, 351, 436, 0,
+3, 401, 401, 422, 235, 235, 52, 0,
+3, 422, 418, 401, 52, 90, 235, 0,
+3, 418, 422, 423, 90, 52, 21, 0,
+3, 423, 419, 418, 21, 361, 90, 0,
+3, 419, 423, 424, 361, 21, 158, 0,
+3, 424, 420, 419, 158, 376, 361, 0,
+3, 420, 424, 425, 376, 158, 39, 0,
+3, 425, 421, 420, 39, 412, 376, 0,
+3, 401, 401, 426, 235, 235, 424, 0,
+3, 426, 422, 401, 424, 52, 235, 0,
+3, 422, 426, 427, 52, 424, 373, 0,
+3, 427, 423, 422, 373, 21, 52, 0,
+3, 423, 427, 428, 21, 373, 375, 0,
+3, 428, 424, 423, 375, 158, 21, 0,
+3, 424, 428, 429, 158, 375, 249, 0,
+3, 429, 425, 424, 249, 39, 158, 0,
+3, 401, 401, 430, 235, 235, 432, 0,
+3, 430, 426, 401, 432, 424, 235, 0,
+3, 426, 430, 431, 424, 432, 229, 0,
+3, 431, 427, 426, 229, 373, 424, 0,
+3, 427, 431, 432, 373, 229, 65, 0,
+3, 432, 428, 427, 65, 375, 373, 0,
+3, 428, 432, 433, 375, 65, 506, 0,
+3, 433, 429, 428, 506, 249, 375, 0,
+3, 401, 401, 434, 235, 235, 302, 0,
+3, 434, 430, 401, 302, 432, 235, 0,
+3, 430, 434, 435, 432, 302, 96, 0,
+3, 435, 431, 430, 96, 229, 432, 0,
+3, 431, 435, 436, 229, 96, 169, 0,
+3, 436, 432, 431, 169, 65, 229, 0,
+3, 432, 436, 437, 65, 169, 59, 0,
+3, 437, 433, 432, 59, 506, 65, 0,
+3, 401, 401, 438, 235, 235, 452, 0,
+3, 438, 434, 401, 452, 302, 235, 0,
+3, 434, 438, 439, 302, 452, 30, 0,
+3, 439, 435, 434, 30, 96, 302, 0,
+3, 435, 439, 440, 96, 30, 460, 0,
+3, 440, 436, 435, 460, 169, 96, 0,
+3, 436, 440, 441, 169, 460, 498, 0,
+3, 441, 437, 436, 498, 59, 169, 0,
+3, 401, 401, 442, 235, 235, 525, 0,
+3, 442, 438, 401, 525, 452, 235, 0,
+3, 438, 442, 443, 452, 525, 456, 0,
+3, 443, 439, 438, 456, 30, 452, 0,
+3, 439, 443, 444, 30, 456, 9, 0,
+3, 444, 440, 439, 9, 460, 30, 0,
+3, 440, 444, 445, 460, 9, 388, 0,
+3, 445, 441, 440, 388, 498, 460, 0,
+3, 401, 401, 446, 235, 235, 212, 0,
+3, 446, 442, 401, 212, 525, 235, 0,
+3, 442, 446, 447, 525, 212, 299, 0,
+3, 447, 443, 442, 299, 456, 525, 0,
+3, 443, 447, 448, 456, 299, 166, 0,
+3, 448, 444, 443, 166, 9, 456, 0,
+3, 444, 448, 449, 9, 166, 72, 0,
+3, 449, 445, 444, 72, 388, 9, 0,
+3, 401, 401, 450, 235, 235, 107, 0,
+3, 450, 446, 401, 107, 212, 235, 0,
+3, 446, 450, 451, 212, 107, 82, 0,
+3, 451, 447, 446, 82, 299, 212, 0,
+3, 447, 451, 452, 299, 82, 391, 0,
+3, 452, 448, 447, 391, 166, 299, 0,
+3, 448, 452, 453, 166, 391, 139, 0,
+3, 453, 449, 448, 139, 72, 166, 0,
+3, 401, 401, 454, 235, 235, 70, 0,
+3, 454, 450, 401, 70, 107, 235, 0,
+3, 450, 454, 455, 107, 70, 51, 0,
+3, 455, 451, 450, 51, 82, 107, 0,
+3, 451, 455, 456, 82, 51, 178, 0,
+3, 456, 452, 451, 178, 391, 82, 0,
+3, 452, 456, 457, 391, 178, 57, 0,
+3, 457, 453, 452, 57, 139, 391, 0,
+3, 401, 401, 458, 235, 235, 442, 0,
+3, 458, 454, 401, 442, 70, 235, 0,
+3, 454, 458, 459, 70, 442, 387, 0,
+3, 459, 455, 454, 387, 51, 70, 0,
+3, 455, 459, 460, 51, 387, 389, 0,
+3, 460, 456, 455, 389, 178, 51, 0,
+3, 456, 460, 461, 178, 389, 264, 0,
+3, 461, 457, 456, 264, 57, 178, 0,
+3, 401, 401, 462, 235, 235, 450, 0,
+3, 462, 458, 401, 450, 442, 235, 0,
+3, 458, 462, 463, 442, 450, 253, 0,
+3, 463, 459, 458, 253, 387, 442, 0,
+3, 459, 463, 464, 387, 253, 86, 0,
+3, 464, 460, 459, 86, 389, 387, 0,
+3, 460, 464, 465, 389, 86, 526, 0,
+3, 465, 461, 460, 526, 264, 389, 0,
+3, 401, 401, 402, 235, 235, 40, 0,
+3, 402, 462, 401, 40, 450, 235, 0,
+3, 462, 402, 403, 450, 40, 119, 0,
+3, 403, 463, 462, 119, 253, 450, 0,
+3, 463, 403, 404, 253, 119, 443, 0,
+3, 404, 464, 463, 443, 86, 253, 0,
+3, 464, 404, 405, 86, 443, 75, 0,
+3, 405, 465, 464, 75, 526, 86, 0,
+3, 405, 409, 470, 75, 241, 519, 0,
+3, 470, 466, 405, 519, 226, 75, 0,
+3, 466, 470, 471, 226, 519, 406, 0,
+3, 471, 467, 466, 406, 98, 226, 0,
+3, 467, 471, 472, 98, 406, 232, 0,
+3, 472, 468, 467, 232, 43, 98, 0,
+3, 468, 472, 473, 43, 232, 345, 0,
+3, 473, 469, 468, 345, 372, 43, 0,
+3, 409, 413, 474, 241, 121, 227, 0,
+3, 474, 470, 409, 227, 519, 241, 0,
+3, 470, 474, 475, 519, 227, 469, 0,
+3, 475, 471, 470, 469, 406, 519, 0,
+3, 471, 475, 476, 406, 469, 258, 0,
+3, 476, 472, 471, 258, 232, 406, 0,
+3, 472, 476, 477, 232, 258, 271, 0,
+3, 477, 473, 472, 271, 345, 232, 0,
+3, 413, 417, 478, 121, 351, 157, 0,
+3, 478, 474, 413, 157, 227, 121, 0,
+3, 474, 478, 479, 227, 157, 80, 0,
+3, 479, 475, 474, 80, 469, 227, 0,
+3, 475, 479, 480, 469, 80, 489, 0,
+3, 480, 476, 475, 489, 258, 469, 0,
+3, 476, 480, 481, 258, 489, 277, 0,
+3, 481, 477, 476, 277, 271, 258, 0,
+3, 417, 421, 482, 351, 412, 153, 0,
+3, 482, 478, 417, 153, 157, 351, 0,
+3, 478, 482, 483, 157, 153, 324, 0,
+3, 483, 479, 478, 324, 80, 157, 0,
+3, 479, 483, 484, 80, 324, 339, 0,
+3, 484, 480, 479, 339, 489, 80, 0,
+3, 480, 484, 485, 489, 339, 88, 0,
+3, 485, 481, 480, 88, 277, 489, 0,
+3, 421, 425, 486, 412, 39, 6, 0,
+3, 486, 482, 421, 6, 153, 412, 0,
+3, 482, 486, 487, 153, 6, 8, 0,
+3, 487, 483, 482, 8, 324, 153, 0,
+3, 483, 487, 488, 324, 8, 16, 0,
+3, 488, 484, 483, 16, 339, 324, 0,
+3, 484, 488, 489, 339, 16, 289, 0,
+3, 489, 485, 484, 289, 88, 339, 0,
+3, 425, 429, 490, 39, 249, 99, 0,
+3, 490, 486, 425, 99, 6, 39, 0,
+3, 486, 490, 491, 6, 99, 200, 0,
+3, 491, 487, 486, 200, 8, 6, 0,
+3, 487, 491, 492, 8, 200, 150, 0,
+3, 492, 488, 487, 150, 16, 8, 0,
+3, 488, 492, 493, 16, 150, 493, 0,
+3, 493, 489, 488, 493, 289, 16, 0,
+3, 429, 433, 494, 249, 506, 291, 0,
+3, 494, 490, 429, 291, 99, 249, 0,
+3, 490, 494, 495, 99, 291, 64, 0,
+3, 495, 491, 490, 64, 200, 99, 0,
+3, 491, 495, 496, 200, 64, 19, 0,
+3, 496, 492, 491, 19, 150, 200, 0,
+3, 492, 496, 497, 150, 19, 433, 0,
+3, 497, 493, 492, 433, 493, 150, 0,
+3, 433, 437, 498, 506, 59, 203, 0,
+3, 498, 494, 433, 203, 291, 506, 0,
+3, 494, 498, 499, 291, 203, 374, 0,
+3, 499, 495, 494, 374, 64, 291, 0,
+3, 495, 499, 500, 64, 374, 307, 0,
+3, 500, 496, 495, 307, 19, 64, 0,
+3, 496, 500, 501, 19, 307, 358, 0,
+3, 501, 497, 496, 358, 433, 19, 0,
+3, 437, 441, 502, 59, 498, 256, 0,
+3, 502, 498, 437, 256, 203, 59, 0,
+3, 498, 502, 503, 203, 256, 132, 0,
+3, 503, 499, 498, 132, 374, 203, 0,
+3, 499, 503, 504, 374, 132, 492, 0,
+3, 504, 500, 499, 492, 307, 374, 0,
+3, 500, 504, 505, 307, 492, 67, 0,
+3, 505, 501, 500, 67, 358, 307, 0,
+3, 441, 445, 506, 498, 388, 487, 0,
+3, 506, 502, 441, 487, 256, 498, 0,
+3, 502, 506, 507, 256, 487, 206, 0,
+3, 507, 503, 502, 206, 132, 256, 0,
+3, 503, 507, 508, 132, 206, 515, 0,
+3, 508, 504, 503, 515, 492, 132, 0,
+3, 504, 508, 509, 492, 515, 527, 0,
+3, 509, 505, 504, 527, 67, 492, 0,
+3, 445, 449, 510, 388, 72, 423, 0,
+3, 510, 506, 445, 423, 487, 388, 0,
+3, 506, 510, 511, 487, 423, 352, 0,
+3, 511, 507, 506, 352, 206, 487, 0,
+3, 507, 511, 512, 206, 352, 224, 0,
+3, 512, 508, 507, 224, 515, 206, 0,
+3, 508, 512, 513, 515, 224, 2, 0,
+3, 513, 509, 508, 2, 527, 515, 0,
+3, 449, 453, 514, 72, 139, 418, 0,
+3, 514, 510, 449, 418, 423, 72, 0,
+3, 510, 514, 515, 423, 418, 341, 0,
+3, 515, 511, 510, 341, 352, 423, 0,
+3, 511, 515, 516, 352, 341, 359, 0,
+3, 516, 512, 511, 359, 224, 352, 0,
+3, 512, 516, 517, 224, 359, 360, 0,
+3, 517, 513, 512, 360, 2, 224, 0,
+3, 453, 457, 518, 139, 57, 24, 0,
+3, 518, 514, 453, 24, 418, 139, 0,
+3, 514, 518, 519, 418, 24, 25, 0,
+3, 519, 515, 514, 25, 341, 418, 0,
+3, 515, 519, 520, 341, 25, 41, 0,
+3, 520, 516, 515, 41, 359, 341, 0,
+3, 516, 520, 521, 359, 41, 314, 0,
+3, 521, 517, 516, 314, 360, 359, 0,
+3, 457, 461, 522, 57, 264, 120, 0,
+3, 522, 518, 457, 120, 24, 57, 0,
+3, 518, 522, 523, 24, 120, 223, 0,
+3, 523, 519, 518, 223, 25, 24, 0,
+3, 519, 523, 524, 25, 223, 171, 0,
+3, 524, 520, 519, 171, 41, 25, 0,
+3, 520, 524, 525, 41, 171, 514, 0,
+3, 525, 521, 520, 514, 314, 41, 0,
+3, 461, 465, 526, 264, 526, 316, 0,
+3, 526, 522, 461, 316, 120, 264, 0,
+3, 522, 526, 527, 120, 316, 85, 0,
+3, 527, 523, 522, 85, 223, 120, 0,
+3, 523, 527, 528, 223, 85, 50, 0,
+3, 528, 524, 523, 50, 171, 223, 0,
+3, 524, 528, 529, 171, 50, 454, 0,
+3, 529, 525, 524, 454, 514, 171, 0,
+3, 465, 405, 466, 526, 75, 226, 0,
+3, 466, 526, 465, 226, 316, 526, 0,
+3, 526, 466, 467, 316, 226, 98, 0,
+3, 467, 527, 526, 98, 85, 316, 0,
+3, 527, 467, 468, 85, 98, 43, 0,
+3, 468, 528, 527, 43, 50, 85, 0,
+3, 528, 468, 469, 50, 43, 372, 0,
+3, 469, 529, 528, 372, 454, 50, 0
+};
+
+
+const int strip_vertices[] = {
+508, 508, 504, 509, 504, 505, 500, 501, 496, 497, 492, 493, 488, 489, 484, 485, 480, 481,
476, 477, 472, 473, -1,
+476, 475, 480, 479, 484, 483, 488, 487, 492, 491, 496, 495, 500, 499, 504, 499, 503, 498,
502, 437, 441, -1,
+527, 526, 467, 466, 471, 470, 475, 474, 479, 478, 483, 482, 487, 486, 491, 490, 495, 494,
499, 494, 498, -1,
+490, 490, 425, 486, 421, 482, 417, 478, 413, 474, 409, 470, 405, 466, 465, 526, 465, 461,
460, 456, 455, 451, -1,
+405, 465, 464, 460, 459, 455, 454, 450, -1,
+455, 451, 450, 446, 450, 401, 454, 458, 459, 463, 464, 404, 405, 404, 409, 408, 413, 412,
417, 416, 421, 420, -1,
+421, 420, 425, 420, 424, 419, 423, 418, 422, 418, 401, 414, 410, 415, 411, 416, 411, 412,
407, 408, 403, 404, 403, 463, -1,
+418, 418, 414, 419, 415, 420, 416, -1,
+407, 403, 402, 462, -1,
+403, 463, 462, 458, 462, 401, 402, 406, 407, 406, 411, 406, 410, 401, -1,
+494, 494, 498, 433, 437, 432, 436, 431, 435, 430, 434, 430, 401, 426, 422, 427, 423, 428,
424, 429, 425, 490, -1,
+430, 430, 426, 431, 427, 432, 428, 433, 429, 494, 490, -1,
+437, 437, 441, 436, 440, 435, 439, 434, 438, 401, 442, 446, 447, 451, 452, 456, 457, 461,
522, 526, 527, -1,
+452, 448, 447, -1,
+510, 445, 449, 444, 448, 443, 447, 443, 442, 443, 438, 443, 439, 444, 440, 445, 441, 506,
502, 507, 503, -1,
+510, 506, 445, -1,
+507, 506, 511, 510, 515, 510, 514, 449, 453, 448, 453, 452, 457, -1,
+527, 523, 522, 518, 457, 518, 453, 518, 514, 519, 515, -1,
+523, 519, 518, -1,
+504, 503, 508, 507, 512, 511, 516, 515, 520, 519, 524, 523, 528, 527, 468, 467, 472, 471,
476, 475, -1,
+472, 473, 468, 469, 528, 529, 524, 525, 520, 521, 516, 517, 512, 513, 508, 509, -1,
+211, 211, 214, 210, 209, -1,
+212, 215, 216, 219, 220, 223, 220, 211, 217, 214, 213, 209, 213, 208, 212, 147, -1,
+220, 217, 216, 213, 212, -1,
+251, 251, 248, 252, 249, 253, 250, 253, 211, 256, 210, 255, 209, 254, 208, 207, 147, 206,
147, 146, 147, 151, 212, 215, -1,
+206, 206, 202, 207, 203, 254, 251, 255, 252, 256, 253, -1,
+223, 223, 222, 219, 218, 215, 155, 151, 150, 146, 145, 146, 205, 206, 201, 202, 197, 202,
198, 203, 199, 251, 248, -1,
+145, 149, 150, 154, 155, 159, 218, 221, 222, 225, 226, 229, -1,
+204, 204, 145, 144, 149, 148, 149, 153, 154, 158, 159, 163, 221, 224, 225, 228, 229, 232,
229, 211, 226, 223, 222, -1,
+224, 224, 167, 163, 162, 158, 157, 153, 152, 148, 87, 148, 83, 144, 143, 204, 139, 200,
135, 196, 131, 192, -1,
+82, 83, 142, 143, 138, 139, 134, 135, 130, 131, 126, 127, 122, 123, 118, 123, 119, 184,
180, 185, 181, -1,
+81, 82, 141, 142, 137, 138, 133, 134, 129, 130, 125, 126, 121, 122, 117, 118, 113, 114,
109, 110, -1,
+80, 81, 140, 141, 136, 137, 132, 133, 128, 129, 124, 125, 120, 121, 116, 117, 112, 113,
108, 109, -1,
+4, 80, 79, 140, 74, 136, 69, 132, 64, 128, 59, 124, 54, 120, 49, 116, 44, 112, 39, 108,
-1,
+79, 79, 73, 74, 68, 69, 63, 64, 58, 59, 53, 54, 48, 49, 48, 43, 42, 37, 36, 31, 30, 31,
25, -1,
+42, 42, 48, 47, 53, 52, 58, 57, 63, 62, 68, 67, 73, 72, 78, 77, 3, 2, 8, 7, 13, -1,
+36, 36, 42, 41, 47, 46, 52, 51, 57, 56, 62, 61, 67, 66, 72, 71, 77, 76, 2, 1, 7, -1,
+66, 66, 60, 61, 55, 56, 50, 51, 45, 46, 40, 41, 35, 36, 30, -1,
+31, 31, 25, 26, 20, 21, 15, 16, 10, 11, 5, 6, 0, 1, 75, 76, 70, 71, 65, 66, 60, -1,
+1, 1, 7, 6, 12, 11, 17, 16, 22, 21, 27, 26, 32, 31, 32, 37, 38, 43, 44, 49, -1,
+7, 7, 13, 12, 18, 17, 23, 22, 28, 27, 33, 32, 33, 38, -1,
+44, 44, 38, 39, 33, 34, 28, 29, 23, 24, 18, 19, 13, 14, 8, 9, 3, 4, 78, 79, 73, -1,
+39, 108, 34, 104, 29, 100, 24, 96, 19, 92, 14, 88, 9, 84, 4, 84, 80, 85, 81, 86, 81, 82,
-1,
+108, 109, 104, 105, 100, 101, 96, 97, 92, 93, 88, 89, 84, 85, -1,
+109, 110, 105, 106, 101, 102, 97, 98, 93, 94, 89, 90, 85, 86, -1,
+118, 119, 114, 115, 110, 111, 106, 107, 102, 103, 98, 99, 94, 95, 90, 91, 86, 87, 82, 83,
-1,
+111, 115, 176, -1,
+107, 111, 172, 176, 177, -1,
+103, 107, 168, 172, 173, 177, 178, -1,
+99, 103, 164, 168, 169, 173, 174, 178, 179, -1,
+95, 99, 160, 164, 165, 169, 170, 174, 175, 179, 233, -1,
+91, 95, 156, 160, 161, 165, 166, 170, 171, 175, 230, 233, 234, -1,
+87, 91, 152, 156, 157, 161, 162, 166, 167, 171, 227, 230, 231, 234, 235, 234, 238, 234,
237, 233, 236, 179, -1,
+185, 185, 181, 186, 182, 187, 183, 239, 236, 240, 237, 241, 238, 211, 235, 232, 231, 228,
227, 224, 167, -1,
+236, 179, 183, 178, 182, 177, 181, 176, 180, 115, 119, -1,
+131, 192, 127, 188, 123, 188, 184, 189, 185, 190, 186, 191, 187, 242, 239, 243, 240, 244,
241, 244, 211, 247, -1,
+192, 192, 188, 193, 189, 194, 190, 195, 191, 245, 242, 246, 243, 247, 244, -1,
+211, 247, 250, 246, 249, 245, 248, 195, 199, 194, 198, 193, 197, 192, 197, 196, 201, 200,
205, 204, 145, -1,
+393, 393, 394, 398, 399, 371, -1,
+399, 395, 394, -1,
+363, 363, 393, 397, 398, 370, 371, 375, -1,
+379, 375, 374, 370, 369, 397, 368, 363, 362, -1,
+396, 395, 400, 399, 372, 371, 376, 375, 380, 379, 384, 383, 388, 387, 392, 391, 396, 391,
395, 390, 394, -1,
+374, 378, 379, 378, 383, 382, 387, 386, 391, 386, 390, 385, 389, 353, 358, 352, 357, 351,
356, 350, 355, -1,
+341, 341, 347, 346, 352, 346, 351, 345, 350, -1,
+335, 334, 340, 339, 345, 344, 350, 349, 355, 354, -1,
+390, 390, 394, 389, 393, 358, 363, 357, 362, 356, 361, 355, 360, 354, 360, 359, 365, 364,
330, 329, 335, 334, -1,
+345, 346, 340, 341, 335, 336, 330, 331, 365, 366, 360, 366, 361, 367, 362, 367, 368, 333,
369, 373, 374, 378, -1,
+353, 353, 348, 385, 381, 386, 381, 382, 377, 378, 377, 373, 338, 333, 332, 367, 332, 366,
332, 331, 337, 336, 342, 341, 347, -1,
+332, 337, 338, 343, 377, 343, 381, 343, 348, 342, 348, 347, 353, 352, -1,
+337, 342, 343, -1,
+314, 314, 319, 318, 323, 322, 323, 327, -1,
+309, 309, 314, 313, 318, 317, 322, 321, 322, 326, 327, 299, -1,
+271, 271, 309, 276, 313, 281, 317, 286, 321, 291, 321, 325, 326, 298, 299, 303, -1,
+265, 265, 271, 270, 276, 275, 281, 280, 286, 285, 291, 290, 291, 296, 325, 297, 298, 302,
303, 307, -1,
+259, 259, 265, 264, 270, 269, 275, 274, 280, 279, 285, 284, 290, 289, 290, 295, 296, 261,
297, 301, 302, 306, 307, 311, -1,
+293, 293, 259, 258, 264, 263, 269, 268, 274, 273, 279, 278, 284, 283, 289, 288, 289, 294,
295, 260, 261, 266, -1,
+309, 305, 271, 266, 265, 260, 259, 294, 293, 288, 287, 288, 282, 283, 277, 278, 272, 273,
267, 268, 262, -1,
+268, 268, 262, 263, 257, 258, 292, 293, 287, -1,
+261, 266, 301, 305, 306, 310, 311, 315, 316, 320, -1,
+316, 316, 311, 312, 307, 308, 303, 304, 299, 300, 327, 328, 323, 324, 319, 320, 319, 315,
314, 310, 309, 305, -1
+};
+
+
+const int strip_normals[] = {
+515, 515, 492, 527, 492, 67, 307, 358, 19, 433, 150, 493, 16, 289, 339, 88, 489, 277,
258, 271, 232, 345, -1,
+258, 469, 489, 80, 339, 324, 16, 8, 150, 200, 19, 64, 307, 374, 492, 374, 132, 203, 256,
59, 498, -1,
+85, 316, 98, 226, 406, 519, 469, 227, 80, 157, 324, 153, 8, 6, 200, 99, 64, 291, 374,
291, 203, -1,
+99, 99, 39, 6, 412, 153, 351, 157, 121, 227, 241, 519, 75, 226, 526, 316, 526, 264, 389,
178, 51, 82, -1,
+75, 526, 86, 389, 387, 51, 70, 107, -1,
+51, 82, 107, 212, 107, 235, 70, 442, 387, 253, 86, 443, 75, 443, 241, 202, 121, 281, 351,
436, 412, 376, -1,
+412, 376, 39, 376, 158, 361, 21, 90, 52, 90, 235, 479, 263, 36, 196, 436, 196, 281, 306,
202, 119, 443, 119, 253, -1,
+90, 90, 479, 361, 36, 376, 436, -1,
+306, 119, 40, 450, -1,
+119, 253, 450, 442, 450, 235, 40, 189, 306, 189, 196, 189, 263, 235, -1,
+291, 291, 203, 506, 59, 65, 169, 229, 96, 432, 302, 432, 235, 424, 52, 373, 21, 375, 158,
249, 39, 99, -1,
+432, 432, 424, 229, 373, 65, 375, 506, 249, 291, 99, -1,
+59, 59, 498, 169, 460, 96, 30, 302, 452, 235, 525, 212, 299, 82, 391, 178, 57, 264, 120,
316, 85, -1,
+391, 166, 299, -1,
+423, 388, 72, 9, 166, 456, 299, 456, 525, 456, 452, 456, 30, 9, 460, 388, 498, 487, 256,
206, 132, -1,
+423, 487, 388, -1,
+206, 487, 352, 423, 341, 423, 418, 72, 139, 166, 139, 391, 57, -1,
+85, 223, 120, 24, 57, 24, 139, 24, 418, 25, 341, -1,
+223, 25, 24, -1,
+492, 132, 515, 206, 224, 352, 359, 341, 41, 25, 171, 223, 50, 85, 43, 98, 232, 406, 258,
469, -1,
+232, 345, 43, 372, 50, 454, 171, 514, 41, 314, 359, 360, 224, 2, 515, 527, -1,
+393, 393, 0, 216, 349, -1,
+486, 215, 327, 91, 177, 254, 177, 393, 512, 0, 231, 349, 231, 279, 486, 246, -1,
+177, 512, 327, 231, 486, -1,
+462, 462, 144, 76, 179, 464, 298, 464, 393, 128, 216, 113, 349, 500, 279, 101, 246, 7,
246, 395, 246, 384, 486, 215, -1,
+7, 7, 195, 101, 444, 500, 462, 113, 76, 128, 464, -1,
+254, 254, 285, 91, 149, 215, 83, 384, 325, 395, 520, 395, 315, 7, 143, 195, 129, 195,
461, 444, 475, 462, 144, -1,
+520, 308, 325, 415, 83, 297, 149, 504, 285, 162, 278, 446, -1,
+403, 403, 520, 276, 308, 404, 308, 272, 415, 416, 297, 317, 504, 125, 162, 60, 446, 110,
446, 393, 278, 254, 285, -1,
+125, 125, 459, 317, 334, 416, 137, 272, 47, 404, 511, 404, 1, 276, 54, 403, 45, 370, 490,
210, 29, 184, -1,
+336, 1, 251, 54, 164, 45, 463, 490, 378, 29, 453, 147, 222, 218, 301, 218, 242, 310, 130,
528, 34, -1,
+26, 336, 148, 251, 269, 164, 419, 463, 293, 378, 420, 453, 333, 222, 208, 301, 294, 56,
127, 228, -1,
+131, 26, 371, 148, 284, 269, 311, 419, 95, 293, 350, 420, 377, 333, 474, 208, 396, 294,
357, 127, -1,
+116, 131, 273, 371, 480, 284, 104, 311, 257, 95, 348, 350, 447, 377, 313, 474, 322, 396,
28, 357, -1,
+273, 273, 183, 480, 347, 104, 53, 257, 181, 348, 124, 447, 428, 313, 428, 435, 11, 270,
193, 305, 69, 305, 386, -1,
+11, 11, 428, 409, 124, 382, 181, 161, 53, 481, 347, 408, 183, 319, 151, 422, 448, 4, 165,
134, 394, -1,
+193, 193, 11, 495, 409, 44, 382, 385, 161, 478, 481, 320, 408, 37, 319, 524, 422, 328, 4,
465, 134, -1,
+37, 37, 431, 320, 136, 478, 513, 385, 27, 44, 467, 495, 115, 193, 69, -1,
+305, 305, 386, 20, 174, 182, 401, 211, 248, 106, 295, 309, 255, 465, 483, 328, 191, 524,
135, 37, 431, -1,
+465, 465, 134, 309, 102, 106, 427, 211, 507, 182, 410, 20, 503, 305, 503, 270, 445, 435,
322, 313, -1,
+134, 134, 394, 102, 455, 427, 5, 507, 23, 410, 405, 503, 405, 445, -1,
+322, 322, 445, 28, 405, 138, 23, 485, 5, 234, 455, 74, 394, 180, 165, 49, 448, 116, 151,
273, 183, -1,
+28, 357, 138, 268, 485, 287, 234, 81, 74, 78, 180, 103, 49, 220, 116, 220, 131, 476, 26,
38, 26, 336, -1,
+357, 127, 268, 252, 287, 398, 81, 274, 78, 154, 103, 62, 220, 476, -1,
+127, 228, 252, 141, 398, 440, 274, 363, 154, 190, 62, 488, 476, 38, -1,
+301, 242, 56, 517, 228, 33, 141, 18, 440, 466, 363, 304, 190, 417, 488, 484, 38, 511,
336, 1, -1,
+33, 517, 260, -1,
+18, 33, 390, 260, 497, -1,
+466, 18, 353, 390, 290, 497, 126, -1,
+304, 466, 187, 353, 123, 290, 522, 126, 501, -1,
+417, 304, 458, 187, 117, 123, 168, 522, 87, 501, 261, -1,
+484, 417, 430, 458, 343, 117, 438, 168, 426, 87, 482, 261, 329, -1,
+511, 484, 47, 430, 137, 343, 334, 438, 459, 426, 439, 482, 92, 329, 192, 329, 267, 329,
491, 261, 219, 501, -1,
+528, 528, 34, 145, 46, 356, 105, 472, 219, 48, 491, 247, 267, 393, 192, 110, 92, 60, 439,
125, 459, -1,
+219, 501, 105, 126, 46, 497, 34, 260, 130, 517, 242, -1,
+29, 184, 147, 156, 218, 156, 310, 402, 528, 146, 145, 17, 356, 411, 472, 364, 48, 441,
247, 441, 393, 509, -1,
+184, 184, 156, 63, 402, 354, 146, 335, 17, 239, 411, 13, 364, 509, 441, -1,
+393, 509, 298, 13, 179, 239, 144, 335, 475, 354, 461, 63, 129, 184, 129, 210, 143, 370,
315, 403, 520, -1,
+296, 296, 160, 133, 344, 330, -1,
+344, 323, 160, -1,
+159, 159, 296, 275, 133, 22, 330, 523, -1,
+198, 523, 77, 22, 286, 275, 437, 159, 499, -1,
+280, 323, 108, 344, 338, 330, 259, 523, 366, 198, 381, 240, 283, 10, 368, 243, 280, 243,
323, 35, 160, -1,
+77, 471, 198, 471, 240, 250, 10, 303, 243, 303, 35, 230, 282, 362, 163, 73, 318, 292, 93,
477, 262, -1,
+413, 413, 326, 399, 73, 399, 292, 100, 477, -1,
+122, 355, 414, 61, 100, 55, 477, 508, 262, 365, -1,
+35, 35, 160, 282, 296, 163, 159, 318, 499, 93, 505, 262, 340, 365, 340, 140, 68, 510,
518, 3, 122, 355, -1,
+100, 399, 414, 413, 122, 111, 518, 213, 68, 167, 340, 167, 505, 245, 499, 245, 437, 346,
286, 79, 77, 471, -1,
+362, 362, 221, 230, 516, 303, 516, 250, 207, 471, 207, 79, 521, 346, 468, 245, 468, 167,
468, 213, 473, 111, 204, 413, 326, -1,
+468, 473, 521, 217, 207, 217, 516, 217, 221, 204, 221, 326, 362, 73, -1,
+473, 204, 217, -1,
+94, 94, 185, 529, 429, 209, 429, 176, -1,
+379, 379, 94, 199, 529, 367, 209, 172, 209, 66, 176, 496, -1,
+312, 312, 379, 238, 199, 15, 367, 332, 172, 197, 172, 451, 66, 84, 496, 186, -1,
+266, 266, 312, 392, 238, 201, 15, 14, 332, 457, 197, 383, 197, 225, 451, 502, 84, 265,
186, 205, -1,
+236, 236, 266, 214, 392, 71, 201, 188, 14, 173, 457, 400, 383, 380, 383, 342, 225, 109,
502, 175, 265, 97, 205, 118, -1,
+152, 152, 236, 337, 214, 58, 71, 369, 188, 434, 173, 114, 400, 288, 380, 42, 380, 397,
342, 32, 109, 331, -1,
+379, 170, 312, 331, 266, 32, 236, 397, 152, 42, 194, 42, 407, 288, 142, 114, 12, 434,
233, 369, 244, -1,
+369, 369, 244, 58, 425, 337, 321, 152, 194, -1,
+109, 331, 175, 170, 97, 300, 118, 421, 31, 89, -1,
+31, 31, 118, 237, 205, 449, 186, 470, 496, 494, 176, 155, 429, 112, 185, 89, 185, 421,
94, 300, 379, 170, -1
+};
+
+#else /* TARGET_HOST_WINCE */
+
+/*
+ * Original teapot code copyright follows:
+ */
+
+/*
+ * (c) Copyright 1993, Silicon Graphics, Inc.
+ *
+ * ALL RIGHTS RESERVED
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notice appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Silicon
+ * Graphics, Inc. not be used in advertising or publicity
+ * pertaining to distribution of the software without specific,
+ * written prior permission.
+ *
+ * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU
+ * "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR
+ * OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. IN NO
+ * EVENT SHALL SILICON GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE
+ * ELSE FOR ANY DIRECT, SPECIAL, INCIDENTAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER,
+ * INCLUDING WITHOUT LIMITATION, LOSS OF PROFIT, LOSS OF USE,
+ * SAVINGS OR REVENUE, OR THE CLAIMS OF THIRD PARTIES, WHETHER OR
+ * NOT SILICON GRAPHICS, INC. HAS BEEN ADVISED OF THE POSSIBILITY
+ * OF SUCH LOSS, HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * ARISING OUT OF OR IN CONNECTION WITH THE POSSESSION, USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ * US Government Users Restricted Rights
+ *
+ * Use, duplication, or disclosure by the Government is subject to
+ * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
+ * (c)(1)(ii) of the Rights in Technical Data and Computer
+ * Software clause at DFARS 252.227-7013 and/or in similar or
+ * successor clauses in the FAR or the DOD or NASA FAR
+ * Supplement. Unpublished-- rights reserved under the copyright
+ * laws of the United States. Contractor/manufacturer is Silicon
+ * Graphics, Inc., 2011 N. Shoreline Blvd., Mountain View, CA
+ * 94039-7311.
+ *
+ * OpenGL(TM) is a trademark of Silicon Graphics, Inc.
+ */
+
+/*
+ * Rim, body, lid, and bottom data must be reflected in x and y;
+ * handle and spout data across the y axis only.
+ */
+static int patchdata[][16] =
+{
+ { 102, 103, 104, 105, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
/* rim */
+ { 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27 },
/* body */
+ { 24, 25, 26, 27, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 },
+ { 96, 96, 96, 96, 97, 98, 99, 100, 101, 101, 101, 101, 0, 1, 2, 3 },
/* lid */
+ { 0, 1, 2, 3, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117 },
+ { 118, 118, 118, 118, 124, 122, 119, 121, 123, 126, 125, 120, 40, 39, 38, 37 },
/* bottom */
+ { 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56 },
/* handle */
+ { 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 28, 65, 66, 67 },
+ { 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83 },
/* spout */
+ { 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95 }
+};
+
+static double cpdata[][3] =
+{
+ {0.2, 0, 2.7}, {0.2, -0.112, 2.7}, {0.112, -0.2, 2.7}, {0,
+ -0.2, 2.7}, {1.3375, 0, 2.53125}, {1.3375, -0.749, 2.53125},
+ {0.749, -1.3375, 2.53125}, {0, -1.3375, 2.53125}, {1.4375,
+ 0, 2.53125}, {1.4375, -0.805, 2.53125}, {0.805, -1.4375,
+ 2.53125}, {0, -1.4375, 2.53125}, {1.5, 0, 2.4}, {1.5, -0.84,
+ 2.4}, {0.84, -1.5, 2.4}, {0, -1.5, 2.4}, {1.75, 0, 1.875},
+ {1.75, -0.98, 1.875}, {0.98, -1.75, 1.875}, {0, -1.75,
+ 1.875}, {2, 0, 1.35}, {2, -1.12, 1.35}, {1.12, -2, 1.35},
+ {0, -2, 1.35}, {2, 0, 0.9}, {2, -1.12, 0.9}, {1.12, -2,
+ 0.9}, {0, -2, 0.9}, {-2, 0, 0.9}, {2, 0, 0.45}, {2, -1.12,
+ 0.45}, {1.12, -2, 0.45}, {0, -2, 0.45}, {1.5, 0, 0.225},
+ {1.5, -0.84, 0.225}, {0.84, -1.5, 0.225}, {0, -1.5, 0.225},
+ {1.5, 0, 0.15}, {1.5, -0.84, 0.15}, {0.84, -1.5, 0.15}, {0,
+ -1.5, 0.15}, {-1.6, 0, 2.025}, {-1.6, -0.3, 2.025}, {-1.5,
+ -0.3, 2.25}, {-1.5, 0, 2.25}, {-2.3, 0, 2.025}, {-2.3, -0.3,
+ 2.025}, {-2.5, -0.3, 2.25}, {-2.5, 0, 2.25}, {-2.7, 0,
+ 2.025}, {-2.7, -0.3, 2.025}, {-3, -0.3, 2.25}, {-3, 0,
+ 2.25}, {-2.7, 0, 1.8}, {-2.7, -0.3, 1.8}, {-3, -0.3, 1.8},
+ {-3, 0, 1.8}, {-2.7, 0, 1.575}, {-2.7, -0.3, 1.575}, {-3,
+ -0.3, 1.35}, {-3, 0, 1.35}, {-2.5, 0, 1.125}, {-2.5, -0.3,
+ 1.125}, {-2.65, -0.3, 0.9375}, {-2.65, 0, 0.9375}, {-2,
+ -0.3, 0.9}, {-1.9, -0.3, 0.6}, {-1.9, 0, 0.6}, {1.7, 0,
+ 1.425}, {1.7, -0.66, 1.425}, {1.7, -0.66, 0.6}, {1.7, 0,
+ 0.6}, {2.6, 0, 1.425}, {2.6, -0.66, 1.425}, {3.1, -0.66,
+ 0.825}, {3.1, 0, 0.825}, {2.3, 0, 2.1}, {2.3, -0.25, 2.1},
+ {2.4, -0.25, 2.025}, {2.4, 0, 2.025}, {2.7, 0, 2.4}, {2.7,
+ -0.25, 2.4}, {3.3, -0.25, 2.4}, {3.3, 0, 2.4}, {2.8, 0,
+ 2.475}, {2.8, -0.25, 2.475}, {3.525, -0.25, 2.49375},
+ {3.525, 0, 2.49375}, {2.9, 0, 2.475}, {2.9, -0.15, 2.475},
+ {3.45, -0.15, 2.5125}, {3.45, 0, 2.5125}, {2.8, 0, 2.4},
+ {2.8, -0.15, 2.4}, {3.2, -0.15, 2.4}, {3.2, 0, 2.4}, {0, 0,
+ 3.15}, {0.8, 0, 3.15}, {0.8, -0.45, 3.15}, {0.45, -0.8,
+ 3.15}, {0, -0.8, 3.15}, {0, 0, 2.85}, {1.4, 0, 2.4}, {1.4,
+ -0.784, 2.4}, {0.784, -1.4, 2.4}, {0, -1.4, 2.4}, {0.4, 0,
+ 2.55}, {0.4, -0.224, 2.55}, {0.224, -0.4, 2.55}, {0, -0.4,
+ 2.55}, {1.3, 0, 2.55}, {1.3, -0.728, 2.55}, {0.728, -1.3,
+ 2.55}, {0, -1.3, 2.55}, {1.3, 0, 2.4}, {1.3, -0.728, 2.4},
+ {0.728, -1.3, 2.4}, {0, -1.3, 2.4}, {0, 0, 0}, {1.425,
+ -0.798, 0}, {1.5, 0, 0.075}, {1.425, 0, 0}, {0.798, -1.425,
+ 0}, {0, -1.5, 0.075}, {0, -1.425, 0}, {1.5, -0.84, 0.075},
+ {0.84, -1.5, 0.075}
+};
+
+static double tex[2][2][2] =
+{
+ { {0.0, 0.0}, {1.0, 0.0} },
+ { {0.0, 1.0}, {1.0, 1.0} }
+};
+#endif /* TARGET_HOST_WINCE */
+
+
+#endif /* FREEGLUT_TEAPOT_DATA_H */
Index: external/trimesh/gluit/glui_img_spinup_dis.c
--- external/trimesh/gluit/glui_img_spinup_dis.c (revision 0)
+++ external/trimesh/gluit/glui_img_spinup_dis.c (revision 0)
@@ -0,0 +1,24 @@
+
+
+int glui_img_spinup_dis[] = { 12, 8, /* width, height */
+ 255,255,255, 127,127,127, 127,127,127, 127,127,127, 127,127,127,
+ 127,127,127, 127,127,127, 127,127,127, 127,127,127, 127,127,127,
+ 127,127,127, 64, 64, 64, 255,255,255, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 127,127,127, 64, 64, 64, 255,255,255,
+ 191,191,191, 191,191,191, 127,127,127, 127,127,127, 127,127,127,
+ 127,127,127, 127,127,127, 255,255,255, 191,191,191, 127,127,127,
+ 64, 64, 64, 255,255,255, 191,191,191, 191,191,191, 191,191,191,
+ 127,127,127, 127,127,127, 127,127,127, 255,255,255, 191,191,191,
+ 191,191,191, 127,127,127, 64, 64, 64, 255,255,255, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 127,127,127, 255,255,255,
+ 191,191,191, 191,191,191, 191,191,191, 127,127,127, 64, 64, 64,
+ 255,255,255, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 127,127,127, 64, 64, 64, 255,255,255, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 64, 64, 64, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255,
+};
Index: external/trimesh/gluit/freeglut_glutfont_definitions.c
--- external/trimesh/gluit/freeglut_glutfont_definitions.c (revision 0)
+++ external/trimesh/gluit/freeglut_glutfont_definitions.c (revision 0)
@@ -0,0 +1,77 @@
+/*
+ * freeglut_glutfont_definitions.c
+ *
+ * Bitmap and stroke fonts displaying.
+ *
+ * Copyright (c) 2003 Stephen J. Baker (whether he wants it or not).
+ * All Rights Reserved.
+ * Written by John F. Fay <fayjf(a)sourceforge.net>et>, who releases the
+ * copyright over to the "freeglut" project lead.
+ * Creation date: Mon July 21 2003
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * This file is necessary for the *nix version of "freeglut" because the
+ * original GLUT defined its font variables in rather an unusual way.
+ * Publicly, in "glut.h", they were defined as "void *". Privately,
+ * in one of the source code files, they were defined as pointers to a
+ * structure. Most compilers and linkers are satisfied with the "void *"
+ * and don't go any farther, but some of them balked. In particular,
+ * when compiling with "freeglut" and then trying to run using the GLUT
+ * ".so" library, some of them would give an error. So we are having to
+ * create this file to define the variables as pointers to an unusual
+ * structure to match GLUT.
+ */
+
+#include "freeglut_internal.h"
+
+#if TARGET_HOST_UNIX_X11
+
+struct freeglutStrokeFont
+{
+ const char *name ;
+ int num_chars ;
+ void *ch ;
+ float top ;
+ float bottom ;
+};
+
+struct freeglutBitmapFont
+{
+ const char *name ;
+ const int num_chars ;
+ const int first ;
+ const void *ch ;
+};
+
+
+struct freeglutStrokeFont glutStrokeRoman ;
+struct freeglutStrokeFont glutStrokeMonoRoman ;
+
+struct freeglutBitmapFont glutBitmap9By15 ;
+struct freeglutBitmapFont glutBitmap8By13 ;
+struct freeglutBitmapFont glutBitmapTimesRoman10 ;
+struct freeglutBitmapFont glutBitmapTimesRoman24 ;
+struct freeglutBitmapFont glutBitmapHelvetica10 ;
+struct freeglutBitmapFont glutBitmapHelvetica12 ;
+struct freeglutBitmapFont glutBitmapHelvetica18 ;
+
+#endif
+
Index: external/trimesh/gluit/glui_add_controls.cc
--- external/trimesh/gluit/glui_add_controls.cc (revision 0)
+++ external/trimesh/gluit/glui_add_controls.cc (revision 0)
@@ -0,0 +1,742 @@
+/****************************************************************************
+
+ GLUI User Interface Toolkit
+ ---------------------------
+
+ glui_add_controls.cpp - Routines for adding controls to a GLUI window
+
+
+ --------------------------------------------------
+
+ Copyright (c) 1998 Paul Rademacher
+
+ This program is freely distributable without licensing fees and is
+ provided without guarantee or warrantee expressed or implied. This
+ program is -not- in the public domain.
+
+*****************************************************************************/
+
+#include "glui.h"
+#include "glui_stdinc.h"
+
+
+/*********************************** GLUI:: add_checkbox() ************/
+
+GLUI_Checkbox *GLUI:: add_checkbox( char *name, int *value_ptr,
+ int id, GLUI_Update_CB callback )
+{
+ return add_checkbox_to_panel( main_panel,
+ name, value_ptr, id, callback );
+}
+
+
+/*********************************** GLUI:: add_checkbox_to_panel() **********/
+
+GLUI_Checkbox *GLUI::add_checkbox_to_panel( GLUI_Panel *panel,
+ char *name, int *value_ptr,
+ int id,
+ GLUI_Update_CB callback )
+{
+ GLUI_Checkbox *control;
+
+ control = new GLUI_Checkbox;
+
+ if ( control ) {
+ control->set_ptr_val( value_ptr );
+ control->user_id = id;
+ control->set_name( name );
+ control->callback = callback;
+
+ add_control( panel, control );
+
+ control->init_live();
+
+ return control;
+ }
+ else {
+ return NULL;
+ }
+}
+
+
+
+/************************************ GLUI_Main::add_control() **************/
+
+int GLUI_Main::add_control( GLUI_Node *parent, GLUI_Control *control )
+{
+ GLUI_Control *parent_control;
+
+ /*** Collapsible nodes have to be handled differently, b/c the first and
+ last children are swapped in and out ***/
+ parent_control = ((GLUI_Control*)parent);
+ if ( parent_control->collapsible == true ) {
+ if ( NOT parent_control->is_open ) {
+ /** Swap in the original first and last children **/
+ parent_control->child_head = parent_control->collapsed_node.child_head;
+ parent_control->child_tail = parent_control->collapsed_node.child_tail;
+
+ /*** Link this control ***/
+ control->link_this_to_parent_last( parent );
+
+ /** Swap the children back out ***/
+ parent_control->collapsed_node.child_head = parent_control->child_head;
+ parent_control->collapsed_node.child_tail = parent_control->child_tail;
+ parent_control->child_head = NULL;
+ parent_control->child_tail = NULL;
+ }
+ else {
+ control->link_this_to_parent_last( parent );
+ }
+ }
+ else {
+ control->link_this_to_parent_last( parent );
+ }
+ control->glui = (GLUI*) this;
+ control->update_size();
+ control->enabled = ((GLUI_Control*) parent)->enabled;
+ control->glui->refresh();
+
+ /** Now set the 'hidden' var based on the parent **/
+ if ( parent_control->hidden OR
+ (parent_control->collapsible AND NOT parent_control->is_open ) )
+ {
+ control->hidden = true;
+ }
+
+ return true;
+}
+
+
+/********************************************* GLUI::add_panel() *************/
+
+GLUI_Panel *GLUI::add_panel( char *name, int type )
+{
+ return add_panel_to_panel( main_panel, name, type );
+}
+
+
+/**************************************** GLUI::add_panel_to_panel() *********/
+
+GLUI_Panel *GLUI::add_panel_to_panel( GLUI_Panel *parent_panel,
+ char *name, int type )
+{
+ GLUI_Panel *panel;
+
+ panel = new GLUI_Panel;
+
+ if ( panel ) {
+ panel->set_name( name );
+ panel->user_id = -1;
+ panel->int_val = type;
+
+ add_control( parent_panel, panel );
+
+ return panel;
+ }
+ else {
+ return NULL;
+ }
+}
+
+
+/***************************** GLUI::add_radiogroup() ***************/
+
+GLUI_RadioGroup *GLUI::add_radiogroup( int *value_ptr,
+ int user_id, GLUI_Update_CB callback)
+{
+ return add_radiogroup_to_panel( main_panel, value_ptr,
+ user_id, callback );
+}
+
+
+/***************************** GLUI::add_radiogroup_to_panel() ***************/
+
+GLUI_RadioGroup *GLUI::add_radiogroup_to_panel( GLUI_Panel *panel,
+ int *value_ptr,
+ int user_id, GLUI_Update_CB callback)
+{
+ GLUI_RadioGroup *control;
+ GLUI_String buf;
+
+ control = new GLUI_RadioGroup;
+
+ if ( control ) {
+ control->set_ptr_val( value_ptr );
+ if ( value_ptr ) {
+ control->int_val = *value_ptr; /** Can't call set_int_val(), b/c that
+ function will try to call the
+ callback, etc */
+ /** Actually, maybe not **/
+ control->last_live_int = *value_ptr;
+ }
+
+ control->user_id = user_id;
+ sprintf( buf, "RadioGroup: %p", control );
+ control->set_name( buf );
+ control->callback = callback;
+
+ add_control( panel, control );
+
+ control->init_live();
+
+ return control;
+ }
+ else {
+ return NULL;
+ }
+
+}
+
+
+/***************************** GLUI::add_radiobutton_to_group() *************/
+
+GLUI_RadioButton *GLUI::add_radiobutton_to_group( GLUI_RadioGroup *group,
+ char *name )
+{
+ GLUI_RadioButton *control;
+
+ if ( group->type != GLUI_CONTROL_RADIOGROUP ) {
+ /*fprintf( stderr, "ERROR: Trying to add radiobutton to non-radiogroup\n"
); */
+ /*fflush( stderr ); */
+ return NULL;
+ }
+
+ control = new GLUI_RadioButton;
+
+ if ( control ) {
+ control->set_int_val( 0 );
+ /*int_val = 0; */
+
+ /** A radio button's user id is always its ordinal number (zero-indexed)
+ within the group */
+ control->user_id = group->num_buttons;
+ group->num_buttons++; /* Increments radiogroup's button count */
+ control->set_name( name );
+ control->group = group;
+
+ add_control( group, control );
+
+ /*** Now update button states ***/
+ group->set_int_val( group->int_val ); /* This tells the group to
+ reset itself to its
+ current value, thereby
+ updating all its buttons */
+
+ return control;
+ }
+ else {
+ return NULL;
+ }
+
+}
+
+
+/********************************** GLUI::add_statictext() ************/
+
+GLUI_StaticText *GLUI::add_statictext( char *name )
+{
+ return add_statictext_to_panel( main_panel, name );
+}
+
+
+/******************************* GLUI::add_statictext_to_panel() **********/
+
+GLUI_StaticText *GLUI::
+add_statictext_to_panel( GLUI_Panel *panel, char *name )
+{
+ GLUI_StaticText *control;
+
+ control = new GLUI_StaticText;
+
+ if ( control ) {
+ control->set_name( name );
+ add_control( panel, control );
+
+ return control;
+ }
+ else {
+ return NULL;
+ }
+
+}
+
+
+/***************************************** GLUI:: add_button() ************/
+
+GLUI_Button *GLUI:: add_button( char *name,
+ int id, GLUI_Update_CB callback )
+{
+ return add_button_to_panel( main_panel,
+ name, id, callback );
+}
+
+
+/*********************************** GLUI:: add_button_to_panel() **********/
+
+GLUI_Button *GLUI::add_button_to_panel( GLUI_Panel *panel,
+ char *name,
+ int id,
+ GLUI_Update_CB callback )
+{
+ GLUI_Button *control;
+
+ control = new GLUI_Button;
+
+ if ( control ) {
+ /* control->set_ptr_val( value_ptr );
+ if ( value_ptr ) {
+ control->set_int_val( *value_ptr );
+ }*/
+
+ control->user_id = id;
+ control->callback = callback;
+ control->set_name( name );
+
+ add_control( panel, control );
+
+ return control;
+ }
+ else {
+ return NULL;
+ }
+}
+
+
+
+/********************************** GLUI::add_separator() ************/
+
+void GLUI::add_separator( void )
+{
+ add_separator_to_panel( main_panel );
+}
+
+
+/******************************* GLUI::add_separator_to_panel() **********/
+
+void GLUI::add_separator_to_panel( GLUI_Panel *panel )
+{
+ GLUI_Separator *control = new GLUI_Separator;
+
+ if ( control ) {
+ add_control( panel, control );
+ }
+}
+
+
+/********************************** GLUI::add_edittext() ************/
+
+GLUI_EditText *GLUI::add_edittext( char *name,
+ int data_type, void *data,
+ int id, GLUI_Update_CB callback)
+{
+ return add_edittext_to_panel( main_panel, name, data_type, data,
+ id, callback );
+}
+
+
+/******************************* GLUI::add_edittext_to_panel() **********/
+
+GLUI_EditText *GLUI::
+add_edittext_to_panel( GLUI_Panel *panel, char *name,
+ int data_type, void *data,
+ int id, GLUI_Update_CB callback)
+{
+ GLUI_EditText *control;
+
+ control = new GLUI_EditText;
+
+ if ( control ) {
+ control->set_name( name );
+
+ control->data_type = data_type;
+ control->ptr_val = data;
+ control->user_id = id;
+ control->callback = callback;
+
+ if ( data_type == GLUI_EDITTEXT_TEXT ) {
+ control->live_type = GLUI_LIVE_TEXT;
+ }
+ else if ( data_type == GLUI_EDITTEXT_INT ) {
+ control->live_type = GLUI_LIVE_INT;
+ if ( data == NULL )
+ control->set_int_val(control->int_val); /** Set to some default, in case of
no live var **/
+ }
+ else if ( data_type == GLUI_EDITTEXT_FLOAT ) {
+ control->live_type = GLUI_LIVE_FLOAT;
+ control->num_periods = 1;
+ if ( data == NULL )
+ control->set_float_val(control->float_val); /** Set to some default, in case
of no live var **/
+ }
+ else {
+ return NULL; /* Did not pass in a valid data type */
+ }
+
+ add_control( panel, control );
+
+ control->init_live();
+
+ return control;
+ }
+ else {
+ return NULL;
+ }
+
+}
+
+
+/********************************** GLUI::add_spinner() ************/
+
+GLUI_Spinner *GLUI::add_spinner( char *name,
+ int data_type, void *data,
+ int id, GLUI_Update_CB callback)
+{
+ return add_spinner_to_panel( main_panel, name, data_type, data,
+ id, callback );
+}
+
+
+/******************************* GLUI::add_spinner_to_panel() **********/
+
+GLUI_Spinner *GLUI::
+add_spinner_to_panel( GLUI_Panel *panel, char *name,
+ int data_type, void *data,
+ int id, GLUI_Update_CB callback)
+{
+ GLUI_Spinner *control;
+ int text_type;
+
+ control = new GLUI_Spinner;
+
+ if ( NOT strcmp( name, "Spinner Test" ))
+ id=id;
+
+
+ if ( control ) {
+ if ( data_type == GLUI_SPINNER_INT ) {
+ text_type = GLUI_EDITTEXT_INT;
+ /* control->live_type = GLUI_LIVE_INT; */
+ }
+ else if ( data_type == GLUI_SPINNER_FLOAT ) {
+ text_type = GLUI_EDITTEXT_FLOAT;
+ /* control->live_type = GLUI_LIVE_FLOAT; */
+ }
+ else {
+ return NULL; /* Did not pass in a valid data type */
+ }
+
+ GLUI_EditText *edittext =
+ add_edittext_to_panel( (GLUI_Panel*) control, name, text_type, data,
+ id, callback );
+
+ if ( edittext ) {
+ control->set_name( name );
+ control->edittext = edittext; /* Link the edittext to the spinner */
+ /* control->ptr_val = data; */
+ control->user_id = id;
+ control->data_type = data_type;
+ control->callback = callback;
+
+ edittext->spinner = control; /* Link the spinner to the edittext */
+
+ add_control( panel, control );
+
+ return control;
+ }
+ else {
+ return NULL;
+ }
+ }
+ else {
+ return NULL;
+ }
+
+}
+
+
+/********************************** GLUI::add_column() ************/
+
+void GLUI::add_column( int draw_bar )
+{
+ add_column_to_panel( main_panel, draw_bar );
+}
+
+
+/******************************* GLUI::add_column_to_panel() **********/
+
+void GLUI::add_column_to_panel( GLUI_Panel *panel, int draw_bar )
+{
+ GLUI_Column *control = new GLUI_Column;
+
+ if ( control ) {
+ control->int_val = draw_bar; /* Whether to draw vertical bar or not */
+
+ add_control( panel, control );
+ }
+ else {
+ }
+}
+
+
+/*********************************** GLUI:: add_listbox() ************/
+
+GLUI_Listbox *GLUI:: add_listbox( char *name, int *value_ptr,
+ int id, GLUI_Update_CB callback )
+{
+ return add_listbox_to_panel( main_panel,
+ name, value_ptr, id, callback );
+}
+
+
+/*********************************** GLUI:: add_listbox_to_panel() **********/
+
+GLUI_Listbox *GLUI::add_listbox_to_panel( GLUI_Panel *panel,
+ char *name, int *value_ptr,
+ int id,
+ GLUI_Update_CB callback )
+{
+ GLUI_Listbox *control;
+
+ control = new GLUI_Listbox;
+
+ if ( control ) {
+ control->set_ptr_val( value_ptr );
+ control->user_id = id;
+ control->set_name( name );
+ control->callback = callback;
+
+ add_control( panel, control );
+
+ control->init_live();
+
+ return control;
+ }
+ else {
+ return NULL;
+ }
+}
+
+
+/*********************************** GLUI:: add_rotation() ************/
+
+GLUI_Rotation *GLUI:: add_rotation( char *name, float *value_ptr,
+ int id, GLUI_Update_CB callback )
+{
+ return add_rotation_to_panel( main_panel,
+ name, value_ptr, id, callback );
+}
+
+
+/*********************************** GLUI:: add_rotation_to_panel() **********/
+
+GLUI_Rotation *GLUI::add_rotation_to_panel( GLUI_Panel *panel,
+ char *name, float *value_ptr,
+ int id,
+ GLUI_Update_CB callback )
+{
+ GLUI_Rotation *control;
+
+ control = new GLUI_Rotation;
+
+ if ( control ) {
+ control->set_ptr_val( value_ptr );
+ control->user_id = id;
+ control->set_name( name );
+ control->callback = callback;
+ add_control( panel, control );
+ control->init_live();
+
+ /*** Init the live 4x4 matrix. This is different than the standard
+ live variable behavior, since the original value of the 4x4 matrix
+ is ignored and reset to Identity ***/
+ if ( value_ptr != NULL ) {
+ int i, j, index;
+ for( i=0; i<4; i++ ) {
+ for( j=0; j<4; j++ ) {
+ index = i*4+j;
+ if ( i==j )
+ value_ptr[index] = 1.0;
+ else
+ value_ptr[index] = 0.0;
+ }
+ }
+ }
+
+ /*init_ball(); */
+
+ return control;
+ }
+ else {
+ return NULL;
+ }
+}
+
+/*********************************** GLUI:: add_slider() ************/
+
+GLUI_Slider *GLUI:: add_slider(
+ char *name,
+ int data_type,
+ float lo,
+ float hi,
+ void *data,
+ int id,
+ GLUI_Update_CB callback )
+{
+ return add_slider_to_panel( main_panel,
+ name, data_type, lo, hi, data, id, callback );
+}
+
+
+/*********************************** GLUI:: add_slider_to_panel() **********/
+GLUI_Slider *GLUI::add_slider_to_panel(
+ GLUI_Panel *panel,
+ char *name,
+ int data_type,
+ float lo,
+ float hi,
+ void *data,
+ int id,
+ GLUI_Update_CB callback )
+{
+ GLUI_Slider *control;
+
+ control = new GLUI_Slider;
+
+ if ( control )
+ {
+ control->set_name( name );
+ control->data_type = data_type;
+ control->ptr_val = data;
+ control->user_id = id;
+ control->callback = callback;
+
+ if ( data_type == GLUI_SLIDER_INT ) {
+ control->set_int_limits((int)lo, (int)hi);
+ if ( data == NULL )
+ {
+ control->set_int_val(control->int_low);
+ control->live_type = GLUI_LIVE_NONE;
+ }
+ else
+ control->live_type = GLUI_LIVE_INT;
+ }
+ else if ( data_type == GLUI_SLIDER_FLOAT ) {
+ control->set_float_limits(lo,hi);
+ if ( data == NULL )
+ {
+ control->set_float_val(control->float_low);
+ control->live_type = GLUI_LIVE_NONE;
+ }
+ else
+ control->live_type = GLUI_LIVE_FLOAT;
+ }
+ else {
+ delete control;
+ return NULL;
+ }
+
+ add_control( panel, control );
+
+ control->init_live();
+
+ //In case the live var was out of range,
+ //(and got clamped) we update the live
+ //var to the internal value
+ control->output_live(false);
+
+ return control;
+ }
+ else {
+ return NULL;
+ }
+
+}
+
+
+/*********************************** GLUI:: add_translation() ************/
+
+GLUI_Translation
+ *GLUI:: add_translation( char *name, int trans_type,
+ float *value_ptr, int id, GLUI_Update_CB callback )
+{
+ return add_translation_to_panel( main_panel,name,trans_type,
+ value_ptr, id, callback );
+}
+
+
+/*********************************** GLUI:: add_translation_to_panel() **********/
+
+GLUI_Translation
+ *GLUI::add_translation_to_panel(
+ GLUI_Panel *panel, char *name,
+ int trans_type, float *value_ptr,
+ int id, GLUI_Update_CB callback )
+{
+ GLUI_Translation *control;
+
+ control = new GLUI_Translation;
+
+ if ( control ) {
+ control->set_ptr_val( value_ptr );
+ control->user_id = id;
+ control->set_name( name );
+ control->callback = callback;
+ add_control( panel, control );
+ control->init_live();
+
+ control->trans_type = trans_type;
+
+ if ( trans_type == GLUI_TRANSLATION_XY ) {
+ control->float_array_size = 2;
+ }
+ else if ( trans_type == GLUI_TRANSLATION_X ) {
+ control->float_array_size = 1;
+ }
+ else if ( trans_type == GLUI_TRANSLATION_Y ) {
+ control->float_array_size = 1;
+ }
+ else if ( trans_type == GLUI_TRANSLATION_Z ) {
+ control->float_array_size = 1;
+ }
+
+ return control;
+ }
+ else {
+ return NULL;
+ }
+}
+
+
+/********************************** GLUI::add_rollout() **************/
+
+GLUI_Rollout *GLUI::add_rollout( char *name, int open )
+{
+ return add_rollout_to_panel( main_panel, name, open );
+}
+
+
+/****************************** GLUI::add_rollout_to_panel() *********/
+
+GLUI_Rollout *GLUI::add_rollout_to_panel(GLUI_Panel *panel,char *name,int open)
+{
+ GLUI_Rollout *rollout;
+
+ rollout = new GLUI_Rollout;
+
+ if ( rollout ) {
+ rollout->set_name( name );
+ rollout->user_id = -1;
+ rollout->int_val = GLUI_PANEL_EMBOSSED;
+
+ if ( NOT open ) {
+ rollout->is_open = false;
+ rollout->h = GLUI_DEFAULT_CONTROL_HEIGHT + 7;
+ }
+
+ add_control( panel, rollout );
+
+ return rollout;
+ }
+ else {
+ return NULL;
+ }
+}
Index: external/trimesh/gluit/glui_img_downarrow.c
--- external/trimesh/gluit/glui_img_downarrow.c (revision 0)
+++ external/trimesh/gluit/glui_img_downarrow.c (revision 0)
@@ -0,0 +1,56 @@
+
+
+int glui_img_downarrow[] = { 16, 16, /* width, height */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 192,192,192, 128,128,128, 128,128,128, 128,128,128,
+ 128,128,128, 128,128,128, 128,128,128, 128,128,128, 128,128,128,
+ 128,128,128, 128,128,128, 128,128,128, 128,128,128, 128,128,128,
+ 128,128,128, 0, 0, 0, 192,192,192, 255,255,255, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 128,128,128, 0, 0, 0, 192,192,192, 255,255,255,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 128,128,128, 0, 0, 0, 192,192,192,
+ 255,255,255, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 128,128,128, 0, 0, 0,
+ 192,192,192, 255,255,255, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 128,128,128,
+ 0, 0, 0, 192,192,192, 255,255,255, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 0, 0, 0, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 128,128,128, 0, 0, 0, 192,192,192, 255,255,255, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 128,128,128, 0, 0, 0, 192,192,192, 255,255,255,
+ 192,192,192, 192,192,192, 192,192,192, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 128,128,128, 0, 0, 0, 192,192,192,
+ 255,255,255, 192,192,192, 192,192,192, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 192,192,192, 192,192,192, 192,192,192, 128,128,128, 0, 0, 0,
+ 192,192,192, 255,255,255, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 128,128,128,
+ 0, 0, 0, 192,192,192, 255,255,255, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 128,128,128, 0, 0, 0, 192,192,192, 255,255,255, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 128,128,128, 0, 0, 0, 192,192,192, 255,255,255,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 128,128,128, 0, 0, 0, 192,192,192,
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 128,128,128, 0, 0, 0,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 0, 0, 0,
+};
Index: external/trimesh/gluit/freeglut_display.c
--- external/trimesh/gluit/freeglut_display.c (revision 0)
+++ external/trimesh/gluit/freeglut_display.c (revision 0)
@@ -0,0 +1,99 @@
+/*
+ * freeglut_display.c
+ *
+ * Display message posting, context buffer swapping.
+ *
+ * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
+ * Written by Pawel W. Olszta, <olszta(a)sourceforge.net>
+ * Creation date: Fri Dec 3 1999
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <GL/freeglut.h>
+#include "freeglut_internal.h"
+
+
+/* -- INTERFACE FUNCTIONS -------------------------------------------------- */
+
+/*
+ * Marks the current window to have the redisplay performed when possible...
+ */
+void FGAPIENTRY glutPostRedisplay( void )
+{
+ freeglut_assert_ready;
+ freeglut_assert_window;
+ fgStructure.Window->State.Redisplay = GL_TRUE;
+}
+
+/*
+ * Swaps the buffers for the current window (if any)
+ */
+void FGAPIENTRY glutSwapBuffers( void )
+{
+ freeglut_assert_ready;
+ freeglut_assert_window;
+
+ glFlush( );
+ if( ! fgStructure.Window->Window.DoubleBuffered )
+ return;
+
+#if TARGET_HOST_UNIX_X11
+ glXSwapBuffers( fgDisplay.Display, fgStructure.Window->Window.Handle );
+#elif TARGET_HOST_WIN32 || TARGET_HOST_WINCE
+ SwapBuffers( fgStructure.Window->Window.Device );
+#endif
+
+ /* GLUT_FPS env var support */
+ if( fgState.FPSInterval )
+ {
+ GLint t = glutGet( GLUT_ELAPSED_TIME );
+ fgState.SwapCount++;
+ if( fgState.SwapTime == 0 )
+ fgState.SwapTime = t;
+ else if( t - fgState.SwapTime > fgState.FPSInterval )
+ {
+ float time = 0.001f * ( t - fgState.SwapTime );
+ float fps = ( float )fgState.SwapCount / time;
+ fprintf( stderr,
+ "freeglut: %d frames in %.2f seconds = %.2f FPS\n",
+ fgState.SwapCount, time, fps );
+ fgState.SwapTime = t;
+ fgState.SwapCount = 0;
+ }
+ }
+}
+
+/*
+ * Mark appropriate window to be displayed
+ */
+void FGAPIENTRY glutPostWindowRedisplay( int windowID )
+{
+ SFG_Window* window;
+
+ freeglut_assert_ready;
+ window = fgWindowByID( windowID );
+ freeglut_return_if_fail( window );
+ window->State.Redisplay = GL_TRUE;
+}
+
+/*** END OF FILE ***/
Index: external/trimesh/gluit/glui_img_listbox_up_dis.c
--- external/trimesh/gluit/glui_img_listbox_up_dis.c (revision 0)
+++ external/trimesh/gluit/glui_img_listbox_up_dis.c (revision 0)
@@ -0,0 +1,42 @@
+
+
+int glui_img_listbox_up_dis[] = { 11, 17, /* width, height */
+ 127,127,127, 127,127,127, 127,127,127, 127,127,127, 127,127,127,
+ 127,127,127, 127,127,127, 127,127,127, 127,127,127, 127,127,127,
+ 127,127,127, 191,191,191, 127,127,127, 127,127,127, 127,127,127,
+ 127,127,127, 127,127,127, 127,127,127, 127,127,127, 127,127,127,
+ 127,127,127, 127,127,127, 191,191,191, 255,255,255, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 127,127,127, 127,127,127, 191,191,191, 255,255,255,
+ 191,191,191, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 127,127,127, 127,127,127, 191,191,191,
+ 255,255,255, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 127,127,127, 127,127,127,
+ 191,191,191, 255,255,255, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 191,191,191, 127,127,127,
+ 127,127,127, 191,191,191, 255,255,255, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 127,127,127, 127,127,127, 191,191,191, 255,255,255, 191,191,191,
+ 191,191,191, 191,191,191, 254,254,254, 191,191,191, 191,191,191,
+ 191,191,191, 127,127,127, 127,127,127, 191,191,191, 255,255,255,
+ 191,191,191, 191,191,191, 127,127,127, 127,127,127, 254,254,254,
+ 191,191,191, 191,191,191, 127,127,127, 127,127,127, 191,191,191,
+ 255,255,255, 191,191,191, 127,127,127, 127,127,127, 127,127,127,
+ 127,127,127, 254,254,254, 191,191,191, 127,127,127, 127,127,127,
+ 191,191,191, 255,255,255, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 191,191,191, 127,127,127,
+ 127,127,127, 191,191,191, 255,255,255, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 127,127,127, 127,127,127, 191,191,191, 255,255,255, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 127,127,127, 127,127,127, 191,191,191, 255,255,255,
+ 191,191,191, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 127,127,127, 127,127,127, 191,191,191,
+ 255,255,255, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 127,127,127, 127,127,127,
+ 191,191,191, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,252, 255,255,255, 127,127,127,
+ 127,127,127, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 127,127,127,
+};
Index: external/trimesh/gluit/glui_algebra3.cc
--- external/trimesh/gluit/glui_algebra3.cc (revision 0)
+++ external/trimesh/gluit/glui_algebra3.cc (revision 0)
@@ -0,0 +1,1037 @@
+/**************************************************************************
+
+ algebra3.cpp, algebra3.h - C++ Vector and Matrix Algebra routines
+
+ There are three vector classes and two matrix classes: vec2, vec3,
+ vec4, mat3, and mat4.
+
+ All the standard arithmetic operations are defined, with '*'
+ for dot product of two vectors and multiplication of two matrices,
+ and '^' for cross product of two vectors.
+
+ Additional functions include length(), normalize(), homogenize for
+ vectors, and print(), set(), apply() for all classes.
+
+ There is a function transpose() for matrices, but note that it
+ does not actually change the matrix,
+
+ When multiplied with a matrix, a vector is treated as a row vector
+ if it precedes the matrix (v*M), and as a column vector if it
+ follows the matrix (M*v).
+
+ Matrices are stored in row-major form.
+
+ A vector of one dimension (2d, 3d, or 4d) can be cast to a vector
+ of a higher or lower dimension. If casting to a higher dimension,
+ the new component is set by default to 1.0, unless a value is
+ specified:
+ vec3 a(1.0, 2.0, 3.0 );
+ vec4 b( a, 4.0 ); // now b == {1.0, 2.0, 3.0, 4.0};
+ When casting to a lower dimension, the vector is homogenized in
+ the lower dimension. E.g., if a 4d {X,Y,Z,W} is cast to 3d, the
+ resulting vector is {X/W, Y/W, Z/W}. It is up to the user to
+ insure the fourth component is not zero before casting.
+
+ There are also the following function for building matrices:
+ identity2D(), translation2D(), rotation2D(),
+ scaling2D(), identity3D(), translation3D(),
+ rotation3D(), rotation3Drad(), scaling3D(),
+ perspective3D()
+
+
+ ---------------------------------------------------------------------
+
+ Author: Jean-Francois DOUEg
+ Revised: Paul Rademacher
+ Version 3.2 - Feb 1998
+
+**************************************************************************/
+
+#include <math.h>
+#include "glui_algebra3.h"
+#include <ctype.h>
+
+/****************************************************************
+* *
+* vec2 Member functions *
+* *
+****************************************************************/
+
+/******************** vec2 CONSTRUCTORS ********************/
+
+vec2::vec2(void)
+{n[VX] = n[VY] = 0.0; }
+
+vec2::vec2(const float x, const float y)
+{ n[VX] = x; n[VY] = y; }
+
+vec2::vec2(const float d)
+{ n[VX] = n[VY] = d; }
+
+vec2::vec2(const vec2& v)
+{ n[VX] = v.n[VX]; n[VY] = v.n[VY]; }
+
+vec2::vec2(const vec3& v) // it is up to caller to avoid divide-by-zero
+{ n[VX] = v.n[VX]/v.n[VZ]; n[VY] = v.n[VY]/v.n[VZ]; };
+
+vec2::vec2(const vec3& v, int dropAxis) {
+ switch (dropAxis) {
+ case VX: n[VX] = v.n[VY]; n[VY] = v.n[VZ]; break;
+ case VY: n[VX] = v.n[VX]; n[VY] = v.n[VZ]; break;
+ default: n[VX] = v.n[VX]; n[VY] = v.n[VY]; break;
+ }
+}
+
+
+/******************** vec2 ASSIGNMENT OPERATORS ******************/
+
+vec2& vec2::operator = (const vec2& v)
+{ n[VX] = v.n[VX]; n[VY] = v.n[VY]; return *this; }
+
+vec2& vec2::operator += ( const vec2& v )
+{ n[VX] += v.n[VX]; n[VY] += v.n[VY]; return *this; }
+
+vec2& vec2::operator -= ( const vec2& v )
+{ n[VX] -= v.n[VX]; n[VY] -= v.n[VY]; return *this; }
+
+vec2& vec2::operator *= ( const float d )
+{ n[VX] *= d; n[VY] *= d; return *this; }
+
+vec2& vec2::operator /= ( const float d )
+{ float d_inv = 1.0f/d; n[VX] *= d_inv; n[VY] *= d_inv; return *this; }
+
+float& vec2::operator [] ( int i) {
+ if (i < VX || i > VY)
+ //VEC_ERROR("vec2 [] operator: illegal access; index = " << i
<< '\n')
+ VEC_ERROR("vec2 [] operator: illegal access" );
+ return n[i];
+}
+
+
+/******************** vec2 SPECIAL FUNCTIONS ********************/
+
+float vec2::length(void)
+{ return sqrt(length2()); }
+
+float vec2::length2(void)
+{ return n[VX]*n[VX] + n[VY]*n[VY]; }
+
+vec2& vec2::normalize(void) // it is up to caller to avoid divide-by-zero
+{ *this /= length(); return *this; }
+
+vec2& vec2::apply(V_FCT_PTR fct)
+{ n[VX] = (*fct)(n[VX]); n[VY] = (*fct)(n[VY]); return *this; }
+
+void vec2::set( float x, float y )
+{ n[VX] = x; n[VY] = y; }
+
+/******************** vec2 FRIENDS *****************************/
+
+vec2 operator - (const vec2& a)
+{ return vec2(-a.n[VX],-a.n[VY]); }
+
+vec2 operator + (const vec2& a, const vec2& b)
+{ return vec2(a.n[VX]+ b.n[VX], a.n[VY] + b.n[VY]); }
+
+vec2 operator - (const vec2& a, const vec2& b)
+{ return vec2(a.n[VX]-b.n[VX], a.n[VY]-b.n[VY]); }
+
+vec2 operator * (const vec2& a, const float d)
+{ return vec2(d*a.n[VX], d*a.n[VY]); }
+
+vec2 operator * (const float d, const vec2& a)
+{ return a*d; }
+
+vec2 operator * (const mat3& a, const vec2& v) {
+ vec3 av;
+
+ av.n[VX] = a.v[0].n[VX]*v.n[VX] + a.v[0].n[VY]*v.n[VY] + a.v[0].n[VZ];
+ av.n[VY] = a.v[1].n[VX]*v.n[VX] + a.v[1].n[VY]*v.n[VY] + a.v[1].n[VZ];
+ av.n[VZ] = a.v[2].n[VX]*v.n[VX] + a.v[2].n[VY]*v.n[VY] + a.v[2].n[VZ];
+ return av;
+}
+
+vec2 operator * (const vec2& v, mat3& a)
+{ return a.transpose() * v; }
+
+vec3 operator * (const mat3& a, const vec3& v) {
+ vec3 av;
+
+ av.n[VX] =
+ a.v[0].n[VX]*v.n[VX] + a.v[0].n[VY]*v.n[VY] + a.v[0].n[VZ]*v.n[VZ];
+ av.n[VY] =
+ a.v[1].n[VX]*v.n[VX] + a.v[1].n[VY]*v.n[VY] + a.v[1].n[VZ]*v.n[VZ];
+ av.n[VZ] =
+ a.v[2].n[VX]*v.n[VX] + a.v[2].n[VY]*v.n[VY] + a.v[2].n[VZ]*v.n[VZ];
+ return av;
+}
+
+vec3 operator * (const vec3& v, mat3& a)
+{ return a.transpose() * v; }
+
+float operator * (const vec2& a, const vec2& b)
+{ return (a.n[VX]*b.n[VX] + a.n[VY]*b.n[VY]); }
+
+vec2 operator / (const vec2& a, const float d)
+{ float d_inv = 1.0f/d; return vec2(a.n[VX]*d_inv, a.n[VY]*d_inv); }
+
+vec3 operator ^ (const vec2& a, const vec2& b)
+{ return vec3(0.0, 0.0, a.n[VX] * b.n[VY] - b.n[VX] * a.n[VY]); }
+
+int operator == (const vec2& a, const vec2& b)
+{ return (a.n[VX] == b.n[VX]) && (a.n[VY] == b.n[VY]); }
+
+int operator != (const vec2& a, const vec2& b)
+{ return !(a == b); }
+
+/*ostream& operator << (ostream& s, vec2& v)
+{ return s << "| " << v.n[VX] << ' ' << v.n[VY]
<< " |"; }
+*/
+
+/*istream& operator >> (istream& s, vec2& v) {
+ vec2 v_tmp;
+ char c = ' ';
+
+ while (isspace(c))
+ s >> c;
+ // The vectors can be formatted either as x y or | x y |
+ if (c == '|') {
+ s >> v_tmp[VX] >> v_tmp[VY];
+ while (s >> c && isspace(c)) ;
+ if (c != '|')
+ ;//s.set(_bad);
+ }
+ else {
+ s.putback(c);
+ s >> v_tmp[VX] >> v_tmp[VY];
+ }
+ if (s)
+ v = v_tmp;
+ return s;
+}
+*/
+
+void swap(vec2& a, vec2& b)
+{ vec2 tmp(a); a = b; b = tmp; }
+
+vec2 min_vec(const vec2& a, const vec2& b)
+{ return vec2(MIN(a.n[VX], b.n[VX]), MIN(a.n[VY], b.n[VY])); }
+
+vec2 max_vec(const vec2& a, const vec2& b)
+{ return vec2(MAX(a.n[VX], b.n[VX]), MAX(a.n[VY], b.n[VY])); }
+
+vec2 prod(const vec2& a, const vec2& b)
+{ return vec2(a.n[VX] * b.n[VX], a.n[VY] * b.n[VY]); }
+
+/****************************************************************
+* *
+* vec3 Member functions *
+* *
+****************************************************************/
+
+// CONSTRUCTORS
+
+vec3::vec3(void)
+{n[VX] = n[VY] = n[VZ] = 0.0;}
+
+vec3::vec3(const float x, const float y, const float z)
+{ n[VX] = x; n[VY] = y; n[VZ] = z; }
+
+vec3::vec3(const float d)
+{ n[VX] = n[VY] = n[VZ] = d; }
+
+vec3::vec3(const vec3& v)
+{ n[VX] = v.n[VX]; n[VY] = v.n[VY]; n[VZ] = v.n[VZ]; }
+
+vec3::vec3(const vec2& v)
+{ n[VX] = v.n[VX]; n[VY] = v.n[VY]; n[VZ] = 1.0; }
+
+vec3::vec3(const vec2& v, float d)
+{ n[VX] = v.n[VX]; n[VY] = v.n[VY]; n[VZ] = d; }
+
+vec3::vec3(const vec4& v) // it is up to caller to avoid divide-by-zero
+{ n[VX] = v.n[VX] / v.n[VW]; n[VY] = v.n[VY] / v.n[VW];
+ n[VZ] = v.n[VZ] / v.n[VW]; }
+
+vec3::vec3(const vec4& v, int dropAxis) {
+ switch (dropAxis) {
+ case VX: n[VX] = v.n[VY]; n[VY] = v.n[VZ]; n[VZ] = v.n[VW]; break;
+ case VY: n[VX] = v.n[VX]; n[VY] = v.n[VZ]; n[VZ] = v.n[VW]; break;
+ case VZ: n[VX] = v.n[VX]; n[VY] = v.n[VY]; n[VZ] = v.n[VW]; break;
+ default: n[VX] = v.n[VX]; n[VY] = v.n[VY]; n[VZ] = v.n[VZ]; break;
+ }
+}
+
+
+// ASSIGNMENT OPERATORS
+
+vec3& vec3::operator = (const vec3& v)
+{ n[VX] = v.n[VX]; n[VY] = v.n[VY]; n[VZ] = v.n[VZ]; return *this; }
+
+vec3& vec3::operator += ( const vec3& v )
+{ n[VX] += v.n[VX]; n[VY] += v.n[VY]; n[VZ] += v.n[VZ]; return *this; }
+
+vec3& vec3::operator -= ( const vec3& v )
+{ n[VX] -= v.n[VX]; n[VY] -= v.n[VY]; n[VZ] -= v.n[VZ]; return *this; }
+
+vec3& vec3::operator *= ( const float d )
+{ n[VX] *= d; n[VY] *= d; n[VZ] *= d; return *this; }
+
+vec3& vec3::operator /= ( const float d )
+{ float d_inv = 1.0f/d; n[VX] *= d_inv; n[VY] *= d_inv; n[VZ] *= d_inv;
+ return *this; }
+
+float& vec3::operator [] ( int i) {
+ if (i < VX || i > VZ)
+ //VEC_ERROR("vec3 [] operator: illegal access; index = " << i
<< '\n')
+ VEC_ERROR("vec3 [] operator: illegal access" );
+
+ return n[i];
+}
+
+
+// SPECIAL FUNCTIONS
+
+float vec3::length(void)
+{ return sqrt(length2()); }
+
+float vec3::length2(void)
+{ return n[VX]*n[VX] + n[VY]*n[VY] + n[VZ]*n[VZ]; }
+
+vec3& vec3::normalize(void) // it is up to caller to avoid divide-by-zero
+{ *this /= length(); return *this; }
+
+vec3& vec3::homogenize(void) // it is up to caller to avoid divide-by-zero
+{ n[VX] /= n[VZ]; n[VY] /= n[VZ]; n[VZ] = 1.0; return *this; }
+
+vec3& vec3::apply(V_FCT_PTR fct)
+{ n[VX] = (*fct)(n[VX]); n[VY] = (*fct)(n[VY]); n[VZ] = (*fct)(n[VZ]);
+return *this; }
+
+void vec3::set( float x, float y, float z ) // set vector
+{ n[VX] = x; n[VY] = y; n[VZ] = z; }
+
+void vec3::print( FILE *file, char *name ) // print vector to a file
+{
+ fprintf( file, "%s: <%f, %f, %f>\n", name, n[VX], n[VY], n[VZ] );
+}
+
+// FRIENDS
+
+vec3 operator - (const vec3& a)
+{ return vec3(-a.n[VX],-a.n[VY],-a.n[VZ]); }
+
+vec3 operator + (const vec3& a, const vec3& b)
+{ return vec3(a.n[VX]+ b.n[VX], a.n[VY] + b.n[VY], a.n[VZ] + b.n[VZ]); }
+
+vec3 operator - (const vec3& a, const vec3& b)
+{ return vec3(a.n[VX]-b.n[VX], a.n[VY]-b.n[VY], a.n[VZ]-b.n[VZ]); }
+
+vec3 operator * (const vec3& a, const float d)
+{ return vec3(d*a.n[VX], d*a.n[VY], d*a.n[VZ]); }
+
+vec3 operator * (const float d, const vec3& a)
+{ return a*d; }
+
+vec3 operator * (const mat4& a, const vec3& v)
+{ return a * vec4(v); }
+
+vec3 operator * (const vec3& v, mat4& a)
+{ return a.transpose() * v; }
+
+float operator * (const vec3& a, const vec3& b)
+{ return (a.n[VX]*b.n[VX] + a.n[VY]*b.n[VY] + a.n[VZ]*b.n[VZ]); }
+
+vec3 operator / (const vec3& a, const float d)
+{ float d_inv = 1.0f/d; return vec3(a.n[VX]*d_inv, a.n[VY]*d_inv,
+ a.n[VZ]*d_inv); }
+
+vec3 operator ^ (const vec3& a, const vec3& b) {
+ return vec3(a.n[VY]*b.n[VZ] - a.n[VZ]*b.n[VY],
+ a.n[VZ]*b.n[VX] - a.n[VX]*b.n[VZ],
+ a.n[VX]*b.n[VY] - a.n[VY]*b.n[VX]);
+}
+
+int operator == (const vec3& a, const vec3& b)
+{ return (a.n[VX] == b.n[VX]) && (a.n[VY] == b.n[VY]) && (a.n[VZ] ==
b.n[VZ]);
+}
+
+int operator != (const vec3& a, const vec3& b)
+{ return !(a == b); }
+
+/*ostream& operator << (ostream& s, vec3& v)
+{ return s << "| " << v.n[VX] << ' ' << v.n[VY]
<< ' ' << v.n[VZ] << " |"; }
+
+istream& operator >> (istream& s, vec3& v) {
+ vec3 v_tmp;
+ char c = ' ';
+
+ while (isspace(c))
+ s >> c;
+ // The vectors can be formatted either as x y z or | x y z |
+ if (c == '|') {
+ s >> v_tmp[VX] >> v_tmp[VY] >> v_tmp[VZ];
+ while (s >> c && isspace(c)) ;
+ if (c != '|')
+ ;//s.set(_bad);
+ }
+ else {
+ s.putback(c);
+ s >> v_tmp[VX] >> v_tmp[VY] >> v_tmp[VZ];
+ }
+ if (s)
+ v = v_tmp;
+ return s;
+}
+*/
+
+void swap(vec3& a, vec3& b)
+{ vec3 tmp(a); a = b; b = tmp; }
+
+vec3 min_vec(const vec3& a, const vec3& b)
+{ return vec3(MIN(a.n[VX], b.n[VX]), MIN(a.n[VY], b.n[VY]), MIN(a.n[VZ],
+ b.n[VZ])); }
+
+vec3 max_vec(const vec3& a, const vec3& b)
+{ return vec3(MAX(a.n[VX], b.n[VX]), MAX(a.n[VY], b.n[VY]), MAX(a.n[VZ],
+ b.n[VZ])); }
+
+vec3 prod(const vec3& a, const vec3& b)
+{ return vec3(a.n[VX] * b.n[VX], a.n[VY] * b.n[VY], a.n[VZ] * b.n[VZ]); }
+
+/****************************************************************
+* *
+* vec4 Member functions *
+* *
+****************************************************************/
+
+// CONSTRUCTORS
+
+vec4::vec4(void)
+{n[VX] = n[VY] = n[VZ] = 0.0; n[VW] = 1.0; }
+
+vec4::vec4(const float x, const float y, const float z, const float w)
+{ n[VX] = x; n[VY] = y; n[VZ] = z; n[VW] = w; }
+
+vec4::vec4(const float d)
+{ n[VX] = n[VY] = n[VZ] = n[VW] = d; }
+
+vec4::vec4(const vec4& v)
+{ n[VX] = v.n[VX]; n[VY] = v.n[VY]; n[VZ] = v.n[VZ]; n[VW] = v.n[VW]; }
+
+vec4::vec4(const vec3& v)
+{ n[VX] = v.n[VX]; n[VY] = v.n[VY]; n[VZ] = v.n[VZ]; n[VW] = 1.0; }
+
+vec4::vec4(const vec3& v, const float d)
+{ n[VX] = v.n[VX]; n[VY] = v.n[VY]; n[VZ] = v.n[VZ]; n[VW] = d; }
+
+
+// ASSIGNMENT OPERATORS
+
+vec4& vec4::operator = (const vec4& v)
+{ n[VX] = v.n[VX]; n[VY] = v.n[VY]; n[VZ] = v.n[VZ]; n[VW] = v.n[VW];
+return *this; }
+
+vec4& vec4::operator += ( const vec4& v )
+{ n[VX] += v.n[VX]; n[VY] += v.n[VY]; n[VZ] += v.n[VZ]; n[VW] += v.n[VW];
+return *this; }
+
+vec4& vec4::operator -= ( const vec4& v )
+{ n[VX] -= v.n[VX]; n[VY] -= v.n[VY]; n[VZ] -= v.n[VZ]; n[VW] -= v.n[VW];
+return *this; }
+
+vec4& vec4::operator *= ( const float d )
+{ n[VX] *= d; n[VY] *= d; n[VZ] *= d; n[VW] *= d; return *this; }
+
+vec4& vec4::operator /= ( const float d )
+{ float d_inv = 1.0f/d; n[VX] *= d_inv; n[VY] *= d_inv; n[VZ] *= d_inv;
+ n[VW] *= d_inv; return *this; }
+
+float& vec4::operator [] ( int i) {
+ if (i < VX || i > VW)
+ //VEC_ERROR("vec4 [] operator: illegal access; index = " << i
<< '\n')
+ VEC_ERROR("vec4 [] operator: illegal access" );
+
+ return n[i];
+}
+
+
+// SPECIAL FUNCTIONS
+
+float vec4::length(void)
+{ return sqrt(length2()); }
+
+float vec4::length2(void)
+{ return n[VX]*n[VX] + n[VY]*n[VY] + n[VZ]*n[VZ] + n[VW]*n[VW]; }
+
+vec4& vec4::normalize(void) // it is up to caller to avoid divide-by-zero
+{ *this /= length(); return *this; }
+
+vec4& vec4::homogenize(void) // it is up to caller to avoid divide-by-zero
+{ n[VX] /= n[VW]; n[VY] /= n[VW]; n[VZ] /= n[VW]; n[VW] = 1.0; return *this; }
+
+vec4& vec4::apply(V_FCT_PTR fct)
+{ n[VX] = (*fct)(n[VX]); n[VY] = (*fct)(n[VY]); n[VZ] = (*fct)(n[VZ]);
+n[VW] = (*fct)(n[VW]); return *this; }
+
+void vec4::print( FILE *file, char *name ) // print vector to a file
+{
+ fprintf( file, "%s: <%f, %f, %f, %f>\n", name, n[VX], n[VY], n[VZ],
n[VW] );
+}
+
+void vec4::set( float x, float y, float z, float a )
+{
+ n[0] = x; n[1] = y; n[2] = z; n[3] = a;
+}
+
+
+// FRIENDS
+
+vec4 operator - (const vec4& a)
+{ return vec4(-a.n[VX],-a.n[VY],-a.n[VZ],-a.n[VW]); }
+
+vec4 operator + (const vec4& a, const vec4& b)
+{ return vec4(a.n[VX] + b.n[VX], a.n[VY] + b.n[VY], a.n[VZ] + b.n[VZ],
+ a.n[VW] + b.n[VW]); }
+
+vec4 operator - (const vec4& a, const vec4& b)
+{ return vec4(a.n[VX] - b.n[VX], a.n[VY] - b.n[VY], a.n[VZ] - b.n[VZ],
+ a.n[VW] - b.n[VW]); }
+
+vec4 operator * (const vec4& a, const float d)
+{ return vec4(d*a.n[VX], d*a.n[VY], d*a.n[VZ], d*a.n[VW] ); }
+
+vec4 operator * (const float d, const vec4& a)
+{ return a*d; }
+
+vec4 operator * (const mat4& a, const vec4& v) {
+ #define ROWCOL(i) a.v[i].n[0]*v.n[VX] + a.v[i].n[1]*v.n[VY] \
+ + a.v[i].n[2]*v.n[VZ] + a.v[i].n[3]*v.n[VW]
+ return vec4(ROWCOL(0), ROWCOL(1), ROWCOL(2), ROWCOL(3));
+ #undef ROWCOL
+}
+
+vec4 operator * (const vec4& v, mat4& a)
+{ return a.transpose() * v; }
+
+float operator * (const vec4& a, const vec4& b)
+{ return (a.n[VX]*b.n[VX] + a.n[VY]*b.n[VY] + a.n[VZ]*b.n[VZ] +
+ a.n[VW]*b.n[VW]); }
+
+vec4 operator / (const vec4& a, const float d)
+{ float d_inv = 1.0f/d; return vec4(a.n[VX]*d_inv, a.n[VY]*d_inv, a.n[VZ]*d_inv,
+ a.n[VW]*d_inv); }
+
+int operator == (const vec4& a, const vec4& b)
+{ return (a.n[VX] == b.n[VX]) && (a.n[VY] == b.n[VY]) && (a.n[VZ] ==
b.n[VZ])
+ && (a.n[VW] == b.n[VW]); }
+
+int operator != (const vec4& a, const vec4& b)
+{ return !(a == b); }
+
+/*ostream& operator << (ostream& s, vec4& v)
+{ return s << "| " << v.n[VX] << ' ' << v.n[VY]
<< ' ' << v.n[VZ] << ' '
+ << v.n[VW] << " |"; }
+
+istream& operator >> (istream& s, vec4& v) {
+ vec4 v_tmp;
+ char c = ' ';
+
+ while (isspace(c))
+ s >> c;
+ // The vectors can be formatted either as x y z w or | x y z w |
+ if (c == '|') {
+ s >> v_tmp[VX] >> v_tmp[VY] >> v_tmp[VZ] >> v_tmp[VW];
+ while (s >> c && isspace(c)) ;
+ if (c != '|')
+ ;//s.set(_bad);
+ }
+ else {
+ s.putback(c);
+ s >> v_tmp[VX] >> v_tmp[VY] >> v_tmp[VZ] >> v_tmp[VW];
+ }
+ if (s)
+ v = v_tmp;
+ return s;
+}
+*/
+void swap(vec4& a, vec4& b)
+{ vec4 tmp(a); a = b; b = tmp; }
+
+vec4 min_vec(const vec4& a, const vec4& b)
+{ return vec4(MIN(a.n[VX], b.n[VX]), MIN(a.n[VY], b.n[VY]), MIN(a.n[VZ],
+ b.n[VZ]), MIN(a.n[VW], b.n[VW])); }
+
+vec4 max_vec(const vec4& a, const vec4& b)
+{ return vec4(MAX(a.n[VX], b.n[VX]), MAX(a.n[VY], b.n[VY]), MAX(a.n[VZ],
+ b.n[VZ]), MAX(a.n[VW], b.n[VW])); }
+
+vec4 prod(const vec4& a, const vec4& b)
+{ return vec4(a.n[VX] * b.n[VX], a.n[VY] * b.n[VY], a.n[VZ] * b.n[VZ],
+ a.n[VW] * b.n[VW]); }
+
+
+/****************************************************************
+* *
+* mat3 member functions *
+* *
+****************************************************************/
+
+// CONSTRUCTORS
+
+mat3::mat3(void) { *this = identity2D(); }
+
+mat3::mat3(const vec3& v0, const vec3& v1, const vec3& v2)
+{ this->set( v0, v1, v2 ); };
+
+mat3::mat3(const float d)
+{ v[0] = v[1] = v[2] = vec3(d); }
+
+mat3::mat3(const mat3& m)
+{ v[0] = m.v[0]; v[1] = m.v[1]; v[2] = m.v[2]; }
+
+
+// ASSIGNMENT OPERATORS
+
+mat3& mat3::operator = ( const mat3& m )
+{ v[0] = m.v[0]; v[1] = m.v[1]; v[2] = m.v[2]; return *this; }
+
+mat3& mat3::operator += ( const mat3& m )
+{ v[0] += m.v[0]; v[1] += m.v[1]; v[2] += m.v[2]; return *this; }
+
+mat3& mat3::operator -= ( const mat3& m )
+{ v[0] -= m.v[0]; v[1] -= m.v[1]; v[2] -= m.v[2]; return *this; }
+
+mat3& mat3::operator *= ( const float d )
+{ v[0] *= d; v[1] *= d; v[2] *= d; return *this; }
+
+mat3& mat3::operator /= ( const float d )
+{ v[0] /= d; v[1] /= d; v[2] /= d; return *this; }
+
+vec3& mat3::operator [] ( int i) {
+ if (i < VX || i > VZ)
+ //VEC_ERROR("mat3 [] operator: illegal access; index = " << i
<< '\n')
+ VEC_ERROR("mat3 [] operator: illegal access" );
+ return v[i];
+}
+
+void mat3::set( const vec3& v0, const vec3& v1, const vec3& v2 ) {
+ v[0] = v0; v[1] = v1; v[2] = v2;
+}
+
+// SPECIAL FUNCTIONS
+
+mat3 mat3::transpose(void) {
+ return mat3(vec3(v[0][0], v[1][0], v[2][0]),
+ vec3(v[0][1], v[1][1], v[2][1]),
+ vec3(v[0][2], v[1][2], v[2][2]));
+}
+
+mat3 mat3::inverse(void) // Gauss-Jordan elimination with partial pivoting
+ {
+ mat3 a(*this), // As a evolves from original mat into identity
+ b(identity2D()); // b evolves from identity into inverse(a)
+ int i, j, i1;
+
+ // Loop over cols of a from left to right, eliminating above and below diag
+ for (j=0; j<3; j++) { // Find largest pivot in column j among rows j..2
+ i1 = j; // Row with largest pivot candidate
+ for (i=j+1; i<3; i++)
+ if (fabs(a.v[i].n[j]) > fabs(a.v[i1].n[j]))
+ i1 = i;
+
+ // Swap rows i1 and j in a and b to put pivot on diagonal
+ swap(a.v[i1], a.v[j]);
+ swap(b.v[i1], b.v[j]);
+
+ // Scale row j to have a unit diagonal
+ if (a.v[j].n[j]==0.)
+ VEC_ERROR("mat3::inverse: singular matrix; can't invert\n");
+ b.v[j] /= a.v[j].n[j];
+ a.v[j] /= a.v[j].n[j];
+
+ // Eliminate off-diagonal elems in col j of a, doing identical ops to b
+ for (i=0; i<3; i++)
+ if (i!=j) {
+ b.v[i] -= a.v[i].n[j]*b.v[j];
+ a.v[i] -= a.v[i].n[j]*a.v[j];
+ }
+ }
+ return b;
+}
+
+mat3& mat3::apply(V_FCT_PTR fct) {
+ v[VX].apply(fct);
+ v[VY].apply(fct);
+ v[VZ].apply(fct);
+ return *this;
+}
+
+
+// FRIENDS
+
+mat3 operator - (const mat3& a)
+{ return mat3(-a.v[0], -a.v[1], -a.v[2]); }
+
+mat3 operator + (const mat3& a, const mat3& b)
+{ return mat3(a.v[0] + b.v[0], a.v[1] + b.v[1], a.v[2] + b.v[2]); }
+
+mat3 operator - (const mat3& a, const mat3& b)
+{ return mat3(a.v[0] - b.v[0], a.v[1] - b.v[1], a.v[2] - b.v[2]); }
+
+mat3 operator * (mat3& a, mat3& b) {
+ #define ROWCOL(i, j) \
+ a.v[i].n[0]*b.v[0][j] + a.v[i].n[1]*b.v[1][j] + a.v[i].n[2]*b.v[2][j]
+ return mat3(vec3(ROWCOL(0,0), ROWCOL(0,1), ROWCOL(0,2)),
+ vec3(ROWCOL(1,0), ROWCOL(1,1), ROWCOL(1,2)),
+ vec3(ROWCOL(2,0), ROWCOL(2,1), ROWCOL(2,2)));
+ #undef ROWCOL
+}
+
+mat3 operator * (const mat3& a, const float d)
+{ return mat3(a.v[0] * d, a.v[1] * d, a.v[2] * d); }
+
+mat3 operator * (const float d, const mat3& a)
+{ return a*d; }
+
+mat3 operator / (const mat3& a, const float d)
+{ return mat3(a.v[0] / d, a.v[1] / d, a.v[2] / d); }
+
+int operator == (const mat3& a, const mat3& b)
+{ return (a.v[0] == b.v[0]) && (a.v[1] == b.v[1]) && (a.v[2] == b.v[2]);
}
+
+int operator != (const mat3& a, const mat3& b)
+{ return !(a == b); }
+
+/*ostream& operator << (ostream& s, mat3& m)
+{ return s << m.v[VX] << '\n' << m.v[VY] << '\n'
<< m.v[VZ]; }
+
+istream& operator >> (istream& s, mat3& m) {
+ mat3 m_tmp;
+
+ s >> m_tmp[VX] >> m_tmp[VY] >> m_tmp[VZ];
+ if (s)
+ m = m_tmp;
+ return s;
+}
+*/
+
+void swap(mat3& a, mat3& b)
+{ mat3 tmp(a); a = b; b = tmp; }
+
+void mat3::print( FILE *file, char *name )
+{
+ int i, j;
+
+ fprintf( stderr, "%s:\n", name );
+
+ for( i = 0; i < 3; i++ )
+ {
+ fprintf( stderr, " " );
+ for( j = 0; j < 3; j++ )
+ {
+ fprintf( stderr, "%f ", v[i][j] );
+ }
+ fprintf( stderr, "\n" );
+ }
+}
+
+
+
+/****************************************************************
+* *
+* mat4 member functions *
+* *
+****************************************************************/
+
+// CONSTRUCTORS
+
+mat4::mat4(void) { *this = identity3D();}
+
+mat4::mat4(const vec4& v0, const vec4& v1, const vec4& v2, const vec4&
v3)
+{ v[0] = v0; v[1] = v1; v[2] = v2; v[3] = v3; }
+
+mat4::mat4(const float d)
+{ v[0] = v[1] = v[2] = v[3] = vec4(d); }
+
+mat4::mat4(const mat4& m)
+{ v[0] = m.v[0]; v[1] = m.v[1]; v[2] = m.v[2]; v[3] = m.v[3]; }
+
+mat4::mat4(const float a00, const float a01, const float a02, const float a03,
+ const float a10, const float a11, const float a12, const float a13,
+ const float a20, const float a21, const float a22, const float a23,
+ const float a30, const float a31, const float a32, const float a33 )
+{
+ v[0][0] = a00; v[0][1] = a01; v[0][2] = a02; v[0][3] = a03;
+ v[1][0] = a10; v[1][1] = a11; v[1][2] = a12; v[1][3] = a13;
+ v[2][0] = a20; v[2][1] = a21; v[2][2] = a22; v[2][3] = a23;
+ v[3][0] = a30; v[3][1] = a31; v[3][2] = a32; v[3][3] = a33;
+}
+
+// ASSIGNMENT OPERATORS
+
+mat4& mat4::operator = ( const mat4& m )
+{ v[0] = m.v[0]; v[1] = m.v[1]; v[2] = m.v[2]; v[3] = m.v[3];
+return *this; }
+
+mat4& mat4::operator += ( const mat4& m )
+{ v[0] += m.v[0]; v[1] += m.v[1]; v[2] += m.v[2]; v[3] += m.v[3];
+return *this; }
+
+mat4& mat4::operator -= ( const mat4& m )
+{ v[0] -= m.v[0]; v[1] -= m.v[1]; v[2] -= m.v[2]; v[3] -= m.v[3];
+return *this; }
+
+mat4& mat4::operator *= ( const float d )
+{ v[0] *= d; v[1] *= d; v[2] *= d; v[3] *= d; return *this; }
+
+mat4& mat4::operator /= ( const float d )
+{ v[0] /= d; v[1] /= d; v[2] /= d; v[3] /= d; return *this; }
+
+vec4& mat4::operator [] ( int i) {
+ if (i < VX || i > VW)
+ //VEC_ERROR("mat4 [] operator: illegal access; index = " << i
<< '\n')
+ VEC_ERROR("mat4 [] operator: illegal access" );
+ return v[i];
+}
+
+// SPECIAL FUNCTIONS;
+
+mat4 mat4::transpose(void) {
+ return mat4(vec4(v[0][0], v[1][0], v[2][0], v[3][0]),
+ vec4(v[0][1], v[1][1], v[2][1], v[3][1]),
+ vec4(v[0][2], v[1][2], v[2][2], v[3][2]),
+ vec4(v[0][3], v[1][3], v[2][3], v[3][3]));
+}
+
+mat4 mat4::inverse(void) // Gauss-Jordan elimination with partial pivoting
+{
+ mat4 a(*this), // As a evolves from original mat into identity
+ b(identity3D()); // b evolves from identity into inverse(a)
+ int i, j, i1;
+
+ // Loop over cols of a from left to right, eliminating above and below diag
+ for (j=0; j<4; j++) { // Find largest pivot in column j among rows j..3
+ i1 = j; // Row with largest pivot candidate
+ for (i=j+1; i<4; i++)
+ if (fabs(a.v[i].n[j]) > fabs(a.v[i1].n[j]))
+ i1 = i;
+
+ // Swap rows i1 and j in a and b to put pivot on diagonal
+ swap(a.v[i1], a.v[j]);
+ swap(b.v[i1], b.v[j]);
+
+ // Scale row j to have a unit diagonal
+ if (a.v[j].n[j]==0.)
+ VEC_ERROR("mat4::inverse: singular matrix; can't invert\n");
+ b.v[j] /= a.v[j].n[j];
+ a.v[j] /= a.v[j].n[j];
+
+ // Eliminate off-diagonal elems in col j of a, doing identical ops to b
+ for (i=0; i<4; i++)
+ if (i!=j) {
+ b.v[i] -= a.v[i].n[j]*b.v[j];
+ a.v[i] -= a.v[i].n[j]*a.v[j];
+ }
+ }
+ return b;
+}
+
+mat4& mat4::apply(V_FCT_PTR fct)
+{ v[VX].apply(fct); v[VY].apply(fct); v[VZ].apply(fct); v[VW].apply(fct);
+return *this; }
+
+
+void mat4::print( FILE *file, char *name )
+{
+ int i, j;
+
+ fprintf( stderr, "%s:\n", name );
+
+ for( i = 0; i < 4; i++ )
+ {
+ fprintf( stderr, " " );
+ for( j = 0; j < 4; j++ )
+ {
+ fprintf( stderr, "%f ", v[i][j] );
+ }
+ fprintf( stderr, "\n" );
+ }
+}
+
+void mat4::swap_rows( int i, int j )
+{
+ vec4 t;
+
+ t = v[i];
+ v[i] = v[j];
+ v[j] = t;
+}
+
+void mat4::swap_cols( int i, int j )
+{
+ float t;
+ int k;
+
+ for(k=0; k<4; k++ ) {
+ t = v[k][i];
+ v[k][i] = v[k][j];
+ v[k][j] = t;
+ }
+}
+
+
+// FRIENDS
+
+mat4 operator - (const mat4& a)
+{ return mat4(-a.v[0], -a.v[1], -a.v[2], -a.v[3]); }
+
+mat4 operator + (const mat4& a, const mat4& b)
+{ return mat4(a.v[0] + b.v[0], a.v[1] + b.v[1], a.v[2] + b.v[2],
+ a.v[3] + b.v[3]);
+}
+
+mat4 operator - (const mat4& a, const mat4& b)
+{ return mat4(a.v[0] - b.v[0], a.v[1] - b.v[1], a.v[2] - b.v[2], a.v[3] - b.v[3]); }
+
+mat4 operator * (mat4& a, mat4& b) {
+ #define ROWCOL(i, j) a.v[i].n[0]*b.v[0][j] + a.v[i].n[1]*b.v[1][j] + \
+ a.v[i].n[2]*b.v[2][j] + a.v[i].n[3]*b.v[3][j]
+ return mat4(
+ vec4(ROWCOL(0,0), ROWCOL(0,1), ROWCOL(0,2), ROWCOL(0,3)),
+ vec4(ROWCOL(1,0), ROWCOL(1,1), ROWCOL(1,2), ROWCOL(1,3)),
+ vec4(ROWCOL(2,0), ROWCOL(2,1), ROWCOL(2,2), ROWCOL(2,3)),
+ vec4(ROWCOL(3,0), ROWCOL(3,1), ROWCOL(3,2), ROWCOL(3,3))
+ );
+}
+
+mat4 operator * (const mat4& a, const float d)
+{ return mat4(a.v[0] * d, a.v[1] * d, a.v[2] * d, a.v[3] * d); }
+
+mat4 operator * (const float d, const mat4& a)
+{ return a*d; }
+
+mat4 operator / (const mat4& a, const float d)
+{ return mat4(a.v[0] / d, a.v[1] / d, a.v[2] / d, a.v[3] / d); }
+
+int operator == (const mat4& a, const mat4& b)
+{ return ((a.v[0] == b.v[0]) && (a.v[1] == b.v[1]) && (a.v[2] == b.v[2])
&&
+ (a.v[3] == b.v[3])); }
+
+int operator != (const mat4& a, const mat4& b)
+{ return !(a == b); }
+
+/*ostream& operator << (ostream& s, mat4& m)
+{ return s << m.v[VX] << '\n' << m.v[VY] << '\n'
<< m.v[VZ] << '\n' << m.v[VW]; }
+
+istream& operator >> (istream& s, mat4& m)
+{
+ mat4 m_tmp;
+
+ s >> m_tmp[VX] >> m_tmp[VY] >> m_tmp[VZ] >> m_tmp[VW];
+ if (s)
+ m = m_tmp;
+ return s;
+}
+*/
+void swap(mat4& a, mat4& b)
+{ mat4 tmp(a); a = b; b = tmp; }
+
+
+/****************************************************************
+* *
+* 2D functions and 3D functions *
+* *
+****************************************************************/
+
+mat3 identity2D(void)
+{ return mat3(vec3(1.0, 0.0, 0.0),
+ vec3(0.0, 1.0, 0.0),
+ vec3(0.0, 0.0, 1.0)); }
+
+mat3 translation2D(vec2& v)
+{ return mat3(vec3(1.0, 0.0, v[VX]),
+ vec3(0.0, 1.0, v[VY]),
+ vec3(0.0, 0.0, 1.0)); }
+
+mat3 rotation2D(vec2& Center, const float angleDeg) {
+ float angleRad = angleDeg * M_PI / 180.0f,
+ c = cos(angleRad),
+ s = sin(angleRad);
+
+ return mat3(vec3(c, -s, Center[VX] * (1.0f-c) + Center[VY] * s),
+ vec3(s, c, Center[VY] * (1.0f-c) - Center[VX] * s),
+ vec3(0.0, 0.0, 1.0));
+}
+
+mat3 scaling2D(vec2& scaleVector)
+{ return mat3(vec3(scaleVector[VX], 0.0, 0.0),
+ vec3(0.0, scaleVector[VY], 0.0),
+ vec3(0.0, 0.0, 1.0)); }
+
+mat4 identity3D(void)
+{ return mat4(vec4(1.0, 0.0, 0.0, 0.0),
+ vec4(0.0, 1.0, 0.0, 0.0),
+ vec4(0.0, 0.0, 1.0, 0.0),
+ vec4(0.0, 0.0, 0.0, 1.0)); }
+
+mat4 translation3D(vec3& v)
+{ return mat4(vec4(1.0, 0.0, 0.0, v[VX]),
+ vec4(0.0, 1.0, 0.0, v[VY]),
+ vec4(0.0, 0.0, 1.0, v[VZ]),
+ vec4(0.0, 0.0, 0.0, 1.0)); }
+
+mat4 rotation3D(vec3& Axis, const float angleDeg) {
+ float angleRad = angleDeg * M_PI / 180.0f,
+ c = cos(angleRad),
+ s = sin(angleRad),
+ t = 1.0f - c;
+
+ Axis.normalize();
+ return mat4(vec4(t * Axis[VX] * Axis[VX] + c,
+ t * Axis[VX] * Axis[VY] - s * Axis[VZ],
+ t * Axis[VX] * Axis[VZ] + s * Axis[VY],
+ 0.0),
+ vec4(t * Axis[VX] * Axis[VY] + s * Axis[VZ],
+ t * Axis[VY] * Axis[VY] + c,
+ t * Axis[VY] * Axis[VZ] - s * Axis[VX],
+ 0.0),
+ vec4(t * Axis[VX] * Axis[VZ] - s * Axis[VY],
+ t * Axis[VY] * Axis[VZ] + s * Axis[VX],
+ t * Axis[VZ] * Axis[VZ] + c,
+ 0.0),
+ vec4(0.0, 0.0, 0.0, 1.0));
+}
+
+mat4 rotation3Drad(vec3& Axis, const float angleRad) {
+ float c = cos(angleRad),
+ s = sin(angleRad),
+ t = 1.0f - c;
+
+ Axis.normalize();
+ return mat4(vec4(t * Axis[VX] * Axis[VX] + c,
+ t * Axis[VX] * Axis[VY] - s * Axis[VZ],
+ t * Axis[VX] * Axis[VZ] + s * Axis[VY],
+ 0.0),
+ vec4(t * Axis[VX] * Axis[VY] + s * Axis[VZ],
+ t * Axis[VY] * Axis[VY] + c,
+ t * Axis[VY] * Axis[VZ] - s * Axis[VX],
+ 0.0),
+ vec4(t * Axis[VX] * Axis[VZ] - s * Axis[VY],
+ t * Axis[VY] * Axis[VZ] + s * Axis[VX],
+ t * Axis[VZ] * Axis[VZ] + c,
+ 0.0),
+ vec4(0.0, 0.0, 0.0, 1.0));
+}
+
+mat4 scaling3D(vec3& scaleVector)
+{ return mat4(vec4(scaleVector[VX], 0.0, 0.0, 0.0),
+ vec4(0.0, scaleVector[VY], 0.0, 0.0),
+ vec4(0.0, 0.0, scaleVector[VZ], 0.0),
+ vec4(0.0, 0.0, 0.0, 1.0)); }
+
+mat4 perspective3D(const float d)
+{ return mat4(vec4(1.0, 0.0, 0.0, 0.0),
+ vec4(0.0, 1.0, 0.0, 0.0),
+ vec4(0.0, 0.0, 1.0, 0.0),
+ vec4(0.0, 0.0, 1.0f/d, 0.0)); }
Index: external/trimesh/gluit/glui_slider.cc
--- external/trimesh/gluit/glui_slider.cc (revision 0)
+++ external/trimesh/gluit/glui_slider.cc (revision 0)
@@ -0,0 +1,725 @@
+/****************************************************************************
+
+ GLUI User Interface Toolkit
+ ---------------------------
+
+ glui_slider - GLUI_Slider control class
+
+
+ --------------------------------------------------
+
+ Copyright (c) 1998 Paul Rademacher
+
+ This program is freely distributable without licensing fees and is
+ provided without guarantee or warrantee expressed or implied. This
+ program is -not- in the public domain.
+
+*****************************************************************************/
+
+#include "glui.h"
+#include "glui_stdinc.h"
+
+#define GLUI_SLIDER_FONT_HEIGHT 9
+#define GLUI_SLIDER_FONT_DROP 3
+#define GLUI_SLIDER_FONT_FULL_HEIGHT (GLUI_SLIDER_FONT_HEIGHT + GLUI_SLIDER_FONT_DROP)
+#define GLUI_SLIDER_FONT_MID_HEIGHT 4
+
+#define GLUI_SLIDER_NAME_INDENT 6
+#define GLUI_SLIDER_NAME_SIDE_BORDER 2
+#define GLUI_SLIDER_NAME_TOP_BORDER 2
+#define GLUI_SLIDER_NAME_BOTTOM_BORDER 0
+
+#define GLUI_SLIDER_VAL_TOP_BORDER 3
+#define GLUI_SLIDER_VAL_SIDE_BORDER 4
+
+#define GLUI_SLIDER_KNOB_HALF_WIDTH 3
+#define GLUI_SLIDER_KNOB_HALF_HEIGHT 8
+#define GLUI_SLIDER_KNOB_SIDE_BORDER 4
+#define GLUI_SLIDER_KNOB_TOP_BORDER 2
+#define GLUI_SLIDER_KNOB_BOTTOM_BORDER 2
+#define GLUI_SLIDER_KNOB_WHITE 254
+#define GLUI_SLIDER_KNOB_L_GREY 230
+#define GLUI_SLIDER_KNOB_GREY 218
+#define GLUI_SLIDER_KNOB_D_GREY 115
+#define GLUI_SLIDER_KNOB_BLACK 0
+
+
+#define GLUI_SLIDER_MAX_VAL_STRING_SIZE 200
+#define GLUI_SLIDER_TRUNCATE_STRING "~"
+
+
+/********************** GLUI_Slider::mouse_down_handler() ******/
+
+int GLUI_Slider::mouse_down_handler( int local_x, int local_y )
+{
+ pressed = true;
+
+ //printf("%d %d\n",local_x,local_y);
+
+ update_val(local_x - x_abs, local_y - y_abs);
+ draw_translated_active_area();
+ if( glui ) glui->post_update_main_gfx();
+ execute_callback();
+
+ return false;
+}
+
+
+/**************************** GLUI_Slider::mouse_up_handler() */
+
+int GLUI_Slider::mouse_up_handler( int local_x, int local_y, int inside )
+{
+ pressed = false;
+
+ //printf("%d %d %d\n",local_x,local_y,inside);
+
+ update_val(local_x - x_abs, local_y - y_abs);
+ draw_translated_active_area();
+ if( glui ) glui->post_update_main_gfx();
+ execute_callback();
+
+ return false;
+}
+
+
+/****************************** GLUI_Slider::mouse_held_down_handler() ******/
+
+int GLUI_Slider::mouse_held_down_handler( int local_x, int local_y, int inside)
+{
+
+ //printf("%d %d %d\n",local_x,local_y,inside);
+
+ update_val(local_x - x_abs, local_y - y_abs);
+ draw_translated_active_area();
+ if( glui ) glui->post_update_main_gfx();
+ execute_callback();
+
+ return false;
+}
+
+/****************************** GLUI_Slider::special_handler() **********/
+
+int GLUI_Slider::special_handler( int key,int mods )
+{
+ int grads;
+
+ int min_x, max_x, wid_x;
+
+ int g;
+ double g_f;
+
+ int new_int;
+
+ min_x = 2 + GLUI_SLIDER_KNOB_SIDE_BORDER + GLUI_SLIDER_KNOB_HALF_WIDTH;
+ max_x = w - 2 - GLUI_SLIDER_KNOB_HALF_WIDTH - GLUI_SLIDER_KNOB_SIDE_BORDER;
+ wid_x = max_x - min_x + 1;
+
+ //The arrows adjust the slider's value.
+ //Without mods (shift, ctrl, alt), the current
+ //value is rounded to the nearest grad and then
+ //one grad is added/subtracted. However, shift,
+ //ctrl, alt modify the grad size by 1/2,1/10,
+ //1/100. If this is an int slider, the min
+ //change is 1.
+ //Note, by default, grads=0 which takes the
+ //num of grads to be equal to the pixel
+ //width of the slider...
+
+ if (graduations == 0)
+ grads = wid_x;
+ else
+ grads = graduations;
+
+ if (mods == 0)
+ {
+ //Use unmodified grads
+ }
+ else if (mods & GLUT_ACTIVE_SHIFT)
+ {
+ grads = 2*(grads-1) + 1;
+ }
+ else if (mods & GLUT_ACTIVE_CTRL)
+ {
+ grads = 10*(grads-1) + 1;
+ }
+ else if (mods & GLUT_ACTIVE_ALT)
+ {
+ grads = 100*(grads-1) + 1;
+ }
+ else
+ {
+ return false;
+ }
+
+ switch (data_type)
+ {
+ case GLUI_SLIDER_INT:
+ if (int_low != int_high)
+ {
+ if (int_val == int_high)
+ g = grads-1;
+ else
+ g = ((int)(((double)grads)*((double)(int_val-int_low))/((double)(int_high -
int_low))));
+ }
+ else
+ g = 0;
+ break;
+ case GLUI_SLIDER_FLOAT:
+ if (float_low != float_high)
+ {
+ if (float_val == float_high)
+ g = grads-1;
+ else
+ g = ((int)(((double)grads)*((double)(float_val-float_low))/((double)(float_high -
float_low))));
+ }
+ else
+ g = 0;
+ break;
+ default:
+ fprintf(stderr,"GLUI_Slider::upate_knob - Impossible data type!\n");
+ abort();
+ }
+
+ switch (key)
+ {
+ case GLUT_KEY_RIGHT:
+ g += 1;
+ if (g > (grads-1))
+ g = grads-1;
+ break;
+ case GLUT_KEY_LEFT:
+ g -= 1;
+ if (g < 0)
+ g = 0;
+ break;
+ default:
+ return false;
+ break;
+ }
+
+ g_f = ((double)g)/((double)(grads-1));
+
+ switch (data_type)
+ {
+ case GLUI_SLIDER_INT:
+ new_int = (int) (((double)int_low) + ((double)(g_f*((double)(int_high-int_low)) )));
+
+ if (new_int == int_val)
+ {
+ switch (key)
+ {
+ case GLUT_KEY_RIGHT:
+ new_int += 1;
+ if (new_int > int_high)
+ new_int = int_high;
+ break;
+ case GLUT_KEY_LEFT:
+ new_int -= 1;
+ if (new_int < int_low)
+ new_int = int_low;
+ break;
+ }
+ }
+ set_int_val(new_int);
+ set_float_val((float)(int_val));
+ break;
+ case GLUI_SLIDER_FLOAT:
+ set_float_val((double)float_low + ((double)g_f)*((double)(float_high-float_low)));
+ set_int_val((int)(float_val));
+ break;
+ default:
+ fprintf(stderr,"GLUI_Slider::upate_knob - Impossible data type!\n");
+ abort();
+ }
+
+ draw_translated_active_area();
+ if( glui ) glui->post_update_main_gfx();
+ execute_callback();
+
+ return false;
+}
+
+/****************************** GLUI_Slider::update_knob() **********/
+
+void GLUI_Slider::update_val( int x, int y )
+{
+
+ int grads;
+
+ int min_x, max_x, wid_x;
+
+ int g;
+ double g_f;
+
+ min_x = 2 + GLUI_SLIDER_KNOB_SIDE_BORDER + GLUI_SLIDER_KNOB_HALF_WIDTH;
+ max_x = w - 2 - GLUI_SLIDER_KNOB_HALF_WIDTH - GLUI_SLIDER_KNOB_SIDE_BORDER;
+ wid_x = max_x - min_x + 1;
+
+ if (graduations == 0)
+ grads = wid_x;
+ else
+ grads = graduations;
+
+ if (x < min_x)
+ x = min_x;
+ else if (x > max_x)
+ x = max_x;
+
+ if (x == max_x)
+ g = grads-1;
+ else
+ g = (int) ((double)(((double)grads)*((double)(x-min_x))/((double)(max_x - min_x))));
+
+ g_f = ((double)g)/((double)(grads-1));
+
+ switch (data_type)
+ {
+ case GLUI_SLIDER_INT:
+ set_int_val((int)(((double)int_low)+0.5+((double)(g_f*((double)(int_high-int_low))))));
+ set_float_val((float)(int_val));
+ break;
+ case GLUI_SLIDER_FLOAT:
+ set_float_val((float)(((double)float_low) + g_f*((double)(float_high-float_low))));
+ set_int_val((int)(float_val));
+ break;
+ default:
+ fprintf(stderr,"GLUI_Slider::upate_knob - Impossible data type!\n");
+ abort();
+ }
+
+}
+
+/****************************** GLUI_Slider::draw() **********/
+
+void GLUI_Slider::draw( int x, int y )
+{
+ int orig;
+
+ if ( NOT glui )
+ return;
+
+ orig = set_to_glut_window();
+
+
+ draw_emboss_box( 0,
+ w,
+ GLUI_SLIDER_NAME_TOP_BORDER +
+ GLUI_SLIDER_FONT_HEIGHT - 1 -
+ GLUI_SLIDER_FONT_MID_HEIGHT,
+ h );
+
+ draw_bkgd_box( GLUI_SLIDER_NAME_INDENT-1,
+ GLUI_SLIDER_NAME_INDENT +
+ string_width(name.string) +
+ 2*GLUI_SLIDER_NAME_SIDE_BORDER - 1,
+ 0,
+ 0 +
+ GLUI_SLIDER_FONT_FULL_HEIGHT +
+ GLUI_SLIDER_NAME_TOP_BORDER +
+ GLUI_SLIDER_NAME_BOTTOM_BORDER);
+
+ draw_name( GLUI_SLIDER_NAME_INDENT +
+ GLUI_SLIDER_NAME_SIDE_BORDER,
+ GLUI_SLIDER_FONT_HEIGHT-1 +
+ GLUI_SLIDER_NAME_TOP_BORDER);
+
+ draw_active_area();
+
+ restore_window(orig);
+
+ draw_active_box( GLUI_SLIDER_NAME_INDENT,
+ GLUI_SLIDER_NAME_INDENT +
+ string_width(name.string) +
+ 2*GLUI_SLIDER_NAME_SIDE_BORDER - 1,
+ 0,
+ GLUI_SLIDER_FONT_FULL_HEIGHT +
+ GLUI_SLIDER_NAME_TOP_BORDER +
+ GLUI_SLIDER_NAME_BOTTOM_BORDER - 1);
+
+}
+
+
+/************************************ GLUI_Slider::update_size() **********/
+
+void GLUI_Slider::update_size( void )
+{
+ int min_w;
+
+ if ( NOT glui )
+ return;
+
+ h = GLUI_SLIDER_NAME_TOP_BORDER +
+ GLUI_SLIDER_FONT_HEIGHT -
+ GLUI_SLIDER_FONT_MID_HEIGHT +
+ GLUI_SLIDER_VAL_TOP_BORDER +
+ GLUI_SLIDER_FONT_HEIGHT +
+ GLUI_SLIDER_KNOB_TOP_BORDER +
+ GLUI_SLIDER_KNOB_HALF_HEIGHT +
+ 1 +
+ GLUI_SLIDER_KNOB_HALF_HEIGHT +
+ GLUI_SLIDER_KNOB_BOTTOM_BORDER +
+ 2;
+
+ min_w = GLUI_SLIDER_NAME_INDENT +
+ string_width(name.string) +
+ 2*GLUI_SLIDER_NAME_SIDE_BORDER +
+ string_width(GLUI_SLIDER_TRUNCATE_STRING) +
+ string_width("0000000") +
+ 2*GLUI_SLIDER_VAL_SIDE_BORDER +
+ 2 - 1; //+2 for border width at right
+
+
+ if (w<min_w)
+ w = min_w;
+
+}
+
+
+/****************************** GLUI_Mouse_Interaction::draw_active_area_translated()
**********/
+
+void GLUI_Slider::draw_translated_active_area( void )
+{
+ int orig;
+ int win_h , win_w;
+
+ if ( NOT glui )
+ return;
+
+ orig = set_to_glut_window();
+ win_h = glutGet( GLUT_WINDOW_HEIGHT );
+ win_w = glutGet(GLUT_WINDOW_WIDTH);
+
+ glMatrixMode( GL_MODELVIEW );
+ glPushMatrix();
+ glLoadIdentity();
+ glTranslatef( (float) win_w/2.0, (float) win_h/2.0, 0.0 );
+ glRotatef( 180.0, 0.0, 1.0, 0.0 );
+ glRotatef( 180.0, 0.0, 0.0, 1.0 );
+ glTranslatef( (float) -win_w/2.0, (float) -win_h/2.0, 0.0 );
+ glTranslatef( (float) this->x_abs + .5, (float) this->y_abs + .5, 0.0 );
+
+ draw_active_area();
+
+ glMatrixMode( GL_MODELVIEW );
+ glPopMatrix();
+
+ restore_window(orig);
+}
+
+/****************************** GLUI_Mouse_Interaction::draw_active_area() **********/
+
+void GLUI_Slider::draw_active_area( void )
+{
+ draw_val();
+ draw_slider();
+}
+
+
+/************************************ GLUI_Slider::draw_val() **********/
+
+void GLUI_Slider::draw_val( void )
+{
+ int max_w, i;
+
+ char buf[GLUI_SLIDER_MAX_VAL_STRING_SIZE];
+
+ switch (data_type)
+ {
+ case GLUI_SLIDER_INT:
+ sprintf(buf,"%d", int_val);
+ break;
+ case GLUI_SLIDER_FLOAT:
+ sprintf(buf,"%.3g", float_val);
+ break;
+ default:
+ fprintf(stderr,"GLUI_Slider::draw_val - Impossible data type!\n");
+ abort();
+ }
+
+ max_w = w +1 -
+ (GLUI_SLIDER_NAME_INDENT +
+ string_width(name.string) +
+ 2*GLUI_SLIDER_NAME_SIDE_BORDER +
+ 2*GLUI_SLIDER_VAL_SIDE_BORDER + 2);
+
+ if (max_w < string_width(GLUI_SLIDER_TRUNCATE_STRING))
+ {
+ fprintf(stderr,"GLUI_Slider::draw_val - Impossible max_w!!!!\n");
+ abort();
+ }
+
+ if (string_width(buf) > max_w)
+ {
+
+ max_w -= string_width(GLUI_SLIDER_TRUNCATE_STRING);
+
+ i = strlen(buf)-1;
+ while ((string_width(buf) > max_w) && (i>=0))
+ {
+ buf[i--] = 0;
+ }
+
+ sprintf(&buf[i+1],"%s",GLUI_SLIDER_TRUNCATE_STRING);
+ }
+
+ draw_bkgd_box(
+ GLUI_SLIDER_NAME_INDENT +
+ string_width(name.string) +
+ 2*GLUI_SLIDER_NAME_SIDE_BORDER +
+ GLUI_SLIDER_VAL_SIDE_BORDER - 1,
+
+ w-1 - GLUI_SLIDER_VAL_SIDE_BORDER,
+
+ GLUI_SLIDER_NAME_TOP_BORDER +
+ GLUI_SLIDER_FONT_HEIGHT -
+ GLUI_SLIDER_FONT_MID_HEIGHT +
+ GLUI_SLIDER_VAL_TOP_BORDER +
+ GLUI_SLIDER_FONT_HEIGHT + 1,
+
+ GLUI_SLIDER_NAME_TOP_BORDER +
+ GLUI_SLIDER_FONT_HEIGHT -
+ GLUI_SLIDER_FONT_MID_HEIGHT +
+ GLUI_SLIDER_VAL_TOP_BORDER + 1 );
+
+ glColor3b( 0, 0, 0 );
+ glRasterPos2i( w -
+ string_width(buf) -
+ GLUI_SLIDER_VAL_SIDE_BORDER,
+ GLUI_SLIDER_NAME_TOP_BORDER +
+ GLUI_SLIDER_FONT_HEIGHT -
+ GLUI_SLIDER_FONT_MID_HEIGHT +
+ GLUI_SLIDER_VAL_TOP_BORDER +
+ GLUI_SLIDER_FONT_HEIGHT);
+ draw_string(buf);
+
+}
+
+/************************************ GLUI_Slider::draw_slider() **********/
+
+void GLUI_Slider::draw_slider( void )
+{
+
+ int min_x;
+ int max_x;
+ int wid_x;
+
+ float min_val;
+ float max_val;
+ float val;
+
+ int x_pos;
+
+ draw_bkgd_box(
+ 2 + GLUI_SLIDER_KNOB_SIDE_BORDER - 1,
+ w-2 - GLUI_SLIDER_KNOB_SIDE_BORDER,
+ GLUI_SLIDER_NAME_TOP_BORDER +
+ GLUI_SLIDER_FONT_HEIGHT -
+ GLUI_SLIDER_FONT_MID_HEIGHT +
+ GLUI_SLIDER_VAL_TOP_BORDER +
+ GLUI_SLIDER_FONT_HEIGHT +
+ GLUI_SLIDER_KNOB_TOP_BORDER+1,
+ GLUI_SLIDER_NAME_TOP_BORDER +
+ GLUI_SLIDER_FONT_HEIGHT -
+ GLUI_SLIDER_FONT_MID_HEIGHT +
+ GLUI_SLIDER_VAL_TOP_BORDER +
+ GLUI_SLIDER_FONT_HEIGHT +
+ GLUI_SLIDER_KNOB_TOP_BORDER +
+ 1+ 2*GLUI_SLIDER_KNOB_HALF_HEIGHT + 1);
+
+
+ draw_emboss_box( 2 +
+ GLUI_SLIDER_KNOB_SIDE_BORDER +
+ GLUI_SLIDER_KNOB_HALF_WIDTH,
+ w - 2 -
+ GLUI_SLIDER_KNOB_HALF_WIDTH -
+ GLUI_SLIDER_KNOB_SIDE_BORDER,
+ GLUI_SLIDER_NAME_TOP_BORDER +
+ GLUI_SLIDER_FONT_HEIGHT -
+ GLUI_SLIDER_FONT_MID_HEIGHT +
+ GLUI_SLIDER_VAL_TOP_BORDER +
+ GLUI_SLIDER_FONT_HEIGHT +
+ GLUI_SLIDER_KNOB_TOP_BORDER +
+ GLUI_SLIDER_KNOB_HALF_HEIGHT,
+ GLUI_SLIDER_NAME_TOP_BORDER +
+ GLUI_SLIDER_FONT_HEIGHT -
+ GLUI_SLIDER_FONT_MID_HEIGHT +
+ GLUI_SLIDER_VAL_TOP_BORDER +
+ GLUI_SLIDER_FONT_HEIGHT +
+ GLUI_SLIDER_KNOB_TOP_BORDER +
+ GLUI_SLIDER_KNOB_HALF_HEIGHT + 3);
+
+
+ min_x = 2 + GLUI_SLIDER_KNOB_SIDE_BORDER + GLUI_SLIDER_KNOB_HALF_WIDTH;
+ max_x = w - 2 - GLUI_SLIDER_KNOB_HALF_WIDTH - GLUI_SLIDER_KNOB_SIDE_BORDER;
+ wid_x = max_x - min_x + 1;
+
+ switch (data_type)
+ {
+ case GLUI_SLIDER_INT:
+ min_val = (float)int_low;
+ max_val = (float)int_high;
+ val = (float)int_val;
+ break;
+ case GLUI_SLIDER_FLOAT:
+ min_val = float_low;
+ max_val = float_high;
+ val = float_val;
+ break;
+ default:
+ fprintf(stderr,"GLUI_Slider::draw_val - Impossible data type!\n");
+ abort();
+ break;
+ }
+
+ if (max_val == min_val)
+ x_pos = min_x;
+ else
+ {
+ if (val == max_val)
+ x_pos = max_x;
+ else
+ x_pos = (int) (min_x + wid_x*((val-min_val)/(max_val-min_val)));
+ }
+
+ draw_knob(x_pos,0,0,0,0,glui->bkgd_color.r, glui->bkgd_color.g,
glui->bkgd_color.b);
+ draw_knob(x_pos,1,0,1,0, GLUI_SLIDER_KNOB_BLACK, GLUI_SLIDER_KNOB_BLACK,
GLUI_SLIDER_KNOB_BLACK);
+ draw_knob(x_pos,0,1,0,1, GLUI_SLIDER_KNOB_WHITE, GLUI_SLIDER_KNOB_WHITE,
GLUI_SLIDER_KNOB_WHITE);
+ if (pressed)
+ draw_knob(x_pos,1,1,1,1, GLUI_SLIDER_KNOB_GREY, GLUI_SLIDER_KNOB_GREY,
GLUI_SLIDER_KNOB_GREY);
+ else
+ draw_knob(x_pos,1,1,1,1,glui->bkgd_color.r, glui->bkgd_color.g,
glui->bkgd_color.b);
+ draw_knob(x_pos,2,1,2,1, GLUI_SLIDER_KNOB_D_GREY, GLUI_SLIDER_KNOB_D_GREY,
GLUI_SLIDER_KNOB_D_GREY);
+ if (pressed)
+ draw_knob(x_pos,2,2,2,2, GLUI_SLIDER_KNOB_L_GREY, GLUI_SLIDER_KNOB_L_GREY,
GLUI_SLIDER_KNOB_L_GREY);
+ else
+ draw_knob(x_pos,2,2,2,2, GLUI_SLIDER_KNOB_GREY, GLUI_SLIDER_KNOB_GREY,
GLUI_SLIDER_KNOB_GREY);
+
+
+}
+/******************************** GLUI_Slider::draw_knob() **********/
+
+void GLUI_Slider::draw_knob(
+ int x,
+ int off_l,
+ int off_r,
+ int off_t,
+ int off_b,
+ unsigned char r,
+ unsigned char g,
+ unsigned char b)
+{
+
+ float col_r = ((float)r)/255.0;
+ float col_g = ((float)g)/255.0;
+ float col_b = ((float)b)/255.0;
+
+ draw_box(
+ x - GLUI_SLIDER_KNOB_HALF_WIDTH - 1 +
+ off_l,
+ x + GLUI_SLIDER_KNOB_HALF_WIDTH -
+ off_r,
+ GLUI_SLIDER_NAME_TOP_BORDER +
+ GLUI_SLIDER_FONT_HEIGHT -
+ GLUI_SLIDER_FONT_MID_HEIGHT +
+ GLUI_SLIDER_VAL_TOP_BORDER +
+ GLUI_SLIDER_FONT_HEIGHT +
+ GLUI_SLIDER_KNOB_TOP_BORDER + 1 +
+ off_t,
+ GLUI_SLIDER_NAME_TOP_BORDER +
+ GLUI_SLIDER_FONT_HEIGHT -
+ GLUI_SLIDER_FONT_MID_HEIGHT +
+ GLUI_SLIDER_VAL_TOP_BORDER +
+ GLUI_SLIDER_FONT_HEIGHT +
+ GLUI_SLIDER_KNOB_TOP_BORDER +
+ GLUI_SLIDER_KNOB_HALF_HEIGHT + 1 +
+ GLUI_SLIDER_KNOB_HALF_HEIGHT + 1 -
+ off_b,
+ col_r,
+ col_g,
+ col_b);
+
+
+}
+
+/********************************* GLUI_Slider::set_float_limits() *********/
+
+void GLUI_Slider::set_float_limits( float low, float high)
+{
+
+ if (low > high)
+ {
+ fprintf(stderr,"GLUI_Slider::set_float_limits - Ignoring: low > hi\n");
+ return;
+ }
+
+ float_low = low;
+ float_high = high;
+
+ if ( NOT IN_BOUNDS( float_val, float_low, float_high ))
+ {
+ set_float_val( float_low );
+ set_int_val( (int)float_val );
+ }
+
+ int_low = (int) float_low;
+ int_high = (int) float_high;
+}
+
+
+/*********************************** GLUI_Slider::set_int_limits() *********/
+
+void GLUI_Slider::set_int_limits( int low, int high)
+{
+ if (low > high)
+ {
+ fprintf(stderr,"GLUI_Slider::set_int_limits - Ignoring: low > hi\n");
+ return;
+ }
+
+ int_low = low;
+ int_high = high;
+
+ if ( NOT IN_BOUNDS( int_val, int_low, int_high ))
+ {
+ set_int_val( int_low );
+ set_float_val( (float)int_val );
+ }
+
+ float_low = (float) int_low;
+ float_high = (float) int_high;
+}
+
+
+/*********************************** GLUI_Slider::set_num_graduations() *********/
+
+void GLUI_Slider::set_num_graduations( int g )
+{
+
+ if (g >= 0)
+ graduations = g;
+
+}
+
+/************** GLUI_Slider::GLUI_Slider() ********************/
+
+GLUI_Slider::GLUI_Slider( void )
+{
+ sprintf( name, "Slider: %p", this );
+
+ type = GLUI_CONTROL_SLIDER;
+ w = GLUI_SLIDER_WIDTH;
+ h = GLUI_SLIDER_HEIGHT;
+ can_activate = true;
+ live_type = GLUI_LIVE_NONE;
+ alignment = GLUI_ALIGN_CENTER;
+
+
+ int_low = GLUI_SLIDER_LO;
+ int_high = GLUI_SLIDER_HI;
+ float_low = GLUI_SLIDER_LO;
+ float_high = GLUI_SLIDER_HI;
+
+ pressed = false;
+
+ graduations = 0;
+}
Index: external/trimesh/gluit/glui_quaternion.cc
--- external/trimesh/gluit/glui_quaternion.cc (revision 0)
+++ external/trimesh/gluit/glui_quaternion.cc (revision 0)
@@ -0,0 +1,229 @@
+/***********************************************************************
+
+ quaternion.cpp
+
+ A quaternion class
+
+ -------------------------------------------------------------------
+
+ Feb 1998, Paul Rademacher (rademach(a)cs.unc.edu)
+
+************************************************************************/
+
+#include "glui_quaternion.h"
+#include <math.h>
+#include "glui_stdinc.h"
+
+/******************************************* constructors **************/
+
+quat::quat( void )
+{
+ *this = quat_identity();
+}
+
+quat::quat(const float x, const float y, const float z, const float w)
+{
+ v.set( x, y, z );
+ s = w;
+}
+
+quat::quat( vec3 _v, float _s )
+{
+ set( _v, _s );
+}
+
+quat::quat( float _s, vec3 _v )
+{
+ set( _v, _s );
+}
+
+quat::quat( const float *d )
+{
+ v[0] = d[0];
+ v[1] = d[1];
+ v[2] = d[2];
+ s = d[3];
+}
+
+quat::quat( const double *d )
+{
+ v[0] = (float)d[0];
+ v[1] = (float)d[1];
+ v[2] = (float)d[2];
+ s = (float)d[3];
+}
+
+quat::quat( const quat &q )
+{
+ v = q.v;
+ s = q.s;
+}
+
+void quat::set( vec3 _v, float _s )
+{
+ v = _v;
+ s = _s;
+}
+
+quat& quat::operator = (const quat& q)
+{
+ v = q.v; s = q.s; return *this;
+}
+
+
+/* ... */
+
+
+/******** quat friends ************/
+
+quat operator + (const quat &a, const quat &b)
+{
+ return quat( a.s+b.s, a.v+b.v );
+}
+
+quat operator - (const quat &a, const quat &b)
+{
+ return quat( a.s-b.s, a.v-b.v );
+}
+
+quat operator - (const quat &a )
+{
+ return quat( -a.s, -a.v );
+}
+
+quat operator * ( const quat &a, const quat &b)
+{
+ return quat( a.s*b.s - a.v*b.v, a.s*b.v + b.s*a.v + a.v^b.v );
+}
+
+quat operator * ( const quat &a, const float t)
+{
+ return quat( a.v * t, a.s * t );
+}
+
+quat operator * ( const float t, const quat &a )
+{
+ return quat( a.v * t, a.s * t );
+}
+
+
+mat4 quat::to_mat4( void )
+{
+ float t, xs, ys, zs, wx, wy, wz, xx, xy, xz, yy, yz, zz;
+
+ t = 2.0f / (v*v + s*s);
+
+ xs = v[VX]*t; ys = v[VY]*t; zs = v[VZ]*t;
+ wx = s*xs; wy = s*ys; wz = s*zs;
+ xx = v[VX]*xs; xy = v[VX]*ys; xz = v[VX]*zs;
+ yy = v[VY]*ys; yz = v[VY]*zs; zz = v[VZ]*zs;
+
+ mat4 matrix( 1.0f-(yy+zz), xy+wz, xz-wy, 0.0f,
+ xy-wz, 1.0f-(xx+zz), yz+wx, 0.0f,
+ xz+wy, yz-wx, 1.0f-(xx+yy), 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f );
+
+ return matrix;
+}
+
+
+/************************************************* quat_identity() *****/
+/* Returns quaternion identity element */
+
+quat quat_identity( void )
+{
+ return quat( vec3( 0.0, 0.0, 0.0 ), 1.0 );
+}
+
+
+/************************************************ quat_slerp() ********/
+/* Quaternion spherical interpolation */
+
+quat quat_slerp( quat from, quat to, float t )
+{
+ quat to1;
+ double omega, cosom, sinom, scale0, scale1;
+
+ /* calculate cosine */
+ cosom = from.v * to.v + from.s + to.s;
+
+ /* Adjust signs (if necessary) */
+ if ( cosom < 0.0 ) {
+ cosom = -cosom;
+ to1 = -to;
+ }
+ else
+ {
+ to1 = to;
+ }
+
+ /* Calculate coefficients */
+ if ((1.0 - cosom) > FUDGE ) {
+ /* standard case (slerp) */
+ omega = acos( cosom );
+ sinom = sin( omega );
+ scale0 = sin((1.0 - t) * omega) / sinom;
+ scale1 = sin(t * omega) / sinom;
+ }
+ else {
+ /* 'from' and 'to' are very close - just do linear interpolation */
+ scale0 = 1.0 - t;
+ scale1 = t;
+ }
+
+ return scale0 * from + scale1 * to1;
+}
+
+
+/********************************************** set_angle() ************/
+/* set rot angle (degrees) */
+
+void quat::set_angle( float f )
+{
+ vec3 axis = get_axis();
+
+ s = cos( DEG2RAD( f ) / 2.0 );
+
+ v = axis * sin(DEG2RAD(f) / 2.0);
+}
+
+
+/********************************************** scale_angle() ************/
+/* scale rot angle (degrees) */
+
+void quat::scale_angle( float f )
+{
+ set_angle( f * get_angle() );
+}
+
+
+/********************************************** get_angle() ************/
+/* get rot angle (degrees). Assumes s is between -1 and 1 */
+
+float quat::get_angle( void )
+{
+ return RAD2DEG( 2.0 * acos( s ) );
+}
+
+
+/********************************************* get_axis() **************/
+
+vec3 quat::get_axis( void )
+{
+ float scale;
+
+ scale = sin( acos( s ) );
+ if ( scale < FUDGE AND scale > -FUDGE )
+ return vec3( 0.0, 0.0, 0.0 );
+ else
+ return v / scale;
+}
+
+
+/******************************************* quat::print() ************/
+
+void quat::print( FILE *dest, char *name )
+{
+ fprintf( dest, "%s: v:<%3.2f %3.2f %3.2f> s:%3.2f\n", name,
+ v[0], v[1], v[2], s );
+}
Index: external/trimesh/gluit/freeglut_cursor.c
--- external/trimesh/gluit/freeglut_cursor.c (revision 0)
+++ external/trimesh/gluit/freeglut_cursor.c (revision 0)
@@ -0,0 +1,270 @@
+/*
+ * freeglut_cursor.c
+ *
+ * The mouse cursor related stuff.
+ *
+ * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
+ * Written by Pawel W. Olszta, <olszta(a)sourceforge.net>
+ * Creation date: Thu Dec 16 1999
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <GL/freeglut.h>
+#include "freeglut_internal.h"
+
+#if TARGET_HOST_UNIX_X11
+ #include <X11/cursorfont.h>
+#endif
+
+/*
+ * TODO BEFORE THE STABLE RELEASE:
+ * glutSetCursor() -- Win32 mappings are incomplete.
+ *
+ * It would be good to use custom mouse cursor shapes, and introduce
+ * an option to display them using glBitmap() and/or texture mapping,
+ * apart from the windowing system version.
+ */
+
+/* -- INTERNAL FUNCTIONS --------------------------------------------------- */
+
+#if TARGET_HOST_UNIX_X11
+
+int fgGetCursorError( Cursor cursor )
+{
+ int ret = 0;
+ char buf[ 256 ];
+
+ switch( cursor )
+ {
+ case BadAlloc:
+ case BadFont:
+ case BadMatch:
+ case BadPixmap:
+ case BadValue:
+ XGetErrorText( fgDisplay.Display, cursor, buf, sizeof buf );
+ fgWarning( "Error in setting cursor:\n %s.", buf );
+ ret = cursor;
+ break;
+ default:
+ /* no error */
+ break;
+ }
+
+ return ret;
+}
+
+#endif
+
+
+/* -- INTERFACE FUNCTIONS -------------------------------------------------- */
+
+/*
+ * Set the cursor image to be used for the current window
+ */
+void FGAPIENTRY glutSetCursor( int cursorID )
+{
+ freeglut_assert_ready; /* XXX WHY do we need the timer active for this? */
+ freeglut_assert_window;
+
+#if TARGET_HOST_UNIX_X11
+ /*
+ * Open issues:
+ * (a) Partial error checking. Is that a problem?
+ * Is fgGetCursorError() correct? Should we abort on errors?
+ * Should there be a freeglut-wide X error handler? Should
+ * we use the X error-handler mechanism?
+ * (b) FULL_CROSSHAIR demotes to plain CROSSHAIR. Old GLUT allows
+ * for this, but if there is a system that easily supports a full-
+ * window (or full-screen) crosshair, we might consider it.
+ * (c) Out-of-range cursor-types generate warnings. Should we abort?
+ */
+ {
+ Cursor cursor = None;
+ Pixmap no_cursor = None ; /* Used for GLUT_CURSOR_NONE */
+ int error = 0;
+
+#define MAP_CURSOR(a,b) \
+ case a: \
+ cursor = XCreateFontCursor( fgDisplay.Display, b ); \
+ break;
+
+ if( GLUT_CURSOR_FULL_CROSSHAIR == cursorID )
+ cursorID = GLUT_CURSOR_CROSSHAIR;
+
+ switch( cursorID )
+ {
+ MAP_CURSOR( GLUT_CURSOR_RIGHT_ARROW, XC_right_ptr);
+ MAP_CURSOR( GLUT_CURSOR_LEFT_ARROW, XC_left_ptr);
+ MAP_CURSOR( GLUT_CURSOR_INFO, XC_hand1);
+ MAP_CURSOR( GLUT_CURSOR_DESTROY, XC_pirate);
+ MAP_CURSOR( GLUT_CURSOR_HELP, XC_question_arrow);
+ MAP_CURSOR( GLUT_CURSOR_CYCLE, XC_exchange);
+ MAP_CURSOR( GLUT_CURSOR_SPRAY, XC_spraycan);
+ MAP_CURSOR( GLUT_CURSOR_WAIT, XC_watch);
+ MAP_CURSOR( GLUT_CURSOR_TEXT, XC_xterm);
+ MAP_CURSOR( GLUT_CURSOR_CROSSHAIR, XC_crosshair);
+ MAP_CURSOR( GLUT_CURSOR_UP_DOWN, XC_sb_v_double_arrow);
+ MAP_CURSOR( GLUT_CURSOR_LEFT_RIGHT, XC_sb_h_double_arrow);
+ MAP_CURSOR( GLUT_CURSOR_TOP_SIDE, XC_top_side);
+ MAP_CURSOR( GLUT_CURSOR_BOTTOM_SIDE, XC_bottom_side);
+ MAP_CURSOR( GLUT_CURSOR_LEFT_SIDE, XC_left_side);
+ MAP_CURSOR( GLUT_CURSOR_RIGHT_SIDE, XC_right_side);
+ MAP_CURSOR( GLUT_CURSOR_TOP_LEFT_CORNER, XC_top_left_corner);
+ MAP_CURSOR( GLUT_CURSOR_TOP_RIGHT_CORNER, XC_top_right_corner);
+ MAP_CURSOR( GLUT_CURSOR_BOTTOM_RIGHT_CORNER,
+ XC_bottom_right_corner);
+ MAP_CURSOR( GLUT_CURSOR_BOTTOM_LEFT_CORNER, XC_bottom_left_corner);
+ /* MAP_CURSOR( GLUT_CURSOR_NONE, XC_bogosity); */
+
+ case GLUT_CURSOR_NONE:
+ {
+ /*
+ * Note that we *never* change {no_cursor_bits} from anything
+ * but all-zeros. It is our image and mask. We also apparently
+ * need to pick a color for foreground/background---but what
+ * one we pick doesn't matter for GLUT_CURSOR_NONE.
+ */
+ static unsigned char no_cursor_bits[ 32 ];
+ XColor black;
+ no_cursor = XCreatePixmapFromBitmapData( fgDisplay.Display,
+ fgDisplay.RootWindow,
+ no_cursor_bits,
+ 16, 16,
+ 1, 0, 1 );
+ XParseColor( fgDisplay.Display,
+ DefaultColormap( fgDisplay.Display,
+ DefaultScreen( fgDisplay.Display ) ),
+ "black",
+ &black );
+ cursor = XCreatePixmapCursor( fgDisplay.Display,
+ no_cursor, no_cursor,
+ &black, &black,
+ 0, 0 );
+ break;
+ }
+
+ case GLUT_CURSOR_INHERIT:
+ break;
+
+ default:
+ fgWarning( "Unknown cursor type: %d\n", cursorID );
+ return;
+ }
+
+ error = fgGetCursorError( cursor );
+
+ if( GLUT_CURSOR_INHERIT == cursorID )
+ XUndefineCursor( fgDisplay.Display,
+ fgStructure.Window->Window.Handle );
+ else
+ {
+ XDefineCursor( fgDisplay.Display,
+ fgStructure.Window->Window.Handle, cursor );
+ XFreeCursor( fgDisplay.Display, cursor );
+ if( GLUT_CURSOR_NONE == cursorID )
+ XFreePixmap( fgDisplay.Display, no_cursor );
+ }
+ }
+
+#elif TARGET_HOST_WIN32 || TARGET_HOST_WINCE
+
+ /*
+ * This is a temporary solution only...
+ */
+ /* Set the cursor AND change it for this window class. */
+# define MAP_CURSOR(a,b) \
+ case a: \
+ SetCursor( LoadCursor( NULL, b ) ); \
+ SetClassLong( fgStructure.Window->Window.Handle, \
+ GCL_HCURSOR, \
+ ( LONG )LoadCursor( NULL, b ) ); \
+ break;
+
+ /* Nuke the cursor AND change it for this window class. */
+# define ZAP_CURSOR(a,b) \
+ case a: \
+ SetCursor( NULL ); \
+ SetClassLong( fgStructure.Window->Window.Handle, \
+ GCL_HCURSOR, ( LONG )NULL ); \
+ break;
+
+ switch( cursorID )
+ {
+ MAP_CURSOR( GLUT_CURSOR_RIGHT_ARROW, IDC_ARROW );
+ MAP_CURSOR( GLUT_CURSOR_LEFT_ARROW, IDC_ARROW );
+ MAP_CURSOR( GLUT_CURSOR_INFO, IDC_HELP );
+ MAP_CURSOR( GLUT_CURSOR_DESTROY, IDC_CROSS );
+ MAP_CURSOR( GLUT_CURSOR_HELP, IDC_HELP );
+ MAP_CURSOR( GLUT_CURSOR_CYCLE, IDC_SIZEALL );
+ MAP_CURSOR( GLUT_CURSOR_SPRAY, IDC_CROSS );
+ MAP_CURSOR( GLUT_CURSOR_WAIT, IDC_WAIT );
+ MAP_CURSOR( GLUT_CURSOR_TEXT, IDC_UPARROW );
+ MAP_CURSOR( GLUT_CURSOR_CROSSHAIR, IDC_CROSS );
+ /* MAP_CURSOR( GLUT_CURSOR_NONE, IDC_NO ); */
+ ZAP_CURSOR( GLUT_CURSOR_NONE, NULL );
+
+ default:
+ MAP_CURSOR( GLUT_CURSOR_UP_DOWN, IDC_ARROW );
+ }
+#endif
+
+ fgStructure.Window->State.Cursor = cursorID;
+}
+
+/*
+ * Moves the mouse pointer to given window coordinates
+ */
+void FGAPIENTRY glutWarpPointer( int x, int y )
+{
+ freeglut_assert_ready; /* XXX WHY do we need the timer active for this? */
+ freeglut_assert_window;
+
+#if TARGET_HOST_UNIX_X11
+
+ XWarpPointer(
+ fgDisplay.Display,
+ None,
+ fgStructure.Window->Window.Handle,
+ 0, 0, 0, 0,
+ x, y
+ );
+ XFlush( fgDisplay.Display ); /* XXX Is this really necessary? */
+
+#elif TARGET_HOST_WIN32 || TARGET_HOST_WINCE
+
+ {
+ POINT coords;
+ coords.x = x;
+ coords.y = y;
+
+ /*
+ * ClientToScreen() translates {coords} for us.
+ */
+ ClientToScreen( fgStructure.Window->Window.Handle, &coords );
+ SetCursorPos( coords.x, coords.y );
+ }
+
+#endif
+}
+
+/*** END OF FILE ***/
Index: external/trimesh/gluit/glui_img_spinup_1.c
--- external/trimesh/gluit/glui_img_spinup_1.c (revision 0)
+++ external/trimesh/gluit/glui_img_spinup_1.c (revision 0)
@@ -0,0 +1,24 @@
+
+
+int glui_img_spinup_1[] = { 12, 8, /* width, height */
+ 0, 0, 0, 127,127,127, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 255,255,255, 0, 0, 0, 127,127,127, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 255,255,255, 0, 0, 0,
+ 127,127,127, 191,191,191, 127,127,127, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 191,191,191, 191,191,191,
+ 255,255,255, 0, 0, 0, 127,127,127, 191,191,191, 191,191,191,
+ 127,127,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191,191,191,
+ 191,191,191, 191,191,191, 255,255,255, 0, 0, 0, 127,127,127,
+ 191,191,191, 191,191,191, 191,191,191, 127,127,127, 0, 0, 0,
+ 191,191,191, 191,191,191, 191,191,191, 191,191,191, 255,255,255,
+ 0, 0, 0, 127,127,127, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 255,255,255, 0, 0, 0, 127,127,127, 127,127,127,
+ 127,127,127, 127,127,127, 127,127,127, 127,127,127, 127,127,127,
+ 127,127,127, 127,127,127, 191,191,191, 255,255,255, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 255,255,255,
+};
Index: external/trimesh/gluit/freeglut_gamemode.c
--- external/trimesh/gluit/freeglut_gamemode.c (revision 0)
+++ external/trimesh/gluit/freeglut_gamemode.c (revision 0)
@@ -0,0 +1,598 @@
+/*
+ * freeglut_gamemode.c
+ *
+ * The game mode handling code.
+ *
+ * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
+ * Written by Pawel W. Olszta, <olszta(a)sourceforge.net>
+ * Creation date: Thu Dec 16 1999
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <GL/freeglut.h>
+#include "freeglut_internal.h"
+
+/*
+ * TODO BEFORE THE STABLE RELEASE:
+ *
+ * glutGameModeString() -- missing
+ * glutEnterGameMode() -- X11 version
+ * glutLeaveGameMode() -- is that correct?
+ * glutGameModeGet() -- is that correct?
+ */
+
+
+/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
+
+/*
+ * Remembers the current visual settings, so that
+ * we can change them and restore later...
+ */
+void fghRememberState( void )
+{
+#if TARGET_HOST_UNIX_X11
+
+ /*
+ * This highly depends on the XFree86 extensions,
+ * not approved as X Consortium standards
+ */
+# ifdef X_XF86VidModeGetModeLine
+
+
+ /*
+ * Remember the current ViewPort location of the screen to be able to
+ * restore the ViewPort on LeaveGameMode():
+ */
+ XF86VidModeGetViewPort(
+ fgDisplay.Display,
+ fgDisplay.Screen,
+ &fgDisplay.DisplayViewPortX,
+ &fgDisplay.DisplayViewPortY
+ );
+
+ /*
+ * Remember the current pointer location before going fullscreen
+ * for restoring it later:
+ */
+ {
+ Window junk_window;
+ unsigned int mask;
+
+ XQueryPointer(
+ fgDisplay.Display, fgDisplay.RootWindow,
+ &junk_window, &junk_window,
+ &fgDisplay.DisplayPointerX, &fgDisplay.DisplayPointerY,
+ &fgDisplay.DisplayPointerX, &fgDisplay.DisplayPointerY, &mask
+ );
+ }
+
+ /*
+ * Query the current display settings:
+ */
+ fgDisplay.DisplayModeValid =
+ XF86VidModeGetModeLine(
+ fgDisplay.Display,
+ fgDisplay.Screen,
+ &fgDisplay.DisplayModeClock,
+ &fgDisplay.DisplayMode
+ );
+
+ if( !fgDisplay.DisplayModeValid )
+ fgWarning( "Runtime use of XF86VidModeGetModeLine failed.\n" );
+
+# else
+ /*
+ * XXX warning fghRememberState: missing XFree86 video mode extensions,
+ * XXX game mode will not change screen resolution when activated
+ */
+# endif
+
+#elif TARGET_HOST_WIN32 || TARGET_HOST_WINCE
+
+/* DEVMODE devMode; */
+
+ /*
+ * Grab the current desktop settings...
+ */
+
+/* hack to get around my stupid cross-gcc headers */
+#define FREEGLUT_ENUM_CURRENT_SETTINGS -1
+
+ EnumDisplaySettings( NULL, FREEGLUT_ENUM_CURRENT_SETTINGS,
+ &fgDisplay.DisplayMode );
+
+ /*
+ * Make sure we will be restoring all settings needed
+ */
+ fgDisplay.DisplayMode.dmFields |=
+ DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY;
+
+#endif
+}
+
+/*
+ * Restores the previously remembered visual settings
+ */
+void fghRestoreState( void )
+{
+#if TARGET_HOST_UNIX_X11
+
+# ifdef X_XF86VidModeGetAllModeLines
+ /*
+ * Restore the remembered pointer position:
+ */
+ XWarpPointer(
+ fgDisplay.Display, None, fgDisplay.RootWindow, 0, 0, 0, 0,
+ fgDisplay.DisplayPointerX, fgDisplay.DisplayPointerY
+ );
+
+ /*
+ * This highly depends on the XFree86 extensions,
+ * not approved as X Consortium standards
+ */
+
+ if( fgDisplay.DisplayModeValid )
+ {
+ XF86VidModeModeInfo** displayModes;
+ int i, displayModesCount;
+
+ XF86VidModeGetAllModeLines(
+ fgDisplay.Display,
+ fgDisplay.Screen,
+ &displayModesCount,
+ &displayModes
+ );
+
+ /*
+ * Check every of the modes looking for one that matches our demands.
+ * If we find one, switch to it and restore the remembered viewport.
+ */
+ for( i = 0; i < displayModesCount; i++ )
+ {
+ if(displayModes[ i ]->hdisplay == fgDisplay.DisplayMode.hdisplay
&&
+ displayModes[ i ]->vdisplay == fgDisplay.DisplayMode.vdisplay
&&
+ displayModes[ i ]->dotclock == fgDisplay.DisplayModeClock )
+ {
+ XF86VidModeSwitchToMode(
+ fgDisplay.Display,
+ fgDisplay.Screen,
+ displayModes[ i ]
+ );
+ XF86VidModeSetViewPort(
+ fgDisplay.Display,
+ fgDisplay.Screen,
+ fgDisplay.DisplayViewPortX,
+ fgDisplay.DisplayViewPortY
+ );
+
+ /*
+ * For the case this would be the last X11 call the application
+ * calls exit() we've to flush the X11 output queue to have the
+ * commands sent to the X server before the application exits.
+ */
+ XFlush( fgDisplay.Display );
+
+ return;
+ }
+ }
+ }
+
+# else
+ /*
+ * XXX warning fghRestoreState: missing XFree86 video mode extensions,
+ * XXX game mode will not change screen resolution when activated
+ */
+# endif
+
+#elif TARGET_HOST_WIN32 || TARGET_HOST_WINCE
+
+ /*
+ * Restore the previously rememebered desktop display settings
+ */
+ ChangeDisplaySettings( &fgDisplay.DisplayMode, 0 );
+
+#endif
+}
+
+/*
+ * Checks the display mode settings against user's preferences
+ */
+GLboolean fghCheckDisplayMode( int width, int height, int depth, int refresh )
+{
+ /*
+ * The desired values should be stored in fgState structure...
+ */
+ return ( width == fgState.GameModeSize.X ) &&
+ ( height == fgState.GameModeSize.Y ) &&
+ ( depth == fgState.GameModeDepth ) &&
+ (refresh == fgState.GameModeRefresh );
+}
+
+/*
+ * Changes the current display mode to match user's settings
+ */
+GLboolean fghChangeDisplayMode( GLboolean haveToTest )
+{
+#if TARGET_HOST_UNIX_X11
+
+ /*
+ * This highly depends on the XFree86 extensions,
+ * not approved as X Consortium standards
+ */
+# ifdef X_XF86VidModeGetAllModeLines
+
+ /*
+ * This is also used by applcations which check modes by calling
+ * glutGameModeGet(GLUT_GAME_MODE_POSSIBLE), so allow the check:
+ */
+ if( haveToTest || fgDisplay.DisplayModeValid )
+ {
+ XF86VidModeModeInfo** displayModes;
+ int i, displayModesCount;
+
+ XF86VidModeGetAllModeLines(
+ fgDisplay.Display,
+ fgDisplay.Screen,
+ &displayModesCount,
+ &displayModes
+ );
+
+ /*
+ * Check every of the modes looking for one that matches our demands
+ */
+ for( i = 0; i < displayModesCount; i++ )
+ {
+ if( fghCheckDisplayMode( displayModes[ i ]->hdisplay,
+ displayModes[ i ]->vdisplay,
+ fgState.GameModeDepth,
+ fgState.GameModeRefresh ) )
+ {
+ if( haveToTest )
+ return GL_TRUE;
+ /*
+ * OKi, this is the display mode we have been looking for...
+ */
+ XF86VidModeSwitchToMode(
+ fgDisplay.Display,
+ fgDisplay.Screen,
+ displayModes[ i ]
+ );
+ return GL_TRUE;
+ }
+ }
+ }
+
+ /*
+ * Something must have went wrong
+ */
+ return GL_FALSE;
+
+# else
+ /*
+ * XXX warning fghChangeDisplayMode: missing XFree86 video mode extensions,
+ * XXX game mode will not change screen resolution when activated
+ */
+ return GL_FALSE;
+# endif
+
+#elif TARGET_HOST_WIN32 || TARGET_HOST_WINCE
+
+ unsigned int displayModes = 0, mode = 0xffffffff;
+ GLboolean success = GL_FALSE;
+ /* HDC desktopDC; */
+ DEVMODE devMode;
+
+ /*
+ * Enumerate the available display modes
+ * Try to get a complete match
+ */
+ while( EnumDisplaySettings( NULL, displayModes, &devMode ) )
+ {
+ /*
+ * Does the enumerated display mode match the user's preferences?
+ */
+ if( fghCheckDisplayMode( devMode.dmPelsWidth, devMode.dmPelsHeight,
+ devMode.dmBitsPerPel,
+ devMode.dmDisplayFrequency ) )
+ {
+ mode = displayModes;
+ break;
+ }
+ displayModes++;
+ }
+
+ if( mode == 0xffffffff )
+ {
+ /* then try without Display Frequency */
+ displayModes = 0;
+
+ /*
+ * Enumerate the available display modes
+ */
+ while( EnumDisplaySettings( NULL, displayModes, &devMode ) )
+ {
+ /* then try without Display Frequency */
+ if( fghCheckDisplayMode( devMode.dmPelsWidth,
+ devMode.dmPelsHeight,
+ devMode.dmBitsPerPel,
+ fgState.GameModeRefresh ) )
+ {
+ mode = displayModes;
+ break;
+ }
+ displayModes++;
+ }
+ }
+
+ /*
+ * Did we find a matching display mode?
+ */
+ if( mode != 0xffffffff )
+ {
+ int retVal = DISP_CHANGE_SUCCESSFUL;
+
+ /*
+ * Mark the values we want to modify in the display change call
+ */
+ devMode.dmFields |=
+ DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY;
+
+ retVal = ChangeDisplaySettings( &devMode, haveToTest ? CDS_TEST : 0 );
+
+ /*
+ * I don't know if it's really needed, but looks nice:
+ */
+ success = (retVal == DISP_CHANGE_SUCCESSFUL) ||
+ (retVal == DISP_CHANGE_NOTUPDATED);
+
+ if( !haveToTest && success )
+ {
+ fgState.GameModeSize.X = devMode.dmPelsWidth;
+ fgState.GameModeSize.Y = devMode.dmPelsHeight;
+ fgState.GameModeDepth = devMode.dmBitsPerPel;
+ fgState.GameModeRefresh = devMode.dmDisplayFrequency;
+ }
+ }
+
+ return success;
+
+#endif
+}
+
+
+/* -- INTERFACE FUNCTIONS -------------------------------------------------- */
+
+/*
+ * Sets the game mode display string
+ */
+void FGAPIENTRY glutGameModeString( const char* string )
+{
+ int width = 640, height = 480, depth = 16, refresh = 72;
+
+ /*
+ * This one seems a bit easier than glutInitDisplayString. The bad thing
+ * about it that I was unable to find the game mode string definition, so
+ * that I assumed it is: "[width]x[height]:[depth]@[refresh rate]", which
+ * appears in all GLUT game mode programs I have seen to date.
+ */
+ if( sscanf( string, "%ix%i:%i@%i", &width, &height, &depth,
&refresh ) !=
+ 4 )
+ if( sscanf( string, "%ix%i:%i", &width, &height, &depth )
!= 3 )
+ if( sscanf( string, "%ix%i@%i", &width, &height,
&refresh ) != 3 )
+ if( sscanf( string, "%ix%i", &width, &height ) != 2 )
+ if( sscanf( string, ":%i@%i", &depth, &refresh ) !=
2 )
+ if( sscanf( string, ":%i", &depth ) != 1 )
+ if( sscanf( string, "@%i", &refresh ) != 1 )
+ fgWarning(
+ "unable to parse game mode string
`%s'",
+ string
+ );
+
+ /*
+ * Hopefully it worked, and if not, we still have the default values
+ */
+ fgState.GameModeSize.X = width;
+ fgState.GameModeSize.Y = height;
+ fgState.GameModeDepth = depth;
+ fgState.GameModeRefresh = refresh;
+}
+
+/*
+ * Enters the game mode
+ */
+int FGAPIENTRY glutEnterGameMode( void )
+{
+ if( fgStructure.GameMode )
+ fgAddToWindowDestroyList( fgStructure.GameMode );
+ else
+ fghRememberState( );
+
+ if( ! fghChangeDisplayMode( GL_FALSE ) )
+ {
+ fgWarning( "failed to change screen settings" );
+ return FALSE;
+ }
+
+ fgStructure.GameMode = fgCreateWindow(
+ NULL, "FREEGLUT", 0, 0,
+ fgState.GameModeSize.X, fgState.GameModeSize.Y, GL_TRUE, GL_FALSE
+ );
+
+ fgStructure.GameMode->State.IsGameMode = GL_TRUE;
+
+#if TARGET_HOST_UNIX_X11
+
+ /* Move the window up to the topleft corner */
+ XMoveWindow( fgDisplay.Display, fgStructure.Window->Window.Handle, 0, 0 );
+
+ /*
+ * Sync needed to avoid a real race, the Xserver must have really created
+ * the window before we can grab the pointer into it:
+ */
+ XSync( fgDisplay.Display, False );
+
+ /* Move the Pointer to the middle of the fullscreen window */
+ XWarpPointer(
+ fgDisplay.Display,
+ None,
+ fgDisplay.RootWindow,
+ 0, 0, 0, 0,
+ fgState.GameModeSize.X/2, fgState.GameModeSize.Y/2
+ );
+
+ /*
+ * Grab the pointer to confine it into the window after the calls to
+ * XWrapPointer() which ensure that the pointer really enters the window.
+ *
+ * We also need to wait here until XGrabPointer() returns GrabSuccess,
+ * otherwise the new window is not viewable yet and if the next function
+ * (XSetInputFocus) is called with a not yet viewable window, it will exit
+ * the application which we have to aviod, so wait until it's viewable:
+ */
+ while( GrabSuccess != XGrabPointer(
+ fgDisplay.Display, fgStructure.GameMode->Window.Handle,
+ TRUE,
+ ButtonPressMask | ButtonReleaseMask | ButtonMotionMask
+ | PointerMotionMask,
+ GrabModeAsync, GrabModeAsync,
+ fgStructure.GameMode->Window.Handle, None, CurrentTime) )
+ usleep( 100 );
+
+ /*
+ * Change input focus to the new window. This will exit the application
+ * if the new window is not viewable yet, see the XGrabPointer loop above.
+ */
+ XSetInputFocus(
+ fgDisplay.Display,
+ fgStructure.GameMode->Window.Handle,
+ RevertToNone,
+ CurrentTime
+ );
+
+# ifdef X_XF86VidModeSetViewPort
+
+ if( fgDisplay.DisplayModeValid )
+ {
+ int x, y;
+ Window child;
+
+ /*
+ * Change to viewport to the window topleft edge:
+ */
+ XF86VidModeSetViewPort( fgDisplay.Display, fgDisplay.Screen, 0, 0 );
+
+ /*
+ * Final window repositioning: It could be avoided using an undecorated
+ * window using override_redirect, but this * would possily require
+ * more changes and investigation.
+ */
+
+ /* Get the current postion of the drawable area on screen */
+ XTranslateCoordinates(
+ fgDisplay.Display,
+ fgStructure.Window->Window.Handle,
+ fgDisplay.RootWindow,
+ 0, 0, &x, &y,
+ &child
+ );
+
+ /* Move the decorataions out of the topleft corner of the display */
+ XMoveWindow( fgDisplay.Display, fgStructure.Window->Window.Handle,
+ -x, -y);
+ }
+
+#endif
+
+ /*
+ * Grab the keyboard, too
+ */
+ XGrabKeyboard(
+ fgDisplay.Display,
+ fgStructure.GameMode->Window.Handle,
+ FALSE,
+ GrabModeAsync, GrabModeAsync,
+ CurrentTime
+ );
+
+#endif
+
+ return TRUE;
+}
+
+/*
+ * Leaves the game mode
+ */
+void FGAPIENTRY glutLeaveGameMode( void )
+{
+ freeglut_return_if_fail( fgStructure.GameMode );
+
+ fgStructure.GameMode->State.IsGameMode = GL_FALSE;
+
+ fgAddToWindowDestroyList( fgStructure.GameMode );
+
+#if TARGET_HOST_UNIX_X11
+
+ XUngrabPointer( fgDisplay.Display, CurrentTime );
+ XUngrabKeyboard( fgDisplay.Display, CurrentTime );
+
+#endif
+
+ fghRestoreState();
+}
+
+/*
+ * Returns information concerning the freeglut game mode
+ */
+int FGAPIENTRY glutGameModeGet( GLenum eWhat )
+{
+ switch( eWhat )
+ {
+ case GLUT_GAME_MODE_ACTIVE:
+ return !!fgStructure.GameMode;
+
+ case GLUT_GAME_MODE_POSSIBLE:
+ return fghChangeDisplayMode( GL_TRUE );
+
+ case GLUT_GAME_MODE_WIDTH:
+ return fgState.GameModeSize.X;
+
+ case GLUT_GAME_MODE_HEIGHT:
+ return fgState.GameModeSize.Y;
+
+ case GLUT_GAME_MODE_PIXEL_DEPTH:
+ return fgState.GameModeDepth;
+
+ case GLUT_GAME_MODE_REFRESH_RATE:
+ return fgState.GameModeRefresh;
+
+ case GLUT_GAME_MODE_DISPLAY_CHANGED:
+ /*
+ * This is true if the game mode has been activated successfully..
+ */
+ return !!fgStructure.GameMode;
+ }
+
+ return -1;
+}
+
+/*** END OF FILE ***/
Index: external/trimesh/gluit/glui_img_uparrow.c
--- external/trimesh/gluit/glui_img_uparrow.c (revision 0)
+++ external/trimesh/gluit/glui_img_uparrow.c (revision 0)
@@ -0,0 +1,56 @@
+
+
+int glui_img_uparrow[] = { 16, 16, /* width, height */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 192,192,192, 128,128,128, 128,128,128, 128,128,128,
+ 128,128,128, 128,128,128, 128,128,128, 128,128,128, 128,128,128,
+ 128,128,128, 128,128,128, 128,128,128, 128,128,128, 128,128,128,
+ 128,128,128, 0, 0, 0, 192,192,192, 255,255,255, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 128,128,128, 0, 0, 0, 192,192,192, 255,255,255,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 128,128,128, 0, 0, 0, 192,192,192,
+ 255,255,255, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 128,128,128, 0, 0, 0,
+ 192,192,192, 255,255,255, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 128,128,128,
+ 0, 0, 0, 192,192,192, 255,255,255, 192,192,192, 192,192,192,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 192,192,192, 192,192,192, 192,192,192,
+ 128,128,128, 0, 0, 0, 192,192,192, 255,255,255, 192,192,192,
+ 192,192,192, 192,192,192, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 128,128,128, 0, 0, 0, 192,192,192, 255,255,255,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 128,128,128, 0, 0, 0, 192,192,192,
+ 255,255,255, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 0, 0, 0, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 128,128,128, 0, 0, 0,
+ 192,192,192, 255,255,255, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 128,128,128,
+ 0, 0, 0, 192,192,192, 255,255,255, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 128,128,128, 0, 0, 0, 192,192,192, 255,255,255, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 128,128,128, 0, 0, 0, 192,192,192, 255,255,255,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 128,128,128, 0, 0, 0, 192,192,192,
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 128,128,128, 0, 0, 0,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 0, 0, 0,
+};
Index: external/trimesh/gluit/freeglut_callbacks.c
--- external/trimesh/gluit/freeglut_callbacks.c (revision 0)
+++ external/trimesh/gluit/freeglut_callbacks.c (revision 0)
@@ -0,0 +1,336 @@
+/*
+ * freeglut_callbacks.c
+ *
+ * The callbacks setting methods.
+ *
+ * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
+ * Written by Pawel W. Olszta, <olszta(a)sourceforge.net>
+ * Creation date: Fri Dec 3 1999
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <GL/freeglut.h>
+#include "freeglut_internal.h"
+
+
+/* -- INTERFACE FUNCTIONS -------------------------------------------------- */
+
+/*
+ * All of the callbacks setting methods can be generalized to this:
+ */
+#define SET_CALLBACK(a) \
+ if( fgStructure.Window == NULL ) \
+ return; \
+ SET_WCB( ( *( fgStructure.Window ) ), a, callback );
+
+/*
+ * Sets the Display callback for the current window
+ */
+void FGAPIENTRY glutDisplayFunc( void (* callback)( void ) )
+{
+ if( !callback )
+ fgError( "Fatal error in program. NULL display callback not "
+ "permitted in GLUT 3.0+ or freeglut 2.0.1+\n" );
+ SET_CALLBACK( Display );
+}
+
+/*
+ * Sets the Reshape callback for the current window
+ */
+void FGAPIENTRY glutReshapeFunc( void (* callback)( int, int ) )
+{
+ SET_CALLBACK( Reshape );
+}
+
+/*
+ * Sets the Keyboard callback for the current window
+ */
+void FGAPIENTRY glutKeyboardFunc( void (* callback)
+ ( unsigned char, int, int ) )
+{
+ SET_CALLBACK( Keyboard );
+}
+
+/*
+ * Sets the Special callback for the current window
+ */
+void FGAPIENTRY glutSpecialFunc( void (* callback)( int, int, int ) )
+{
+ SET_CALLBACK( Special );
+}
+
+/*
+ * Sets the global idle callback
+ */
+void FGAPIENTRY glutIdleFunc( void (* callback)( void ) )
+{
+ freeglut_assert_ready;
+ fgState.IdleCallback = callback;
+}
+
+/*
+ * Sets the Timer callback for the current window
+ */
+void FGAPIENTRY glutTimerFunc( unsigned int timeOut, void (* callback)( int ),
+ int timerID )
+{
+ SFG_Timer *timer, *node;
+
+ freeglut_assert_ready;
+
+ if( (timer = fgState.FreeTimers.Last) )
+ {
+ fgListRemove( &fgState.FreeTimers, &timer->Node );
+ }
+ else
+ {
+ if( ! (timer = malloc(sizeof(SFG_Timer))) )
+ fgError( "Fatal error: "
+ "Memory allocation failure in glutTimerFunc()\n" );
+ }
+
+ timer->Callback = callback;
+ timer->ID = timerID;
+ timer->TriggerTime = fgElapsedTime() + timeOut;
+
+ for( node = fgState.Timers.First; node; node = node->Node.Next )
+ {
+ if( node->TriggerTime > timer->TriggerTime )
+ break;
+ }
+
+ fgListInsert( &fgState.Timers, &node->Node, &timer->Node );
+}
+
+/*
+ * Sets the Visibility callback for the current window.
+ */
+static void fghVisibility( int status )
+{
+ int glut_status = GLUT_VISIBLE;
+
+ freeglut_assert_ready;
+ freeglut_return_if_fail( fgStructure.Window );
+
+ if( ( GLUT_HIDDEN == status ) || ( GLUT_FULLY_COVERED == status ) )
+ glut_status = GLUT_NOT_VISIBLE;
+ INVOKE_WCB( *( fgStructure.Window ), Visibility, ( glut_status ) );
+}
+
+void FGAPIENTRY glutVisibilityFunc( void (* callback)( int ) )
+{
+ SET_CALLBACK( Visibility );
+
+ if( callback )
+ glutWindowStatusFunc( fghVisibility );
+ else
+ glutWindowStatusFunc( NULL );
+}
+
+/*
+ * Sets the keyboard key release callback for the current window
+ */
+void FGAPIENTRY glutKeyboardUpFunc( void (* callback)
+ ( unsigned char, int, int ) )
+{
+ SET_CALLBACK( KeyboardUp );
+}
+
+/*
+ * Sets the special key release callback for the current window
+ */
+void FGAPIENTRY glutSpecialUpFunc( void (* callback)( int, int, int ) )
+{
+ SET_CALLBACK( SpecialUp );
+}
+
+/*
+ * Sets the joystick callback and polling rate for the current window
+ */
+void FGAPIENTRY glutJoystickFunc( void (* callback)
+ ( unsigned int, int, int, int ),
+ int pollInterval )
+{
+ SET_CALLBACK( Joystick );
+ fgStructure.Window->State.JoystickPollRate = pollInterval;
+
+ fgStructure.Window->State.JoystickLastPoll =
+ fgElapsedTime() - fgStructure.Window->State.JoystickPollRate;
+
+ if( fgStructure.Window->State.JoystickLastPoll < 0 )
+ fgStructure.Window->State.JoystickLastPoll = 0;
+}
+
+/*
+ * Sets the mouse callback for the current window
+ */
+void FGAPIENTRY glutMouseFunc( void (* callback)( int, int, int, int ) )
+{
+ SET_CALLBACK( Mouse );
+}
+
+/*
+ * Sets the mouse wheel callback for the current window
+ */
+void FGAPIENTRY glutMouseWheelFunc( void (* callback)( int, int, int, int ) )
+{
+ SET_CALLBACK( MouseWheel );
+}
+
+/*
+ * Sets the mouse motion callback for the current window (one or more buttons
+ * are pressed)
+ */
+void FGAPIENTRY glutMotionFunc( void (* callback)( int, int ) )
+{
+ SET_CALLBACK( Motion );
+}
+
+/*
+ * Sets the passive mouse motion callback for the current window (no mouse
+ * buttons are pressed)
+ */
+void FGAPIENTRY glutPassiveMotionFunc( void (* callback)( int, int ) )
+{
+ SET_CALLBACK( Passive );
+}
+
+/*
+ * Window mouse entry/leave callback
+ */
+void FGAPIENTRY glutEntryFunc( void (* callback)( int ) )
+{
+ SET_CALLBACK( Entry );
+}
+
+/*
+ * Window destruction callbacks
+ */
+void FGAPIENTRY glutCloseFunc( void (* callback)( void ) )
+{
+ SET_CALLBACK( Destroy );
+}
+
+void FGAPIENTRY glutWMCloseFunc( void (* callback)( void ) )
+{
+ glutCloseFunc( callback );
+}
+
+/* A. Donev: Destruction callback for menus */
+void FGAPIENTRY glutMenuDestroyFunc( void (* callback)( void ) )
+{
+ if( fgStructure.Menu )
+ fgStructure.Menu->Destroy = callback;
+}
+
+/*
+ * Deprecated version of glutMenuStatusFunc callback setting method
+ */
+void FGAPIENTRY glutMenuStateFunc( void (* callback)( int ) )
+{
+ freeglut_assert_ready;
+ fgState.MenuStateCallback = callback;
+}
+
+/*
+ * Sets the global menu status callback for the current window
+ */
+void FGAPIENTRY glutMenuStatusFunc( void (* callback)( int, int, int ) )
+{
+ freeglut_assert_ready;
+ fgState.MenuStatusCallback = callback;
+}
+
+/*
+ * Sets the overlay display callback for the current window
+ */
+void FGAPIENTRY glutOverlayDisplayFunc( void (* callback)( void ) )
+{
+ SET_CALLBACK( OverlayDisplay );
+}
+
+/*
+ * Sets the window status callback for the current window
+ */
+void FGAPIENTRY glutWindowStatusFunc( void (* callback)( int ) )
+{
+ SET_CALLBACK( WindowStatus );
+}
+
+/*
+ * Sets the spaceball motion callback for the current window
+ */
+void FGAPIENTRY glutSpaceballMotionFunc( void (* callback)( int, int, int ) )
+{
+ SET_CALLBACK( SpaceMotion );
+}
+
+/*
+ * Sets the spaceball rotate callback for the current window
+ */
+void FGAPIENTRY glutSpaceballRotateFunc( void (* callback)( int, int, int ) )
+{
+ SET_CALLBACK( SpaceRotation );
+}
+
+/*
+ * Sets the spaceball button callback for the current window
+ */
+void FGAPIENTRY glutSpaceballButtonFunc( void (* callback)( int, int ) )
+{
+ SET_CALLBACK( SpaceButton );
+}
+
+/*
+ * Sets the button box callback for the current window
+ */
+void FGAPIENTRY glutButtonBoxFunc( void (* callback)( int, int ) )
+{
+ SET_CALLBACK( ButtonBox );
+}
+
+/*
+ * Sets the dials box callback for the current window
+ */
+void FGAPIENTRY glutDialsFunc( void (* callback)( int, int ) )
+{
+ SET_CALLBACK( Dials );
+}
+
+/*
+ * Sets the tablet motion callback for the current window
+ */
+void FGAPIENTRY glutTabletMotionFunc( void (* callback)( int, int ) )
+{
+ SET_CALLBACK( TabletMotion );
+}
+
+/*
+ * Sets the tablet buttons callback for the current window
+ */
+void FGAPIENTRY glutTabletButtonFunc( void (* callback)( int, int, int, int ) )
+{
+ SET_CALLBACK( TabletButton );
+}
+
+/*** END OF FILE ***/
Index: external/trimesh/gluit/glui_img_spindown_dis.c
--- external/trimesh/gluit/glui_img_spindown_dis.c (revision 0)
+++ external/trimesh/gluit/glui_img_spindown_dis.c (revision 0)
@@ -0,0 +1,24 @@
+
+
+int glui_img_spindown_dis[] = { 12, 8, /* width, height */
+ 255,255,255, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 255,255,255, 127,127,127, 127,127,127,
+ 127,127,127, 127,127,127, 127,127,127, 127,127,127, 127,127,127,
+ 127,127,127, 127,127,127, 127,127,127, 64, 64, 64, 255,255,255,
+ 191,191,191, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 191,191,191, 127,127,127,
+ 64, 64, 64, 255,255,255, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 127,127,127, 255,255,255, 191,191,191, 191,191,191,
+ 191,191,191, 127,127,127, 64, 64, 64, 255,255,255, 191,191,191,
+ 191,191,191, 191,191,191, 127,127,127, 127,127,127, 127,127,127,
+ 255,255,255, 191,191,191, 191,191,191, 127,127,127, 64, 64, 64,
+ 255,255,255, 191,191,191, 191,191,191, 127,127,127, 127,127,127,
+ 127,127,127, 127,127,127, 127,127,127, 255,255,255, 191,191,191,
+ 127,127,127, 64, 64, 64, 255,255,255, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 127,127,127, 64, 64, 64, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 64, 64, 64,
+};
Index: external/trimesh/gluit/glui_column.cc
--- external/trimesh/gluit/glui_column.cc (revision 0)
+++ external/trimesh/gluit/glui_column.cc (revision 0)
@@ -0,0 +1,76 @@
+/****************************************************************************
+
+ GLUI User Interface Toolkit
+ ---------------------------
+
+ glui_column.cpp - GLUI_Column control class
+
+
+ --------------------------------------------------
+
+ Copyright (c) 1998 Paul Rademacher
+
+ This program is freely distributable without licensing fees and is
+ provided without guarantee or warrantee expressed or implied. This
+ program is -not- in the public domain.
+
+*****************************************************************************/
+
+#include "glui.h"
+#include "glui_stdinc.h"
+
+/**************************************** GLUI_Column::draw() ************/
+
+void GLUI_Column::draw( int x, int y )
+{
+ int orig;
+ int panel_x, panel_y, panel_w, panel_h, panel_x_off, panel_y_off;
+ int y_diff;
+
+ if ( NOT can_draw() )
+ return;
+
+ if ( int_val == 1 ) { /* Draw a vertical bar */
+ orig = set_to_glut_window();
+
+ if ( parent() != NULL ) {
+ get_this_column_dims(&panel_x, &panel_y, &panel_w, &panel_h,
+ &panel_x_off, &panel_y_off);
+
+ y_diff = y_abs - panel_y;
+
+ if ( 0 ) {
+ glLineWidth(1.0);
+ glBegin( GL_LINES );
+ glColor3f( .5, .5, .5 );
+ glVertex2i( -GLUI_XOFF+1, -y_diff + GLUI_SEPARATOR_HEIGHT/2 );
+ glVertex2i( -GLUI_XOFF+1, -y_diff + panel_h - GLUI_SEPARATOR_HEIGHT/2);
+
+ glColor3f( 1.0, 1.0, 1.0 );
+ glVertex2i( -GLUI_XOFF+2, -y_diff + GLUI_SEPARATOR_HEIGHT/2 );
+ glVertex2i( -GLUI_XOFF+2, -y_diff + panel_h - GLUI_SEPARATOR_HEIGHT/2);
+ glEnd();
+ }
+ else {
+ glLineWidth(1.0);
+ glBegin( GL_LINES );
+ glColor3f( .5, .5, .5 );
+ glVertex2i( -2, 0 );
+ glVertex2i( -2, h );
+ /*glVertex2i( 0, -y_diff + GLUI_SEPARATOR_HEIGHT/2 ); */
+ /*glVertex2i( 0, -y_diff + panel_h - GLUI_SEPARATOR_HEIGHT/2); */
+
+ glColor3f( 1.0, 1.0, 1.0 );
+ glVertex2i( -1, 0 );
+ glVertex2i( -1, h );
+ /*glVertex2i( 1, -y_diff + GLUI_SEPARATOR_HEIGHT/2 ); */
+ /*glVertex2i( 1, -y_diff + panel_h - GLUI_SEPARATOR_HEIGHT/2); */
+ glEnd();
+ }
+
+ }
+
+ restore_window(orig);
+ }
+}
+
Index: external/trimesh/gluit/freeglut_main.c
--- external/trimesh/gluit/freeglut_main.c (revision 0)
+++ external/trimesh/gluit/freeglut_main.c (revision 0)
@@ -0,0 +1,1982 @@
+/*
+ * freeglut_main.c
+ *
+ * The windows message processing methods.
+ *
+ * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
+ * Written by Pawel W. Olszta, <olszta(a)sourceforge.net>
+ * Creation date: Fri Dec 3 1999
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <GL/freeglut.h>
+#include "freeglut_internal.h"
+
+#include <limits.h>
+#if TARGET_HOST_UNIX_X11
+#include <sys/types.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/stat.h>
+#elif TARGET_HOST_WIN32
+#elif TARGET_HOST_WINCE
+
+typedef struct GXDisplayProperties GXDisplayProperties;
+typedef struct GXKeyList GXKeyList;
+#include <gx.h>
+
+typedef struct GXKeyList (*GXGETDEFAULTKEYS)(int);
+typedef int (*GXOPENINPUT)();
+
+GXGETDEFAULTKEYS GXGetDefaultKeys_ = NULL;
+GXOPENINPUT GXOpenInput_ = NULL;
+
+struct GXKeyList gxKeyList;
+
+#endif
+
+#ifndef MAX
+#define MAX(a,b) (((a)>(b)) ? (a) : (b))
+#endif
+
+#ifndef MIN
+#define MIN(a,b) (((a)<(b)) ? (a) : (b))
+#endif
+
+
+/*
+ * TODO BEFORE THE STABLE RELEASE:
+ *
+ * There are some issues concerning window redrawing under X11, and maybe
+ * some events are not handled. The Win32 version lacks some more features,
+ * but seems acceptable for not demanding purposes.
+ *
+ * Need to investigate why the X11 version breaks out with an error when
+ * closing a window (using the window manager, not glutDestroyWindow)...
+ */
+
+/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
+
+/*
+ * Handle a window configuration change. When no reshape
+ * callback is hooked, the viewport size is updated to
+ * match the new window size.
+ */
+static void fghReshapeWindowByHandle ( SFG_WindowHandleType handle,
+ int width, int height )
+{
+ SFG_Window *current_window = fgStructure.Window;
+
+ SFG_Window* window = fgWindowByHandle( handle );
+ freeglut_return_if_fail( window != NULL );
+
+
+#if TARGET_HOST_UNIX_X11
+
+ XResizeWindow( fgDisplay.Display, window->Window.Handle,
+ width, height );
+ XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */
+
+#elif TARGET_HOST_WIN32 || TARGET_HOST_WINCE
+
+#if !TARGET_HOST_WINCE
+ {
+ RECT rect;
+
+ /*
+ * For windowed mode, get the current position of the
+ * window and resize taking the size of the frame
+ * decorations into account.
+ */
+
+ GetWindowRect( window->Window.Handle, &rect );
+ rect.right = rect.left + width;
+ rect.bottom = rect.top + height;
+
+ if ( window->Parent == NULL )
+ {
+ if ( ! window->IsMenu && !window->State.IsGameMode )
+ {
+ rect.right += GetSystemMetrics( SM_CXSIZEFRAME ) * 2;
+ rect.bottom += GetSystemMetrics( SM_CYSIZEFRAME ) * 2 +
+ GetSystemMetrics( SM_CYCAPTION );
+ }
+ }
+
+ /*
+ * SWP_NOACTIVATE Do not activate the window
+ * SWP_NOOWNERZORDER Do not change position in z-order
+ * SWP_NOSENDCHANGING Supress WM_WINDOWPOSCHANGING message
+ * SWP_NOZORDER Retains the current Z order (ignore 2nd param)
+ */
+
+ SetWindowPos( window->Window.Handle,
+ HWND_TOP,
+ rect.left,
+ rect.top,
+ rect.right - rect.left,
+ rect.bottom - rect.top,
+ SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING |
+ SWP_NOZORDER
+ );
+ }
+#endif /* TARGET_HOST_WINCE */
+
+ /*
+ * XXX Should update {window->State.OldWidth, window->State.OldHeight}
+ * XXX to keep in lockstep with UNIX_X11 code.
+ */
+ if( FETCH_WCB( *window, Reshape ) )
+ INVOKE_WCB( *window, Reshape, ( width, height ) );
+ else
+ {
+ fgSetWindow( window );
+ glViewport( 0, 0, width, height );
+ }
+
+#endif
+
+ /*
+ * Force a window redraw. In Windows at least this is only a partial
+ * solution: if the window is increasing in size in either dimension,
+ * the already-drawn part does not get drawn again and things look funny.
+ * But without this we get this bad behaviour whenever we resize the
+ * window.
+ */
+ window->State.Redisplay = GL_TRUE;
+
+ if( window->IsMenu )
+ fgSetWindow( current_window );
+}
+
+/*
+ * Calls a window's redraw method. This is used when
+ * a redraw is forced by the incoming window messages.
+ */
+static void fghRedrawWindowByHandle ( SFG_WindowHandleType handle )
+{
+ SFG_Window* window = fgWindowByHandle( handle );
+ freeglut_return_if_fail( window );
+ freeglut_return_if_fail( FETCH_WCB ( *window, Display ) );
+
+ window->State.Redisplay = GL_FALSE;
+
+ freeglut_return_if_fail( window->State.Visible );
+
+ if( window->State.NeedToResize )
+ {
+ SFG_Window *current_window = fgStructure.Window;
+
+ fgSetWindow( window );
+
+ fghReshapeWindowByHandle(
+ window->Window.Handle,
+ window->State.Width,
+ window->State.Height
+ );
+
+ window->State.NeedToResize = GL_FALSE;
+ fgSetWindow( current_window );
+ }
+
+ INVOKE_WCB( *window, Display, ( ) );
+}
+
+/*
+ * A static helper function to execute display callback for a window
+ */
+static void fghcbDisplayWindow( SFG_Window *window,
+ SFG_Enumerator *enumerator )
+{
+ if( window->State.NeedToResize )
+ {
+ SFG_Window *current_window = fgStructure.Window;
+
+ fgSetWindow( window );
+
+ fghReshapeWindowByHandle(
+ window->Window.Handle,
+ window->State.Width,
+ window->State.Height
+ );
+
+ window->State.NeedToResize = GL_FALSE;
+ fgSetWindow ( current_window );
+ }
+
+ if( window->State.Redisplay &&
+ window->State.Visible )
+ {
+ window->State.Redisplay = GL_FALSE;
+
+#if TARGET_HOST_UNIX_X11
+ {
+ SFG_Window *current_window = fgStructure.Window;
+
+ INVOKE_WCB( *window, Display, ( ) );
+ fgSetWindow( current_window );
+ }
+#elif TARGET_HOST_WIN32 || TARGET_HOST_WINCE
+ RedrawWindow(
+ window->Window.Handle, NULL, NULL,
+ RDW_NOERASE | RDW_INTERNALPAINT | RDW_INVALIDATE | RDW_UPDATENOW
+ );
+#endif
+ }
+
+ fgEnumSubWindows( window, fghcbDisplayWindow, enumerator );
+}
+
+/*
+ * Make all windows perform a display call
+ */
+static void fghDisplayAll( void )
+{
+ SFG_Enumerator enumerator;
+
+ enumerator.found = GL_FALSE;
+ enumerator.data = NULL;
+
+ fgEnumWindows( fghcbDisplayWindow, &enumerator );
+}
+
+/*
+ * Window enumerator callback to check for the joystick polling code
+ */
+static void fghcbCheckJoystickPolls( SFG_Window *window,
+ SFG_Enumerator *enumerator )
+{
+ long int checkTime = fgElapsedTime( );
+
+ if( window->State.JoystickLastPoll + window->State.JoystickPollRate <=
+ checkTime )
+ {
+#if !TARGET_HOST_WINCE
+ fgJoystickPollWindow( window );
+#endif /* !TARGET_HOST_WINCE */
+ window->State.JoystickLastPoll = checkTime;
+ }
+
+ fgEnumSubWindows( window, fghcbCheckJoystickPolls, enumerator );
+}
+
+/*
+ * Check all windows for joystick polling
+ */
+static void fghCheckJoystickPolls( void )
+{
+ SFG_Enumerator enumerator;
+
+ enumerator.found = GL_FALSE;
+ enumerator.data = NULL;
+
+ fgEnumWindows( fghcbCheckJoystickPolls, &enumerator );
+}
+
+/*
+ * Check the global timers
+ */
+static void fghCheckTimers( void )
+{
+ long checkTime = fgElapsedTime( );
+
+ while( fgState.Timers.First )
+ {
+ SFG_Timer *timer = fgState.Timers.First;
+
+ if( timer->TriggerTime > checkTime )
+ break;
+
+ fgListRemove( &fgState.Timers, &timer->Node );
+ fgListAppend( &fgState.FreeTimers, &timer->Node );
+
+ timer->Callback( timer->ID );
+ }
+}
+
+/*
+ * Elapsed Time
+ */
+long fgElapsedTime( void )
+{
+ if ( fgState.Time.Set )
+ {
+#if TARGET_HOST_UNIX_X11
+ struct timeval now;
+ long elapsed;
+
+ gettimeofday( &now, NULL );
+
+ elapsed = (now.tv_usec - fgState.Time.Value.tv_usec) / 1000;
+ elapsed += (now.tv_sec - fgState.Time.Value.tv_sec) * 1000;
+
+ return elapsed;
+#elif TARGET_HOST_WIN32
+ return timeGetTime() - fgState.Time.Value;
+#elif TARGET_HOST_WINCE
+ return GetTickCount() - fgState.Time.Value;
+#endif
+ }
+ else
+ {
+#if TARGET_HOST_UNIX_X11
+ gettimeofday( &fgState.Time.Value, NULL );
+#elif TARGET_HOST_WIN32
+ fgState.Time.Value = timeGetTime ();
+#elif TARGET_HOST_WINCE
+ fgState.Time.Value = GetTickCount();
+#endif
+ fgState.Time.Set = GL_TRUE ;
+
+ return 0 ;
+ }
+}
+
+/*
+ * Error Messages.
+ */
+void fgError( const char *fmt, ... )
+{
+ va_list ap;
+
+ va_start( ap, fmt );
+
+ fprintf( stderr, "freeglut ");
+ if( fgState.ProgramName )
+ fprintf (stderr, "(%s): ", fgState.ProgramName);
+ vfprintf( stderr, fmt, ap );
+ fprintf( stderr, "\n" );
+
+ va_end( ap );
+
+ if ( fgState.Initialised )
+ fgDeinitialize ();
+
+ exit( 1 );
+}
+
+void fgWarning( const char *fmt, ... )
+{
+ va_list ap;
+
+ va_start( ap, fmt );
+
+ fprintf( stderr, "freeglut ");
+ if( fgState.ProgramName )
+ fprintf( stderr, "(%s): ", fgState.ProgramName );
+ vfprintf( stderr, fmt, ap );
+ fprintf( stderr, "\n" );
+
+ va_end( ap );
+}
+
+/*
+ * Indicates whether Joystick events are being used by ANY window.
+ *
+ * The current mechanism is to walk all of the windows and ask if
+ * there is a joystick callback. We have a short-circuit early
+ * return if we find any joystick handler registered.
+ *
+ * The real way to do this is to make use of the glutTimer() API
+ * to more cleanly re-implement the joystick API. Then, this code
+ * and all other "joystick timer" code can be yanked.
+ *
+ */
+static void fgCheckJoystickCallback( SFG_Window* w, SFG_Enumerator* e)
+{
+ if( FETCH_WCB( *w, Joystick ) )
+ {
+ e->found = GL_TRUE;
+ e->data = w;
+ }
+ fgEnumSubWindows( w, fgCheckJoystickCallback, e );
+}
+static int fgHaveJoystick( void )
+{
+ SFG_Enumerator enumerator;
+ enumerator.found = GL_FALSE;
+ enumerator.data = NULL;
+ fgEnumWindows( fgCheckJoystickCallback, &enumerator );
+ return !!enumerator.data;
+}
+static void fgHavePendingRedisplaysCallback( SFG_Window* w, SFG_Enumerator* e)
+{
+ if( w->State.Redisplay )
+ {
+ e->found = GL_TRUE;
+ e->data = w;
+ }
+ fgEnumSubWindows( w, fgHavePendingRedisplaysCallback, e );
+}
+static int fgHavePendingRedisplays (void)
+{
+ SFG_Enumerator enumerator;
+ enumerator.found = GL_FALSE;
+ enumerator.data = NULL;
+ fgEnumWindows( fgHavePendingRedisplaysCallback, &enumerator );
+ return !!enumerator.data;
+}
+/*
+ * Returns the number of GLUT ticks (milliseconds) till the next timer event.
+ */
+static long fgNextTimer( void )
+{
+ long ret = INT_MAX;
+ SFG_Timer *timer = fgState.Timers.First;
+
+ if( timer )
+ ret = timer->TriggerTime - fgElapsedTime();
+ if( ret < 0 )
+ ret = 0;
+
+ return ret;
+}
+/*
+ * Does the magic required to relinquish the CPU until something interesting
+ * happens.
+ */
+static void fgSleepForEvents( void )
+{
+ long msec;
+
+ if( fgState.IdleCallback || fgHavePendingRedisplays( ) )
+ return;
+
+ msec = fgNextTimer( );
+ if( fgHaveJoystick( ) ) /* XXX Use GLUT timers for joysticks... */
+ msec = MIN( msec, 10 ); /* XXX Dumb; forces granularity to .01sec */
+
+#if TARGET_HOST_UNIX_X11
+ /*
+ * Possibly due to aggressive use of XFlush() and friends,
+ * it is possible to have our socket drained but still have
+ * unprocessed events. (Or, this may just be normal with
+ * X, anyway?) We do non-trivial processing of X events
+ * after tham in event-reading loop, in any case, so we
+ * need to allow that we may have an empty socket but non-
+ * empty event queue.
+ */
+ if( ! XPending( fgDisplay.Display ) )
+ {
+ fd_set fdset;
+ int err;
+ int socket;
+ struct timeval wait;
+
+ socket = ConnectionNumber( fgDisplay.Display );
+ FD_ZERO( &fdset );
+ FD_SET( socket, &fdset );
+ wait.tv_sec = msec / 1000;
+ wait.tv_usec = (msec % 1000) * 1000;
+ err = select( socket+1, &fdset, NULL, NULL, &wait );
+
+ if( -1 == err )
+ fgWarning ( "freeglut select() error: %d\n", errno );
+ }
+#elif TARGET_HOST_WIN32 || TARGET_HOST_WINCE
+ MsgWaitForMultipleObjects( 0, NULL, FALSE, msec, QS_ALLEVENTS );
+#endif
+}
+
+#if TARGET_HOST_UNIX_X11
+/*
+ * Returns GLUT modifier mask for an XEvent.
+ */
+int fgGetXModifiers( XEvent *event )
+{
+ int ret = 0;
+
+ if( event->xkey.state & ( ShiftMask | LockMask ) )
+ ret |= GLUT_ACTIVE_SHIFT;
+ if( event->xkey.state & ControlMask )
+ ret |= GLUT_ACTIVE_CTRL;
+ if( event->xkey.state & Mod1Mask )
+ ret |= GLUT_ACTIVE_ALT;
+
+ return ret;
+}
+#endif
+
+
+/* -- INTERFACE FUNCTIONS -------------------------------------------------- */
+
+/*
+ * Executes a single iteration in the freeglut processing loop.
+ */
+void FGAPIENTRY glutMainLoopEvent( void )
+{
+#if TARGET_HOST_UNIX_X11
+ SFG_Window* window;
+ XEvent event;
+
+ /*
+ * This code was repeated constantly, so here it goes into a definition:
+ */
+#define GETWINDOW(a) \
+ window = fgWindowByHandle( event.a.window ); \
+ if( window == NULL ) \
+ break;
+
+#define GETMOUSE(a) \
+ window->State.MouseX = event.a.x; \
+ window->State.MouseY = event.a.y;
+
+ freeglut_assert_ready;
+
+ while( XPending( fgDisplay.Display ) )
+ {
+ XNextEvent( fgDisplay.Display, &event );
+
+ switch( event.type )
+ {
+ case ClientMessage:
+ /*
+ * Destroy the window when the WM_DELETE_WINDOW message arrives
+ */
+ if( (Atom) event.xclient.data.l[ 0 ] == fgDisplay.DeleteWindow )
+ {
+ GETWINDOW( xclient );
+
+ fgDestroyWindow ( window );
+
+ if( fgState.ActionOnWindowClose == GLUT_ACTION_EXIT )
+ {
+ fgDeinitialize( );
+ exit( 0 );
+ }
+ else if( fgState.ActionOnWindowClose == GLUT_ACTION_GLUTMAINLOOP_RETURNS
)
+ fgState.ExecState = GLUT_EXEC_STATE_STOP;
+
+ return;
+ }
+ break;
+
+ /*
+ * CreateNotify causes a configure-event so that sub-windows are
+ * handled compatibly with GLUT. Otherwise, your sub-windows
+ * (in freeglut only) will not get an initial reshape event,
+ * which can break things.
+ *
+ * GLUT presumably does this because it generally tries to treat
+ * sub-windows the same as windows.
+ *
+ * XXX Technically, GETWINDOW( xconfigure ) and
+ * XXX {event.xconfigure} may not be legit ways to get at
+ * XXX data for CreateNotify events. In practice, the data
+ * XXX is in a union which is laid out much the same either
+ * XXX way. But if you want to split hairs, this isn't legit,
+ * XXX and we should instead duplicate some code.
+ */
+ case CreateNotify:
+ case ConfigureNotify:
+ GETWINDOW( xconfigure );
+ {
+ int width = event.xconfigure.width;
+ int height = event.xconfigure.height;
+
+ if( ( width != window->State.OldWidth ) ||
+ ( height != window->State.OldHeight ) )
+ {
+ window->State.OldWidth = width;
+ window->State.OldHeight = height;
+ if( FETCH_WCB( *window, Reshape ) )
+ INVOKE_WCB( *window, Reshape, ( width, height ) );
+ else
+ {
+ fgSetWindow( window );
+ glViewport( 0, 0, width, height );
+ }
+ glutPostRedisplay( );
+ }
+ }
+ break;
+
+ case DestroyNotify:
+ /*
+ * This is sent to confirm the XDestroyWindow call.
+ *
+ * XXX WHY is this commented out? Should we re-enable it?
+ */
+ /* fgAddToWindowDestroyList ( window ); */
+ break;
+
+ case Expose:
+ /*
+ * We are too dumb to process partial exposes...
+ *
+ * XXX Well, we could do it. However, it seems to only
+ * XXX be potentially useful for single-buffered (since
+ * XXX double-buffered does not respect viewport when we
+ * XXX do a buffer-swap).
+ *
+ */
+ if( event.xexpose.count == 0 )
+ {
+ GETWINDOW( xexpose );
+ fgSetWindow( window );
+ glutPostRedisplay( );
+ }
+ break;
+
+ case MapNotify:
+ case UnmapNotify:
+ /*
+ * If we never do anything with this, can we just not ask to
+ * get these messages?
+ */
+ break;
+
+ case MappingNotify:
+ /*
+ * Have the client's keyboard knowledge updated (xlib.ps,
+ * page 206, says that's a good thing to do)
+ */
+ XRefreshKeyboardMapping( (XMappingEvent *) &event );
+ break;
+
+ case VisibilityNotify:
+ {
+ GETWINDOW( xvisibility );
+ /*
+ * XXX INVOKE_WCB() does this check for us.
+ */
+ if( ! FETCH_WCB( *window, WindowStatus ) )
+ break;
+ fgSetWindow( window );
+
+ /*
+ * Sending this event, the X server can notify us that the window
+ * has just acquired one of the three possible visibility states:
+ * VisibilityUnobscured, VisibilityPartiallyObscured or
+ * VisibilityFullyObscured
+ */
+ switch( event.xvisibility.state )
+ {
+ case VisibilityUnobscured:
+ INVOKE_WCB( *window, WindowStatus, ( GLUT_FULLY_RETAINED ) );
+ window->State.Visible = GL_TRUE;
+ break;
+
+ case VisibilityPartiallyObscured:
+ INVOKE_WCB( *window, WindowStatus,
+ ( GLUT_PARTIALLY_RETAINED ) );
+ window->State.Visible = GL_TRUE;
+ break;
+
+ case VisibilityFullyObscured:
+ INVOKE_WCB( *window, WindowStatus, ( GLUT_FULLY_COVERED ) );
+ window->State.Visible = GL_FALSE;
+ break;
+
+ default:
+ fgWarning( "Uknown X visibility state: %d",
+ event.xvisibility.state );
+ break;
+ }
+ }
+ break;
+
+ case EnterNotify:
+ case LeaveNotify:
+ GETWINDOW( xcrossing );
+ GETMOUSE( xcrossing );
+ INVOKE_WCB( *window, Entry, ( ( EnterNotify == event.type ) ?
+ GLUT_ENTERED :
+ GLUT_LEFT ) );
+ break;
+
+ case MotionNotify:
+ {
+ GETWINDOW( xmotion );
+ GETMOUSE( xmotion );
+
+ if( window->ActiveMenu )
+ {
+ if( window == window->ActiveMenu->ParentWindow )
+ {
+ window->ActiveMenu->Window->State.MouseX =
+ event.xmotion.x_root - window->ActiveMenu->X;
+ window->ActiveMenu->Window->State.MouseY =
+ event.xmotion.y_root - window->ActiveMenu->Y;
+ }
+ window->ActiveMenu->Window->State.Redisplay = GL_TRUE ;
+ fgSetWindow( window->ActiveMenu->ParentWindow );
+
+ break;
+ }
+
+ /*
+ * XXX For more than 5 buttons, just check {event.xmotion.state},
+ * XXX rather than a host of bit-masks? Or maybe we need to
+ * XXX track ButtonPress/ButtonRelease events in our own
+ * XXX bit-mask?
+ */
+#define BUTTON_MASK \
+ ( Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask )
+ if ( event.xmotion.state & BUTTON_MASK )
+ INVOKE_WCB( *window, Motion, ( event.xmotion.x,
+ event.xmotion.y ) );
+ else
+ INVOKE_WCB( *window, Passive, ( event.xmotion.x,
+ event.xmotion.y ) );
+ }
+ break;
+
+ case ButtonRelease:
+ case ButtonPress:
+ {
+ GLboolean pressed = GL_TRUE;
+ int button;
+
+ if( event.type == ButtonRelease )
+ pressed = GL_FALSE ;
+
+ /*
+ * A mouse button has been pressed or released. Traditionally,
+ * break if the window was found within the freeglut structures.
+ */
+ GETWINDOW( xbutton );
+ GETMOUSE( xbutton );
+
+ /*
+ * An X button (at least in XFree86) is numbered from 1.
+ * A GLUT button is numbered from 0.
+ * Old GLUT passed through buttons other than just the first
+ * three, though it only gave symbolic names and official
+ * support to the first three.
+ */
+ button = event.xbutton.button - 1;
+
+ /*
+ * XXX This comment is replicated in the WIN32 section and
+ * XXX maybe also in the menu code. Can we move the info
+ * XXX to one central place and *reference* it from here?
+ *
+ * Do not execute the application's mouse callback if a menu
+ * is hooked to this button. In that case an appropriate
+ * private call should be generated.
+ * Near as I can tell, this is the menu behaviour:
+ * - Down-click the menu button, menu not active: activate
+ * the menu with its upper left-hand corner at the mouse
+ * location.
+ * - Down-click any button outside the menu, menu active:
+ * deactivate the menu
+ * - Down-click any button inside the menu, menu active:
+ * select the menu entry and deactivate the menu
+ * - Up-click the menu button, menu not active: nothing happens
+ * - Up-click the menu button outside the menu, menu active:
+ * nothing happens
+ * - Up-click the menu button inside the menu, menu active:
+ * select the menu entry and deactivate the menu
+ */
+ /* Window has an active menu, it absorbs any mouse click */
+ if( window->ActiveMenu )
+ {
+ if( window == window->ActiveMenu->ParentWindow )
+ {
+ window->ActiveMenu->Window->State.MouseX =
+ event.xbutton.x_root - window->ActiveMenu->X;
+ window->ActiveMenu->Window->State.MouseY =
+ event.xbutton.y_root - window->ActiveMenu->Y;
+ }
+
+ /* In the menu, invoke the callback and deactivate the menu*/
+ if( fgCheckActiveMenu( window->ActiveMenu->Window,
+ window->ActiveMenu ) )
+ {
+ /*
+ * Save the current window and menu and set the current
+ * window to the window whose menu this is
+ */
+ SFG_Window *save_window = fgStructure.Window;
+ SFG_Menu *save_menu = fgStructure.Menu;
+ SFG_Window *parent_window =
+ window->ActiveMenu->ParentWindow;
+ fgSetWindow( parent_window );
+ fgStructure.Menu = window->ActiveMenu;
+
+ /* Execute the menu callback */
+ fgExecuteMenuCallback( window->ActiveMenu );
+ fgDeactivateMenu( parent_window );
+
+ /* Restore the current window and menu */
+ fgSetWindow( save_window );
+ fgStructure.Menu = save_menu;
+ }
+ else if( pressed )
+ /*
+ * Outside the menu, deactivate if it's a downclick
+ *
+ * XXX This isn't enough. A downclick outside of
+ * XXX the interior of our freeglut windows should also
+ * XXX deactivate the menu. This is more complicated.
+ */
+ fgDeactivateMenu( window->ActiveMenu->ParentWindow );
+
+ /*
+ * XXX Why does an active menu require a redisplay at
+ * XXX this point? If this can come out cleanly, then
+ * XXX it probably should do so; if not, a comment should
+ * XXX explain it.
+ */
+ window->State.Redisplay = GL_TRUE;
+ break;
+ }
+
+ /*
+ * No active menu, let's check whether we need to activate one.
+ */
+ if( ( 0 <= button ) &&
+ ( FREEGLUT_MAX_MENUS > button ) &&
+ ( window->Menu[ button ] ) &&
+ pressed )
+ {
+ /*
+ * XXX Posting a requisite Redisplay seems bogus.
+ */
+ window->State.Redisplay = GL_TRUE;
+ fgSetWindow( window );
+ fgActivateMenu( window, button );
+ break;
+ }
+
+ /*
+ * Check if there is a mouse or mouse wheel callback hooked to the
+ * window
+ */
+ if( ! FETCH_WCB( *window, Mouse ) &&
+ ! FETCH_WCB( *window, MouseWheel ) )
+ break;
+
+ fgState.Modifiers = fgGetXModifiers( &event );
+
+ /*
+ * Finally execute the mouse or mouse wheel callback
+ *
+ * XXX Use a symbolic constant, *not* "4"! ("3, sire!")
+ */
+ if( ( button < 3 ) || ( ! FETCH_WCB( *window, MouseWheel ) ) )
+ INVOKE_WCB( *window, Mouse, ( button,
+ pressed ? GLUT_DOWN : GLUT_UP,
+ event.xbutton.x,
+ event.xbutton.y )
+ );
+ else
+ {
+ /*
+ * Map 4 and 5 to wheel zero; EVEN to +1, ODD to -1
+ * " 6 and 7 " " one; ...
+ *
+ * XXX This *should* be behind some variables/macros,
+ * XXX since the order and numbering isn't certain
+ * XXX See XFree86 configuration docs (even back in the
+ * XXX 3.x days, and especially with 4.x).
+ *
+ * XXX Note that {button} has already been decremeted
+ * XXX in mapping from X button numbering to GLUT.
+ */
+ int wheel_number = (button - 3) / 2;
+ int direction = -1;
+ if( button % 2 )
+ direction = 1;
+
+ if( pressed )
+ INVOKE_WCB( *window, MouseWheel, ( wheel_number,
+ direction,
+ event.xbutton.x,
+ event.xbutton.y )
+ );
+ }
+
+ /*
+ * Trash the modifiers state
+ */
+ fgState.Modifiers = 0xffffffff;
+ }
+ break;
+
+ case KeyRelease:
+ case KeyPress:
+ {
+ FGCBKeyboard keyboard_cb;
+ FGCBSpecial special_cb;
+
+ GETWINDOW( xkey );
+ GETMOUSE( xkey );
+
+ /* Detect auto repeated keys, if configured globally or per-window */
+
+ if ( fgState.KeyRepeat==GLUT_KEY_REPEAT_OFF ||
window->State.IgnoreKeyRepeat==GL_TRUE )
+ {
+ if (event.type==KeyRelease)
+ {
+ /*
+ * Look at X11 keystate to detect repeat mode.
+ * While X11 says the key is actually held down, we'll ignore
KeyRelease/KeyPress pairs.
+ */
+
+ char keys[32];
+ XQueryKeymap( fgDisplay.Display, keys ); /* Look at X11 keystate to
detect repeat mode */
+
+ if ( event.xkey.keycode<256 ) /* XQueryKeymap is
limited to 256 keycodes */
+ {
+ if ( keys[event.xkey.keycode>>3] &
(1<<(event.xkey.keycode%8)) )
+ window->State.KeyRepeating = GL_TRUE;
+ else
+ window->State.KeyRepeating = GL_FALSE;
+ }
+ }
+ }
+ else
+ window->State.KeyRepeating = GL_FALSE;
+
+ /* Cease processing this event if it is auto repeated */
+
+ if (window->State.KeyRepeating)
+ break;
+
+ if( event.type == KeyPress )
+ {
+ keyboard_cb = FETCH_WCB( *window, Keyboard );
+ special_cb = FETCH_WCB( *window, Special );
+ }
+ else
+ {
+ keyboard_cb = FETCH_WCB( *window, KeyboardUp );
+ special_cb = FETCH_WCB( *window, SpecialUp );
+ }
+
+ /*
+ * Is there a keyboard/special callback hooked for this window?
+ */
+ if( keyboard_cb || special_cb )
+ {
+ XComposeStatus composeStatus;
+ char asciiCode[ 32 ];
+ KeySym keySym;
+ int len;
+
+ /*
+ * Check for the ASCII/KeySym codes associated with the event:
+ */
+ len = XLookupString( &event.xkey, asciiCode, sizeof(asciiCode),
+ &keySym, &composeStatus
+ );
+
+ /*
+ * GLUT API tells us to have two separate callbacks...
+ */
+ if( len > 0 )
+ {
+ /*
+ * ...one for the ASCII translateable keypresses...
+ */
+ if( keyboard_cb )
+ {
+ fgSetWindow( window );
+ fgState.Modifiers = fgGetXModifiers( &event );
+ keyboard_cb( asciiCode[ 0 ],
+ event.xkey.x, event.xkey.y
+ );
+ fgState.Modifiers = 0xffffffff;
+ }
+ }
+ else
+ {
+ int special = -1;
+
+ /*
+ * ...and one for all the others, which need to be
+ * translated to GLUT_KEY_Xs...
+ */
+ switch( keySym )
+ {
+ case XK_F1: special = GLUT_KEY_F1; break;
+ case XK_F2: special = GLUT_KEY_F2; break;
+ case XK_F3: special = GLUT_KEY_F3; break;
+ case XK_F4: special = GLUT_KEY_F4; break;
+ case XK_F5: special = GLUT_KEY_F5; break;
+ case XK_F6: special = GLUT_KEY_F6; break;
+ case XK_F7: special = GLUT_KEY_F7; break;
+ case XK_F8: special = GLUT_KEY_F8; break;
+ case XK_F9: special = GLUT_KEY_F9; break;
+ case XK_F10: special = GLUT_KEY_F10; break;
+ case XK_F11: special = GLUT_KEY_F11; break;
+ case XK_F12: special = GLUT_KEY_F12; break;
+
+ case XK_Left: special = GLUT_KEY_LEFT; break;
+ case XK_Right: special = GLUT_KEY_RIGHT; break;
+ case XK_Up: special = GLUT_KEY_UP; break;
+ case XK_Down: special = GLUT_KEY_DOWN; break;
+
+ case XK_KP_Prior:
+ case XK_Prior: special = GLUT_KEY_PAGE_UP; break;
+ case XK_KP_Next:
+ case XK_Next: special = GLUT_KEY_PAGE_DOWN; break;
+ case XK_KP_Home:
+ case XK_Home: special = GLUT_KEY_HOME; break;
+ case XK_KP_End:
+ case XK_End: special = GLUT_KEY_END; break;
+ case XK_KP_Insert:
+ case XK_Insert: special = GLUT_KEY_INSERT; break;
+ }
+
+ /*
+ * Execute the callback (if one has been specified),
+ * given that the special code seems to be valid...
+ */
+ if( special_cb && (special != -1) )
+ {
+ fgSetWindow( window );
+ fgState.Modifiers = fgGetXModifiers( &event );
+ special_cb( special, event.xkey.x, event.xkey.y );
+ fgState.Modifiers = 0xffffffff;
+ }
+ }
+ }
+ }
+ break;
+
+ case ReparentNotify:
+ break; /* XXX Should disable this event */
+
+ default:
+ fgWarning ("Unknown X event type: %d", event.type);
+ break;
+ }
+ }
+
+#elif TARGET_HOST_WIN32 || TARGET_HOST_WINCE
+
+ MSG stMsg;
+
+ while( PeekMessage( &stMsg, NULL, 0, 0, PM_NOREMOVE ) )
+ {
+ if( GetMessage( &stMsg, NULL, 0, 0 ) == 0 )
+ {
+ if( fgState.ActionOnWindowClose == GLUT_ACTION_EXIT )
+ {
+ fgDeinitialize( );
+ exit( 0 );
+ }
+ else if( fgState.ActionOnWindowClose == GLUT_ACTION_GLUTMAINLOOP_RETURNS )
+ fgState.ExecState = GLUT_EXEC_STATE_STOP;
+
+ return;
+ }
+
+ TranslateMessage( &stMsg );
+ DispatchMessage( &stMsg );
+ }
+#endif
+
+ if( fgState.Timers.First )
+ fghCheckTimers( );
+ fghCheckJoystickPolls( );
+ fghDisplayAll( );
+
+ fgCloseWindows( );
+}
+
+/*
+ * Enters the freeglut processing loop.
+ * Stays until the "ExecState" changes to "GLUT_EXEC_STATE_STOP".
+ */
+void FGAPIENTRY glutMainLoop( void )
+{
+ int action;
+
+#if TARGET_HOST_WIN32 || TARGET_HOST_WINCE
+ SFG_Window *window = (SFG_Window *)fgStructure.Windows.First ;
+#endif
+
+ freeglut_assert_ready;
+
+#if TARGET_HOST_WIN32 || TARGET_HOST_WINCE
+ /*
+ * Processing before the main loop: If there is a window which is open and
+ * which has a visibility callback, call it. I know this is an ugly hack,
+ * but I'm not sure what else to do about it. Ideally we should leave
+ * something uninitialized in the create window code and initialize it in
+ * the main loop, and have that initialization create a "WM_ACTIVATE"
+ * message. Then we would put the visibility callback code in the
+ * "case WM_ACTIVATE" block below. - John Fay -- 10/24/02
+ */
+ while( window )
+ {
+ if ( FETCH_WCB( *window, Visibility ) )
+ {
+ SFG_Window *current_window = fgStructure.Window ;
+
+ INVOKE_WCB( *window, Visibility, ( window->State.Visible ) );
+ fgSetWindow( current_window );
+ }
+
+ window = (SFG_Window *)window->Node.Next ;
+ }
+#endif
+
+ fgState.ExecState = GLUT_EXEC_STATE_RUNNING ;
+ while( fgState.ExecState == GLUT_EXEC_STATE_RUNNING )
+ {
+ SFG_Window *window;
+
+ glutMainLoopEvent( );
+ /*
+ * Step through the list of windows, seeing if there are any
+ * that are not menus
+ */
+ for( window = ( SFG_Window * )fgStructure.Windows.First;
+ window;
+ window = ( SFG_Window * )window->Node.Next )
+ if ( ! ( window->IsMenu ) )
+ break;
+
+ if( ! window )
+ fgState.ExecState = GLUT_EXEC_STATE_STOP;
+ else
+ {
+ if( fgState.IdleCallback )
+ fgState.IdleCallback( );
+
+ fgSleepForEvents( );
+ }
+ }
+
+ /*
+ * When this loop terminates, destroy the display, state and structure
+ * of a freeglut session, so that another glutInit() call can happen
+ *
+ * Save the "ActionOnWindowClose" because "fgDeinitialize" resets
it.
+ */
+ action = fgState.ActionOnWindowClose;
+ fgDeinitialize( );
+ if( action == GLUT_ACTION_EXIT )
+ exit( 0 );
+}
+
+/*
+ * Leaves the freeglut processing loop.
+ */
+void FGAPIENTRY glutLeaveMainLoop( void )
+{
+ fgState.ExecState = GLUT_EXEC_STATE_STOP ;
+}
+
+
+#if TARGET_HOST_WIN32 || TARGET_HOST_WINCE
+/*
+ * Determine a GLUT modifer mask based on MS-WINDOWS system info.
+ */
+int fgGetWin32Modifiers (void)
+{
+ return
+ ( ( ( GetKeyState( VK_LSHIFT ) < 0 ) ||
+ ( GetKeyState( VK_RSHIFT ) < 0 )) ? GLUT_ACTIVE_SHIFT : 0 ) |
+ ( ( ( GetKeyState( VK_LCONTROL ) < 0 ) ||
+ ( GetKeyState( VK_RCONTROL ) < 0 )) ? GLUT_ACTIVE_CTRL : 0 ) |
+ ( ( ( GetKeyState( VK_LMENU ) < 0 ) ||
+ ( GetKeyState( VK_RMENU ) < 0 )) ? GLUT_ACTIVE_ALT : 0 );
+}
+
+/*
+ * The window procedure for handling Win32 events
+ */
+LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
+ LPARAM lParam )
+{
+ SFG_Window* window = fgWindowByHandle( hWnd );
+ PAINTSTRUCT ps;
+ LONG lRet = 1;
+
+ if ( ( window == NULL ) && ( uMsg != WM_CREATE ) )
+ return DefWindowProc( hWnd, uMsg, wParam, lParam );
+
+ /* printf ( "Window %3d message <%04x> %12d %12d\n",
window?window->ID:0,
+ uMsg, wParam, lParam ); */
+ switch( uMsg )
+ {
+ case WM_CREATE:
+ /*
+ * The window structure is passed as the creation structure paramter...
+ */
+ window = (SFG_Window *) (((LPCREATESTRUCT) lParam)->lpCreateParams);
+ assert( window != NULL );
+
+ window->Window.Handle = hWnd;
+ window->Window.Device = GetDC( hWnd );
+ if( window->IsMenu )
+ {
+ unsigned int current_DisplayMode = fgState.DisplayMode;
+ fgState.DisplayMode = GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH;
+#if !TARGET_HOST_WINCE
+ fgSetupPixelFormat( window, GL_FALSE, PFD_MAIN_PLANE );
+#endif
+ fgState.DisplayMode = current_DisplayMode;
+
+ if( fgStructure.MenuContext )
+ wglMakeCurrent( window->Window.Device,
+ fgStructure.MenuContext->Context
+ );
+ else
+ {
+ fgStructure.MenuContext =
+ (SFG_MenuContext *)malloc( sizeof(SFG_MenuContext) );
+ fgStructure.MenuContext->Context =
+ wglCreateContext( window->Window.Device );
+ }
+
+ /* window->Window.Context = wglGetCurrentContext (); */
+ window->Window.Context = wglCreateContext( window->Window.Device );
+ }
+ else
+ {
+#if !TARGET_HOST_WINCE
+ fgSetupPixelFormat( window, GL_FALSE, PFD_MAIN_PLANE );
+#endif
+
+ if( ! fgState.UseCurrentContext )
+ window->Window.Context =
+ wglCreateContext( window->Window.Device );
+ else
+ {
+ window->Window.Context = wglGetCurrentContext( );
+ if( ! window->Window.Context )
+ window->Window.Context =
+ wglCreateContext( window->Window.Device );
+ }
+ }
+
+ window->State.NeedToResize = GL_TRUE;
+ window->State.Width = fgState.Size.X;
+ window->State.Height = fgState.Size.Y;
+
+ ReleaseDC( window->Window.Handle, window->Window.Device );
+
+#if TARGET_HOST_WINCE
+ /* Take over button handling */
+ {
+ HINSTANCE dxDllLib=LoadLibrary(_T("gx.dll"));
+ if (dxDllLib)
+ {
+ GXGetDefaultKeys_=(GXGETDEFAULTKEYS)GetProcAddress(dxDllLib,
_T("?GXGetDefaultKeys@@YA?AUGXKeyList@@H@Z"));
+ GXOpenInput_=(GXOPENINPUT)GetProcAddress(dxDllLib,
_T("?GXOpenInput@@YAHXZ"));
+ }
+
+ if(GXOpenInput_)
+ (*GXOpenInput_)();
+ if(GXGetDefaultKeys_)
+ gxKeyList = (*GXGetDefaultKeys_)(GX_LANDSCAPEKEYS);
+ }
+
+#endif /* TARGET_HOST_WINCE */
+ break;
+
+ case WM_SIZE:
+ /*
+ * If the window is visible, then it is the user manually resizing it.
+ * If it is not, then it is the system sending us a dummy resize with
+ * zero dimensions on a "glutIconifyWindow" call.
+ */
+ if( window->State.Visible )
+ {
+ window->State.NeedToResize = GL_TRUE;
+#if TARGET_HOST_WINCE
+ window->State.Width = HIWORD(lParam);
+ window->State.Height = LOWORD(lParam);
+#else
+ window->State.Width = LOWORD(lParam);
+ window->State.Height = HIWORD(lParam);
+#endif /* TARGET_HOST_WINCE */
+ }
+
+ break;
+#if 0
+ case WM_SETFOCUS:
+ printf("WM_SETFOCUS: %p\n", window );
+ lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
+ break;
+
+ case WM_ACTIVATE:
+ if (LOWORD(wParam) != WA_INACTIVE)
+ {
+ /* glutSetCursor( fgStructure.Window->State.Cursor ); */
+ printf("WM_ACTIVATE: glutSetCursor( %p, %d)\n", window,
+ window->State.Cursor );
+ glutSetCursor( window->State.Cursor );
+ }
+
+ lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
+ break;
+#endif
+
+ /*
+ * XXX Why not re-use some common code with the glutSetCursor()
+ * XXX function (or perhaps invoke glutSetCursor())?
+ * XXX That is, why are we duplicating code, here, from
+ * XXX glutSetCursor()? The WIN32 code should be able to just
+ * XXX call glutSetCurdsor() instead of defining two macros
+ * XXX and implementing a nested case in-line.
+ */
+ case WM_SETCURSOR:
+ /* Set the cursor AND change it for this window class. */
+#define MAP_CURSOR(a,b) \
+ case a: \
+ SetCursor( LoadCursor( NULL, b ) ); \
+ break;
+
+ /* Nuke the cursor AND change it for this window class. */
+#define ZAP_CURSOR(a,b) \
+ case a: \
+ SetCursor( NULL ); \
+ break;
+
+ if( LOWORD( lParam ) == HTCLIENT )
+ switch( window->State.Cursor )
+ {
+ MAP_CURSOR( GLUT_CURSOR_RIGHT_ARROW, IDC_ARROW );
+ MAP_CURSOR( GLUT_CURSOR_LEFT_ARROW, IDC_ARROW );
+ MAP_CURSOR( GLUT_CURSOR_INFO, IDC_HELP );
+ MAP_CURSOR( GLUT_CURSOR_DESTROY, IDC_CROSS );
+ MAP_CURSOR( GLUT_CURSOR_HELP, IDC_HELP );
+ MAP_CURSOR( GLUT_CURSOR_CYCLE, IDC_SIZEALL );
+ MAP_CURSOR( GLUT_CURSOR_SPRAY, IDC_CROSS );
+ MAP_CURSOR( GLUT_CURSOR_WAIT, IDC_WAIT );
+ MAP_CURSOR( GLUT_CURSOR_TEXT, IDC_UPARROW );
+ MAP_CURSOR( GLUT_CURSOR_CROSSHAIR, IDC_CROSS );
+ /* MAP_CURSOR( GLUT_CURSOR_NONE, IDC_NO ); */
+ ZAP_CURSOR( GLUT_CURSOR_NONE, NULL );
+
+ default:
+ MAP_CURSOR( GLUT_CURSOR_UP_DOWN, IDC_ARROW );
+ }
+ else
+ lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
+ break;
+
+ case WM_SHOWWINDOW:
+ window->State.Visible = GL_TRUE;
+ window->State.Redisplay = GL_TRUE;
+ break;
+
+ case WM_PAINT:
+ /* Turn on the visibility in case it was turned off somehow */
+ window->State.Visible = GL_TRUE;
+ BeginPaint( hWnd, &ps );
+ fghRedrawWindowByHandle( hWnd );
+ EndPaint( hWnd, &ps );
+ break;
+
+ case WM_CLOSE:
+ fgDestroyWindow ( window );
+ if ( fgState.ActionOnWindowClose != GLUT_ACTION_CONTINUE_EXECUTION )
+ PostQuitMessage(0);
+ break;
+
+ case WM_DESTROY:
+ /*
+ * The window already got destroyed, so don't bother with it.
+ */
+ return 0;
+
+ case WM_MOUSEMOVE:
+ {
+#if TARGET_HOST_WINCE
+ window->State.MouseX = 320-HIWORD( lParam );
+ window->State.MouseY = LOWORD( lParam );
+#else
+ window->State.MouseX = LOWORD( lParam );
+ window->State.MouseY = HIWORD( lParam );
+#endif /* TARGET_HOST_WINCE */
+
+ if ( window->ActiveMenu )
+ {
+ window->State.Redisplay = GL_TRUE;
+ fgSetWindow ( window->ActiveMenu->ParentWindow );
+ break;
+ }
+
+ fgState.Modifiers = fgGetWin32Modifiers( );
+
+ if( ( wParam & MK_LBUTTON ) ||
+ ( wParam & MK_MBUTTON ) ||
+ ( wParam & MK_RBUTTON ) )
+ INVOKE_WCB( *window, Motion, ( window->State.MouseX,
+ window->State.MouseY ) );
+ else
+ INVOKE_WCB( *window, Passive, ( window->State.MouseX,
+ window->State.MouseY ) );
+
+ fgState.Modifiers = 0xffffffff;
+ }
+ break;
+
+ case WM_LBUTTONDOWN:
+ case WM_MBUTTONDOWN:
+ case WM_RBUTTONDOWN:
+ case WM_LBUTTONUP:
+ case WM_MBUTTONUP:
+ case WM_RBUTTONUP:
+ {
+ GLboolean pressed = GL_TRUE;
+ int button;
+
+#if TARGET_HOST_WINCE
+ window->State.MouseX = 320-HIWORD( lParam );
+ window->State.MouseY = LOWORD( lParam );
+#else
+ window->State.MouseX = LOWORD( lParam );
+ window->State.MouseY = HIWORD( lParam );
+#endif /* TARGET_HOST_WINCE */
+
+ switch( uMsg )
+ {
+ case WM_LBUTTONDOWN:
+ pressed = GL_TRUE;
+ button = GLUT_LEFT_BUTTON;
+ break;
+ case WM_MBUTTONDOWN:
+ pressed = GL_TRUE;
+ button = GLUT_MIDDLE_BUTTON;
+ break;
+ case WM_RBUTTONDOWN:
+ pressed = GL_TRUE;
+ button = GLUT_RIGHT_BUTTON;
+ break;
+ case WM_LBUTTONUP:
+ pressed = GL_FALSE;
+ button = GLUT_LEFT_BUTTON;
+ break;
+ case WM_MBUTTONUP:
+ pressed = GL_FALSE;
+ button = GLUT_MIDDLE_BUTTON;
+ break;
+ case WM_RBUTTONUP:
+ pressed = GL_FALSE;
+ button = GLUT_RIGHT_BUTTON;
+ break;
+ default:
+ pressed = GL_FALSE;
+ button = -1;
+ break;
+ }
+
+#if !TARGET_HOST_WINCE
+ if( GetSystemMetrics( SM_SWAPBUTTON ) )
+ {
+ if( button == GLUT_LEFT_BUTTON )
+ button = GLUT_RIGHT_BUTTON;
+ else
+ if( button == GLUT_RIGHT_BUTTON )
+ button = GLUT_LEFT_BUTTON;
+ }
+#endif /* !TARGET_HOST_WINCE */
+
+ if( button == -1 )
+ return DefWindowProc( hWnd, uMsg, lParam, wParam );
+
+ /*
+ * XXX This comment is duplicated in two other spots.
+ * XXX Can we centralize it?
+ *
+ * Do not execute the application's mouse callback if a
+ * menu is hooked to this button.
+ * In that case an appropriate private call should be generated.
+ * Near as I can tell, this is the menu behaviour:
+ * - Down-click the menu button, menu not active: activate
+ * the menu with its upper left-hand corner at the mouse location.
+ * - Down-click any button outside the menu, menu active:
+ * deactivate the menu
+ * - Down-click any button inside the menu, menu active:
+ * select the menu entry and deactivate the menu
+ * - Up-click the menu button, menu not active: nothing happens
+ * - Up-click the menu button outside the menu, menu active:
+ * nothing happens
+ * - Up-click the menu button inside the menu, menu active:
+ * select the menu entry and deactivate the menu
+ */
+ /* Window has an active menu, it absorbs any mouse click */
+ if( window->ActiveMenu )
+ {
+ /* Outside the menu, deactivate the menu if it's a downclick */
+ if( ! fgCheckActiveMenu( window, window->ActiveMenu ) )
+ {
+ if( pressed )
+ fgDeactivateMenu( window->ActiveMenu->ParentWindow );
+ }
+ else /* In menu, invoke the callback and deactivate the menu*/
+ {
+ /*
+ * Save the current window and menu and set the current
+ * window to the window whose menu this is
+ */
+ SFG_Window *save_window = fgStructure.Window;
+ SFG_Menu *save_menu = fgStructure.Menu;
+ SFG_Window *parent_window = window->ActiveMenu->ParentWindow;
+ fgSetWindow( parent_window );
+ fgStructure.Menu = window->ActiveMenu;
+
+ /* Execute the menu callback */
+ fgExecuteMenuCallback( window->ActiveMenu );
+ fgDeactivateMenu( parent_window );
+
+ /* Restore the current window and menu */
+ fgSetWindow( save_window );
+ fgStructure.Menu = save_menu;
+ }
+
+ /*
+ * Let's make the window redraw as a result of the mouse
+ * click and menu activity.
+ */
+ if( ! window->IsMenu )
+ window->State.Redisplay = GL_TRUE;
+
+ break;
+ }
+
+ if( window->Menu[ button ] && pressed )
+ {
+ window->State.Redisplay = GL_TRUE;
+ fgSetWindow( window );
+ fgActivateMenu( window, button );
+
+ break;
+ }
+
+ if( ! FETCH_WCB( *window, Mouse ) )
+ break;
+
+ fgSetWindow( window );
+ fgState.Modifiers = fgGetWin32Modifiers( );
+
+ INVOKE_WCB(
+ *window, Mouse,
+ ( button,
+ pressed ? GLUT_DOWN : GLUT_UP,
+ window->State.MouseX,
+ window->State.MouseY
+ )
+ );
+
+ fgState.Modifiers = 0xffffffff;
+ }
+ break;
+
+ case 0x020a:
+ /* Should be WM_MOUSEWHEEL but my compiler doesn't recognize it */
+ {
+ /*
+ * XXX THIS IS SPECULATIVE -- John Fay, 10/2/03
+ * XXX Should use WHEEL_DELTA instead of 120
+ */
+ int wheel_number = LOWORD( wParam );
+ short ticks = ( short )HIWORD( wParam ) / 120;
+ int direction = 1;
+
+ if( ticks < 0 )
+ {
+ direction = -1;
+ ticks = -ticks;
+ }
+
+ /*
+ * The mouse cursor has moved. Remember the new mouse cursor's position
+ */
+ /* window->State.MouseX = LOWORD( lParam ); */
+ /* Need to adjust by window position, */
+ /* window->State.MouseY = HIWORD( lParam ); */
+ /* change "lParam" to other parameter */
+
+ if( ! FETCH_WCB( *window, MouseWheel ) &&
+ ! FETCH_WCB( *window, Mouse ) )
+ break;
+
+ fgSetWindow( window );
+ fgState.Modifiers = fgGetWin32Modifiers( );
+
+ while( ticks-- )
+ if( FETCH_WCB( *window, MouseWheel ) )
+ INVOKE_WCB( *window, MouseWheel,
+ ( wheel_number,
+ direction,
+ window->State.MouseX,
+ window->State.MouseY
+ )
+ );
+ else /* No mouse wheel, call the mouse button callback twice */
+ {
+ /*
+ * XXX The below assumes that you have no more than 3 mouse
+ * XXX buttons. Sorry.
+ */
+ int button = wheel_number*2 + 3;
+ if( direction < 0 )
+ ++button;
+ INVOKE_WCB( *window, Mouse,
+ ( button, GLUT_DOWN,
+ window->State.MouseX, window->State.MouseY )
+ );
+ INVOKE_WCB( *window, Mouse,
+ ( button, GLUT_UP,
+ window->State.MouseX, window->State.MouseX )
+ );
+ }
+
+ fgState.Modifiers = 0xffffffff;
+ }
+ break ;
+
+ case WM_SYSKEYDOWN:
+ case WM_KEYDOWN:
+ {
+ int keypress = -1;
+ POINT mouse_pos ;
+
+ if( ( fgState.KeyRepeat==GLUT_KEY_REPEAT_OFF ||
window->State.IgnoreKeyRepeat==GL_TRUE ) && (HIWORD(lParam) & KF_REPEAT) )
+ break;
+
+ /*
+ * Remember the current modifiers state. This is done here in order
+ * to make sure the VK_DELETE keyboard callback is executed properly.
+ */
+ fgState.Modifiers = fgGetWin32Modifiers( );
+
+ GetCursorPos( &mouse_pos );
+ ScreenToClient( window->Window.Handle, &mouse_pos );
+
+ window->State.MouseX = mouse_pos.x;
+ window->State.MouseY = mouse_pos.y;
+
+ /*
+ * Convert the Win32 keystroke codes to GLUTtish way
+ */
+# define KEY(a,b) case a: keypress = b; break;
+
+ switch( wParam )
+ {
+ KEY( VK_F1, GLUT_KEY_F1 );
+ KEY( VK_F2, GLUT_KEY_F2 );
+ KEY( VK_F3, GLUT_KEY_F3 );
+ KEY( VK_F4, GLUT_KEY_F4 );
+ KEY( VK_F5, GLUT_KEY_F5 );
+ KEY( VK_F6, GLUT_KEY_F6 );
+ KEY( VK_F7, GLUT_KEY_F7 );
+ KEY( VK_F8, GLUT_KEY_F8 );
+ KEY( VK_F9, GLUT_KEY_F9 );
+ KEY( VK_F10, GLUT_KEY_F10 );
+ KEY( VK_F11, GLUT_KEY_F11 );
+ KEY( VK_F12, GLUT_KEY_F12 );
+ KEY( VK_PRIOR, GLUT_KEY_PAGE_UP );
+ KEY( VK_NEXT, GLUT_KEY_PAGE_DOWN );
+ KEY( VK_HOME, GLUT_KEY_HOME );
+ KEY( VK_END, GLUT_KEY_END );
+ KEY( VK_LEFT, GLUT_KEY_LEFT );
+ KEY( VK_UP, GLUT_KEY_UP );
+ KEY( VK_RIGHT, GLUT_KEY_RIGHT );
+ KEY( VK_DOWN, GLUT_KEY_DOWN );
+ KEY( VK_INSERT, GLUT_KEY_INSERT );
+
+ case VK_DELETE:
+ /*
+ * The delete key should be treated as an ASCII keypress:
+ */
+ INVOKE_WCB( *window, Keyboard,
+ ( 127, window->State.MouseX, window->State.MouseY )
+ );
+ }
+
+#if TARGET_HOST_WINCE
+ if(!(lParam & 0x40000000)) /* Prevent auto-repeat */
+ {
+ if(wParam==(unsigned)gxKeyList.vkRight)
+ keypress = GLUT_KEY_RIGHT;
+ else if(wParam==(unsigned)gxKeyList.vkLeft)
+ keypress = GLUT_KEY_LEFT;
+ else if(wParam==(unsigned)gxKeyList.vkUp)
+ keypress = GLUT_KEY_UP;
+ else if(wParam==(unsigned)gxKeyList.vkDown)
+ keypress = GLUT_KEY_DOWN;
+ else if(wParam==(unsigned)gxKeyList.vkA)
+ keypress = GLUT_KEY_F1;
+ else if(wParam==(unsigned)gxKeyList.vkB)
+ keypress = GLUT_KEY_F2;
+ else if(wParam==(unsigned)gxKeyList.vkC)
+ keypress = GLUT_KEY_F3;
+ else if(wParam==(unsigned)gxKeyList.vkStart)
+ keypress = GLUT_KEY_F4;
+ }
+#endif
+
+ if( keypress != -1 )
+ INVOKE_WCB( *window, Special,
+ ( keypress,
+ window->State.MouseX, window->State.MouseY )
+ );
+
+ fgState.Modifiers = 0xffffffff;
+ }
+ break;
+
+ case WM_SYSKEYUP:
+ case WM_KEYUP:
+ {
+ int keypress = -1;
+ POINT mouse_pos;
+
+ /*
+ * Remember the current modifiers state. This is done here in order
+ * to make sure the VK_DELETE keyboard callback is executed properly.
+ */
+ fgState.Modifiers = fgGetWin32Modifiers( );
+
+ GetCursorPos( &mouse_pos );
+ ScreenToClient( window->Window.Handle, &mouse_pos );
+
+ window->State.MouseX = mouse_pos.x;
+ window->State.MouseY = mouse_pos.y;
+
+ /*
+ * Convert the Win32 keystroke codes to GLUTtish way.
+ * "KEY(a,b)" was defined under "WM_KEYDOWN"
+ */
+
+ switch( wParam )
+ {
+ KEY( VK_F1, GLUT_KEY_F1 );
+ KEY( VK_F2, GLUT_KEY_F2 );
+ KEY( VK_F3, GLUT_KEY_F3 );
+ KEY( VK_F4, GLUT_KEY_F4 );
+ KEY( VK_F5, GLUT_KEY_F5 );
+ KEY( VK_F6, GLUT_KEY_F6 );
+ KEY( VK_F7, GLUT_KEY_F7 );
+ KEY( VK_F8, GLUT_KEY_F8 );
+ KEY( VK_F9, GLUT_KEY_F9 );
+ KEY( VK_F10, GLUT_KEY_F10 );
+ KEY( VK_F11, GLUT_KEY_F11 );
+ KEY( VK_F12, GLUT_KEY_F12 );
+ KEY( VK_PRIOR, GLUT_KEY_PAGE_UP );
+ KEY( VK_NEXT, GLUT_KEY_PAGE_DOWN );
+ KEY( VK_HOME, GLUT_KEY_HOME );
+ KEY( VK_END, GLUT_KEY_END );
+ KEY( VK_LEFT, GLUT_KEY_LEFT );
+ KEY( VK_UP, GLUT_KEY_UP );
+ KEY( VK_RIGHT, GLUT_KEY_RIGHT );
+ KEY( VK_DOWN, GLUT_KEY_DOWN );
+ KEY( VK_INSERT, GLUT_KEY_INSERT );
+
+ case VK_DELETE:
+ /*
+ * The delete key should be treated as an ASCII keypress:
+ */
+ INVOKE_WCB( *window, KeyboardUp,
+ ( 127, window->State.MouseX, window->State.MouseY )
+ );
+ break;
+
+ default:
+ {
+#if !TARGET_HOST_WINCE
+ BYTE state[ 256 ];
+ WORD code[ 2 ];
+
+ GetKeyboardState( state );
+
+ if( ToAscii( wParam, 0, state, code, 0 ) == 1 )
+ wParam=code[ 0 ];
+
+ INVOKE_WCB( *window, KeyboardUp,
+ ( (char)wParam,
+ window->State.MouseX, window->State.MouseY )
+ );
+#endif /* !TARGET_HOST_WINCE */
+ }
+ }
+
+ if( keypress != -1 )
+ INVOKE_WCB( *window, SpecialUp,
+ ( keypress,
+ window->State.MouseX, window->State.MouseY )
+ );
+
+ fgState.Modifiers = 0xffffffff;
+ }
+ break;
+
+ case WM_SYSCHAR:
+ case WM_CHAR:
+ {
+ if( (fgState.KeyRepeat==GLUT_KEY_REPEAT_OFF ||
window->State.IgnoreKeyRepeat==GL_TRUE) && (HIWORD(lParam) & KF_REPEAT) )
+ break;
+
+ fgState.Modifiers = fgGetWin32Modifiers( );
+ INVOKE_WCB( *window, Keyboard,
+ ( (char)wParam,
+ window->State.MouseX, window->State.MouseY )
+ );
+ fgState.Modifiers = 0xffffffff;
+ }
+ break;
+
+ case WM_CAPTURECHANGED:
+ /* User has finished resizing the window, force a redraw */
+ INVOKE_WCB( *window, Display, ( ) );
+
+ /*lRet = DefWindowProc( hWnd, uMsg, wParam, lParam ); */
+ break;
+
+ /*
+ * Other messages that I have seen and which are not handled already
+ */
+ case WM_SETTEXT: /* 0x000c */
+ lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
+ /* Pass it on to "DefWindowProc" to set the window text */
+ break;
+
+ case WM_GETTEXT: /* 0x000d */
+ /* Ideally we would copy the title of the window into "lParam" */
+ /* strncpy ( (char *)lParam, "Window Title", wParam );
+ lRet = ( wParam > 12 ) ? 12 : wParam; */
+ /* the number of characters copied */
+ lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
+ break;
+
+ case WM_GETTEXTLENGTH: /* 0x000e */
+ /* Ideally we would get the length of the title of the window */
+ lRet = 12;
+ /* the number of characters in "Window Title\0" (see above) */
+ break;
+
+ case WM_ERASEBKGND: /* 0x0014 */
+ lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
+ break;
+
+#if !TARGET_HOST_WINCE
+ case WM_SYNCPAINT: /* 0x0088 */
+ /* Another window has moved, need to update this one */
+ window->State.Redisplay = GL_TRUE;
+ lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
+ /* Help screen says this message must be passed to "DefWindowProc" */
+ break;
+
+ case WM_NCPAINT: /* 0x0085 */
+ /* Need to update the border of this window */
+ lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
+ /* Pass it on to "DefWindowProc" to repaint a standard border */
+ break;
+
+ case WM_SYSCOMMAND : /* 0x0112 */
+ {
+ /*
+ * We have received a system command message. Try to act on it.
+ * The commands are passed in through the "wParam" parameter:
+ * The least significant digit seems to be which edge of the window
+ * is being used for a resize event:
+ * 4 3 5
+ * 1 2
+ * 7 6 8
+ * Congratulations and thanks to Richard Rauch for figuring this out..
+ */
+ switch ( wParam & 0xfff0 )
+ {
+ case SC_SIZE :
+ break ;
+
+ case SC_MOVE :
+ break ;
+
+ case SC_MINIMIZE :
+ /* User has clicked on the "-" to minimize the window */
+ /* Turn off the visibility */
+ window->State.Visible = GL_FALSE ;
+
+ break ;
+
+ case SC_MAXIMIZE :
+ break ;
+
+ case SC_NEXTWINDOW :
+ break ;
+
+ case SC_PREVWINDOW :
+ break ;
+
+ case SC_CLOSE :
+ /* Followed very closely by a WM_CLOSE message */
+ break ;
+
+ case SC_VSCROLL :
+ break ;
+
+ case SC_HSCROLL :
+ break ;
+
+ case SC_MOUSEMENU :
+ break ;
+
+ case SC_KEYMENU :
+ break ;
+
+ case SC_ARRANGE :
+ break ;
+
+ case SC_RESTORE :
+ break ;
+
+ case SC_TASKLIST :
+ break ;
+
+ case SC_SCREENSAVE :
+ break ;
+
+ case SC_HOTKEY :
+ break ;
+
+ default:
+#if _DEBUG
+ fgWarning( "Unknown wParam type 0x%x\n", wParam );
+#endif
+ break;
+ }
+ }
+#endif /* !TARGET_HOST_WINCE */
+
+ /* We need to pass the message on to the operating system as well */
+ lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
+ break;
+
+ default:
+ /*
+ * Handle unhandled messages
+ */
+ lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
+ break;
+ }
+
+ return lRet;
+}
+#endif
+
+/*** END OF FILE ***/
Index: external/trimesh/gluit/glui_img_checkbox_1.c
--- external/trimesh/gluit/glui_img_checkbox_1.c (revision 0)
+++ external/trimesh/gluit/glui_img_checkbox_1.c (revision 0)
@@ -0,0 +1,38 @@
+
+
+int glui_img_checkbox_1[] = { 13, 13, /* width, height */
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 128,128,128, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 255,255,255, 128,128,128, 0, 0, 0, 255,255,255, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 255,255,255, 192,192,192, 255,255,255, 128,128,128,
+ 0, 0, 0, 255,255,255, 255,255,255, 255,255,255, 0, 0, 0,
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 192,192,192, 255,255,255, 128,128,128, 0, 0, 0, 255,255,255,
+ 255,255,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 192,192,192, 255,255,255,
+ 128,128,128, 0, 0, 0, 255,255,255, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 255,255,255, 255,255,255,
+ 255,255,255, 192,192,192, 255,255,255, 128,128,128, 0, 0, 0,
+ 255,255,255, 0, 0, 0, 0, 0, 0, 255,255,255, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 255,255,255, 255,255,255, 192,192,192,
+ 255,255,255, 128,128,128, 0, 0, 0, 255,255,255, 0, 0, 0,
+ 255,255,255, 255,255,255, 255,255,255, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 255,255,255, 192,192,192, 255,255,255, 128,128,128,
+ 0, 0, 0, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 255,255,255, 0, 0, 0, 0, 0, 0, 255,255,255,
+ 192,192,192, 255,255,255, 128,128,128, 0, 0, 0, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 0, 0, 0, 255,255,255, 192,192,192, 255,255,255,
+ 128,128,128, 0, 0, 0, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 192,192,192, 255,255,255, 128,128,128, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192,192,192,
+ 255,255,255, 128,128,128, 128,128,128, 128,128,128, 128,128,128,
+ 128,128,128, 128,128,128, 128,128,128, 128,128,128, 128,128,128,
+ 128,128,128, 128,128,128, 128,128,128, 255,255,255,
+};
Index: external/trimesh/gluit/glui_panel.cc
--- external/trimesh/gluit/glui_panel.cc (revision 0)
+++ external/trimesh/gluit/glui_panel.cc (revision 0)
@@ -0,0 +1,178 @@
+/****************************************************************************
+
+ GLUI User Interface Toolkit
+ ---------------------------
+
+ glui_panel.cpp - GLUI_Panel control class
+
+
+ --------------------------------------------------
+
+ Copyright (c) 1998 Paul Rademacher
+
+ This program is freely distributable without licensing fees and is
+ provided without guarantee or warrantee expressed or implied. This
+ program is -not- in the public domain.
+
+*****************************************************************************/
+
+#include "glui.h"
+#include "glui_stdinc.h"
+
+/****************************** GLUI_Panel::draw() **********/
+
+void GLUI_Panel::draw( int x, int y )
+{
+ int top, orig;
+
+ if ( NOT can_draw() )
+ return;
+
+ orig = set_to_glut_window();
+
+ if ( int_val == GLUI_PANEL_RAISED ) {
+ top = 0;
+ glLineWidth( 1.0 );
+ glColor3f( 1.0, 1.0, 1.0 );
+ glBegin( GL_LINE_LOOP );
+ glVertex2i( 0, top ); glVertex2i( w, top );
+ glVertex2i( 0, top ); glVertex2i( 0, h );
+ glEnd();
+
+ glColor3f( .5, .5, .5 );
+ glBegin( GL_LINE_LOOP );
+ glVertex2i( w, top );
+ glVertex2i( w, h );
+ glVertex2i( 0, h );
+ glVertex2i( w, h );
+ glEnd();
+
+ /** ORIGINAL RAISED PANEL METHOD - A LITTLE TOO HIGH **
+ glLineWidth(1.0);
+ glBegin( GL_LINES );
+ glColor3f( 1.0, 1.0, 1.0 );
+ glVertex2i( 1, 1 ); glVertex2i( w-2, 1 );
+ glVertex2i( 1, 1 ); glVertex2i( 1, h-2 );
+
+ glColor3f( .5, .5, .5 );
+ glVertex2i( w-1, 1 ); glVertex2i( w-1, h-1 );
+ glVertex2i( 1, h-1 ); glVertex2i( w-1, h-1 );
+
+ glColor3f( 0.0, 0.0, 0.0 );
+ glVertex2i( 0, h ); glVertex2i( w, h );
+ glVertex2i( w, 0 ); glVertex2i( w, h );
+ glEnd();
+
+ -- Touch up the lines a bit (needed in some opengl implementations
+ glBegin( GL_POINTS );
+ glColor3f( .5, .5, .5 );
+ glVertex2i( w-1, h-1 );
+ glColor3f( 0.0, 0.0, 0.0 );
+ glVertex2i( w, h );
+ glEnd();
+ **/
+ }
+ else if ( int_val == GLUI_PANEL_EMBOSSED ) {
+ if ( name[0] == '\0' ) {
+ top = 0;
+ }
+ else {
+ top = GLUI_PANEL_EMBOSS_TOP;
+ }
+
+ glLineWidth( 1.0 );
+ glColor3f( 1.0, 1.0, 1.0 );
+ glBegin( GL_LINE_LOOP );
+ glVertex2i( 0, top ); glVertex2i( w, top );
+ glVertex2i( w, h ); glVertex2i( 0, h );
+
+ glVertex2i( 1, top+1 ); glVertex2i( w-1, top+1 );
+ glVertex2i( w-1, h-1 ); glVertex2i( 1, h-1 );
+ glEnd();
+
+ glColor3f( .5, .5, .5 );
+ glBegin( GL_LINE_LOOP );
+ glVertex2i( 0, top );
+ glVertex2i( w-1, top );
+ glVertex2i( w-1, h-1 );
+ glVertex2i( 0, h-1 );
+ glEnd();
+
+ /**** Only display text in embossed panel ****/
+ if ( name[0] != '\0' ) { /* Only draw non-null strings */
+ int left = 7, height=GLUI_PANEL_NAME_DROP+1;
+ int str_width;
+
+ str_width = string_width(name);
+
+ if ( glui )
+ glColor3ub(glui->bkgd_color.r,glui->bkgd_color.g,glui->bkgd_color.b);
+ glDisable( GL_CULL_FACE );
+ glBegin( GL_QUADS );
+ glVertex2i( left-3, 0 ); glVertex2i( left+str_width+3, 0 );
+ glVertex2i( left+str_width+3, height ); glVertex2i( left-3, height );
+ glEnd();
+
+ draw_name( left, GLUI_PANEL_NAME_DROP );
+ }
+ }
+
+ glLineWidth( 1.0 );
+
+ restore_window(orig);
+}
+
+
+/****************************** GLUI_Panel::set_name() **********/
+
+void GLUI_Panel::set_name( char *new_name )
+{
+ strncpy(name,new_name,sizeof(GLUI_String));
+
+ update_size();
+
+ if ( glui )
+ glui->refresh();
+}
+
+
+/****************************** GLUI_Panel::set_type() **********/
+
+void GLUI_Panel::set_type( int new_type )
+{
+ int old_window;
+
+ if ( new_type != int_val ) {
+ int_val = new_type;
+
+ /* translate_and_draw_front(); */
+ update_size();
+
+ old_window = set_to_glut_window();
+ glutPostRedisplay( );
+ restore_window( old_window );
+ }
+}
+
+
+/************************************** GLUI_Panel::update_size() **********/
+
+void GLUI_Panel::update_size( void )
+{
+ int text_size;
+
+ if ( NOT glui )
+ return;
+
+ text_size = string_width(name);
+
+ if ( w < text_size + 16 )
+ w = text_size + 16 ;
+
+ if ( name[0] != '\0' AND int_val == GLUI_PANEL_EMBOSSED ) {
+ this->y_off_top = GLUI_YOFF + 8;
+ }
+ else {
+ this->y_off_top = GLUI_YOFF;
+ }
+}
Index: external/trimesh/gluit/glui_rotation.cc
--- external/trimesh/gluit/glui_rotation.cc (revision 0)
+++ external/trimesh/gluit/glui_rotation.cc (revision 0)
@@ -0,0 +1,389 @@
+/****************************************************************************
+
+ GLUI User Interface Toolkit
+ ---------------------------
+
+ glui_rotation - GLUI_Rotation control class
+
+
+ --------------------------------------------------
+
+ Copyright (c) 1998 Paul Rademacher
+
+ This program is freely distributable without licensing fees and is
+ provided without guarantee or warrantee expressed or implied. This
+ program is -not- in the public domain.
+
+*****************************************************************************/
+
+#include "glui.h"
+#include "glui_arcball.h"
+#include "glui_algebra3.h"
+
+/*************************** GLUI_Rotation::iaction_mouse_down_handler() ***/
+
+int GLUI_Rotation::iaction_mouse_down_handler( int local_x, int local_y )
+{
+ copy_float_array_to_ball();
+
+ init_ball();
+
+ local_y = (int) floor(2.0 * ball->center[1] - local_y);
+
+ ball->mouse_down( local_x, local_y );
+
+ /* printf( "%d %d - %f %f\n", local_x, local_y, ball->center[0],
ball->center[1] ); */
+
+ copy_ball_to_float_array();
+
+ spinning = false;
+
+ return false;
+}
+
+
+/*********************** GLUI_Rotation::iaction_mouse_up_handler() **********/
+
+int GLUI_Rotation::iaction_mouse_up_handler( int local_x, int local_y,
+ int inside )
+{
+ copy_float_array_to_ball();
+
+ ball->mouse_up();
+
+ return false;
+}
+
+
+/******************* GLUI_Rotation::iaction_mouse_held_down_handler() ******/
+
+int GLUI_Rotation::iaction_mouse_held_down_handler( int local_x, int local_y,
+ int inside)
+{
+ if ( NOT glui )
+ return 0;
+
+ copy_float_array_to_ball();
+
+ local_y = (int) floor(2.0 * ball->center[1] - local_y);
+
+ /* printf( "%d %d\n", local_x, local_y ); */
+
+ ball->mouse_motion( local_x, local_y, 0,
+ (glui->curr_modifiers & GLUT_ACTIVE_ALT) != 0,
+ (glui->curr_modifiers & GLUT_ACTIVE_CTRL) != 0 );
+
+ copy_ball_to_float_array();
+
+ if ( can_spin )
+ spinning = true;
+
+ return false;
+}
+
+
+/******************** GLUI_Rotation::iaction_draw_active_area_persp() **************/
+
+void GLUI_Rotation::iaction_draw_active_area_persp( void )
+{
+ if ( NOT can_draw() )
+ return;
+
+ copy_float_array_to_ball();
+
+ setup_texture();
+ setup_lights();
+
+ glEnable(GL_CULL_FACE );
+
+ glMatrixMode( GL_MODELVIEW );
+ glPushMatrix();
+
+ mat4 tmp_rot = *ball->rot_ptr;
+ glMultMatrixf( (float*) &tmp_rot[0][0] );
+
+ /*** Draw the checkered box ***/
+ /*glDisable( GL_TEXTURE_2D ); */
+ draw_ball( 1.96 );
+
+ glPopMatrix();
+
+ glDisable( GL_TEXTURE_2D );
+ glDisable( GL_LIGHTING );
+ glDisable( GL_CULL_FACE );
+}
+
+
+/******************** GLUI_Rotation::iaction_draw_active_area_ortho() **********/
+
+void GLUI_Rotation::iaction_draw_active_area_ortho( void )
+{
+ if ( NOT can_draw() )
+ return;
+
+ /********* Draw emboss circles around arcball control *********/
+ int k;
+ float radius;
+ radius = (float)(h-22)/2.0; /*MIN((float)w/2.0, (float)h/2.0); */
+ glLineWidth( 1.0 );
+ glBegin( GL_LINE_LOOP);
+ for( k=0; k<60; k++ ) {
+ float phi = 2*M_PI*(float)k/60.0;
+ vec2 p( cos(phi) * (2.0 + radius), sin(phi) * (2.0 + radius));
+ if ( p[1] < -p[0] ) glColor3ub( 128,128,128 );
+ else glColor3ub( 255,255,255 );
+ glVertex2fv((float*)&p[0]);
+ }
+ glEnd();
+
+ glBegin( GL_LINE_LOOP);
+ for( k=0; k<60; k++ ) {
+ float phi = 2*M_PI*(float)k/60.0;
+ vec2 p( cos(phi) * (1.0 + radius), sin(phi) * (1.0 + radius));
+ if ( enabled ) {
+ if ( p[1] < -p[0] ) glColor3ub( 0,0,0);
+ else glColor3ub( 192,192,192);
+ }
+ else
+ {
+ if ( p[1] < -p[0] ) glColor3ub( 180,180,180);
+ else glColor3ub( 192,192,192);
+ }
+ glVertex2fv((float*)&p[0]);
+ }
+ glEnd();
+}
+
+
+/******************************** GLUI_Rotation::iaction_dump() **********/
+
+void GLUI_Rotation::iaction_dump( FILE *output )
+{
+}
+
+
+/******************** GLUI_Rotation::iaction_special_handler() **********/
+
+int GLUI_Rotation::iaction_special_handler( int key,int modifiers )
+{
+
+ return false;
+}
+
+/********************************** GLUI_Rotation::init_ball() **********/
+
+void GLUI_Rotation::init_ball( void )
+{
+ /*printf( "%f %f %f", float( MIN(w/2,h/2)), (float) w/2, (float) h/2 );
*/
+
+ ball->set_params( vec2( (float)(w/2), (float)((h-18)/2)),
+ (float) 2.0*(h-18) );
+ /*ball->set_damping( .05 ); */
+ /*float( MIN(w/2,h/2))*2.0 ); */
+ /* ball->reset_mouse(); */
+}
+
+
+/****************************** GLUI_Rotation::setup_texture() *********/
+
+void GLUI_Rotation::setup_texture( void )
+{
+ int i, j;
+ int dark, light; /*** Dark and light colors for ball checkerboard ***/
+
+#define CHECKBOARD_SIZE 64
+ unsigned char texture_image[CHECKBOARD_SIZE] [CHECKBOARD_SIZE] [3];
+ unsigned char c;
+ for( i=0; i<CHECKBOARD_SIZE; i++ ) {
+ for( j=0; j<CHECKBOARD_SIZE; j++ ) {
+ if ( enabled ) {
+ dark = 110;
+ light = 220;
+ }
+ else {
+ dark = glui->bkgd_color.r - 30;
+ light = glui->bkgd_color.r;
+ }
+
+ c = ((((i&0x8)==0) ^ ((j&0x8))==0)) * light;
+ if ( c == 0 )
+ c = dark;
+ texture_image[i][j][0] = c;
+ texture_image[i][j][1] = c;
+ texture_image[i][j][2] = c;
+ }
+ }
+
+ glColor3f( 1.0, 1.0, 1.0 );
+ glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
+ glEnable( GL_TEXTURE_2D);
+ glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, CHECKBOARD_SIZE,
+ CHECKBOARD_SIZE, 0, GL_RGB, GL_UNSIGNED_BYTE,
+ texture_image );
+
+}
+
+
+/****************************** GLUI_Rotation::setup_lights() ***********/
+
+void GLUI_Rotation::setup_lights( void )
+{
+ glEnable( GL_LIGHTING );
+ /* if ( enabled )
+ glEnable( GL_LIGHTING );
+ else
+ glDisable( GL_LIGHTING );*/
+ glEnable(GL_LIGHT0);
+ glColorMaterial(GL_AMBIENT_AND_DIFFUSE, GL_FRONT_AND_BACK );
+ glEnable(GL_COLOR_MATERIAL);
+ GLfloat light0_ambient[] = {0.2f, 0.2f, 0.2f, 1.0f};
+ GLfloat light0_diffuse[] = {1.f, 1.f, 1.0f, 1.0f};
+ GLfloat light0_position[] = {-1.f, 1.f, 1.0f, 0.0f};
+ glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient);
+ glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
+ glLightfv(GL_LIGHT0, GL_POSITION, light0_position);
+}
+
+
+/****************************** GLUI_Rotation::draw_ball() **************/
+
+void GLUI_Rotation::draw_ball( float radius )
+{
+ if ( NOT can_draw() )
+ return;
+
+ if (quadObj == NULL) quadObj = gluNewQuadric();
+ if (quadObj) {
+ gluQuadricDrawStyle(quadObj, GLU_FILL);
+ gluQuadricNormals(quadObj, GLU_SMOOTH);
+ gluQuadricTexture(quadObj, true );
+ gluSphere(quadObj, radius, 16, 16);
+ }
+}
+
+
+/****************************** GLUI_Rotation::reset() **********/
+
+void GLUI_Rotation::reset( void )
+{
+ ball->init(); /** reset quaternion, etc. **/
+ ball->set_params( vec2( (float)(w/2), (float)((h-18)/2)),
+ (float) 2.0*(h-18) );
+
+ set_spin( this->damping );
+
+ copy_ball_to_float_array();
+
+ translate_and_draw_front();
+
+ output_live(true); /*** Output live and draw main grx window ***/
+}
+
+
+/****************************** GLUI_Rotation::needs_idle() *********/
+
+int GLUI_Rotation::needs_idle( void )
+{
+ return can_spin;
+}
+
+
+/****************************** GLUI_Rotation::idle() ***************/
+
+void GLUI_Rotation::idle( void )
+{
+ spinning = ball->is_spinning;
+
+ if ( can_spin == true AND spinning == true ) {
+ copy_float_array_to_ball();
+ ball->idle();
+
+ *ball->rot_ptr = *ball->rot_ptr * ball->rot_increment;
+
+ mat4 tmp_rot;
+ tmp_rot = *ball->rot_ptr;
+
+ copy_ball_to_float_array();
+
+ draw_active_area_only = true;
+ translate_and_draw_front();
+ draw_active_area_only = false;
+
+ output_live(true); /** output live and update gfx **/
+ }
+ else {
+ }
+}
+
+
+/********************** GLUI_Rotation::copy_float_array_to_ball() *********/
+
+void GLUI_Rotation::copy_float_array_to_ball( void )
+{
+ int i;
+ float *fp_src, *fp_dst;
+
+ fp_src = &float_array_val[0];
+ fp_dst = &((*ball->rot_ptr)[0][0]);
+
+ for( i=0; i<16; i++ ) {
+ *fp_dst = *fp_src;
+
+ fp_src++;
+ fp_dst++;
+ }
+}
+
+
+/********************** GLUI_Rotation::copy_ball_to_float_array() *********/
+
+void GLUI_Rotation::copy_ball_to_float_array( void )
+{
+ mat4 tmp_rot;
+ tmp_rot = *ball->rot_ptr;
+
+ set_float_array_val( (float*) &tmp_rot[0][0] );
+}
+
+
+/************************ GLUI_Rotation::set_spin() **********************/
+
+void GLUI_Rotation::set_spin( float damp_factor )
+{
+ if ( damp_factor == 0.0 )
+ can_spin = false;
+ else
+ can_spin = true;
+
+ ball->set_damping( 1.0 - damp_factor );
+
+ this->damping = damp_factor;
+}
+
+
+/************** GLUI_Rotation::GLUI_Rotation() ********************/
+
+
+GLUI_Rotation::GLUI_Rotation( void )
+{
+ sprintf( name, "Rotation: %p", this );
+ type = GLUI_CONTROL_ROTATION;
+ w = GLUI_ROTATION_WIDTH;
+ h = GLUI_ROTATION_HEIGHT;
+ can_activate = true;
+ live_type = GLUI_LIVE_FLOAT_ARRAY;
+ float_array_size = 16;
+ quadObj = NULL;
+ alignment = GLUI_ALIGN_CENTER;
+ can_spin = false;
+ spinning = false;
+ damping = 0.0;
+ ball = new Arcball;
+
+ reset();
+}
Index: external/trimesh/gluit/glui_arcball.h
--- external/trimesh/gluit/glui_arcball.h (revision 0)
+++ external/trimesh/gluit/glui_arcball.h (revision 0)
@@ -0,0 +1,80 @@
+/**********************************************************************
+
+ Arcball.h
+
+ A C++ class that implements the Arcball, as described by Ken
+ Shoemake in Graphics Gems IV.
+ This class takes as input mouse events (mouse down, mouse drag,
+ mouse up), and creates the appropriate quaternions and 4x4 matrices
+ to represent the rotation given by the mouse.
+
+ This class is used as follows:
+ - initialize [either in the constructor or with set_params()], the
+ center position (x,y) of the arcball on the screen, and the radius
+ - on mouse down, call mouse_down(x,y) with the mouse position
+ - as the mouse is dragged, repeatedly call mouse_motion() with the
+ current x and y positions. One can optionally pass in the current
+ state of the SHIFT, ALT, and CONTROL keys (passing zero if keys
+ are not pressed, non-zero otherwise), which constrains
+ the rotation to certain axes (X for CONTROL, Y for ALT).
+ - when the mouse button is released, call mouse_up()
+
+ Axis constraints can also be explicitly set with the
+ set_constraints() function.
+
+ The current rotation is stored in the 4x4 float matrix 'rot'.
+ It is also stored in the quaternion 'q_now'.
+
+ ------------------------------------------------------------------
+
+ Feb 25, 1998 - Paul Rademacher (rademach(a)cs.unc.edu)
+
+**********************************************************************/
+
+
+#ifndef _ARCBALL_H_
+#define _ARCBALL_H_
+
+
+#include "glui_stdinc.h"
+#include "glui_algebra3.h"
+#include "glui_quaternion.h"
+#include <GL/glut.h>
+
+class Arcball {
+public:
+ Bool constraint_x, constraint_y;
+ vec2 center;
+ float radius, damp_factor;
+ int zero_increment;
+
+ vec3 constrain_vector( vec3 vector, vec3 axis );
+ vec3 mouse_to_sphere( vec2 p );
+
+ //public:
+ int is_mouse_down; /* true for down, false for up */
+ int is_spinning;
+ quat q_now, q_down, q_drag, q_increment;
+ vec2 down_pt;
+ mat4 rot, rot_increment;
+ mat4 *rot_ptr;
+
+ void set_damping( float d );
+ void idle( void );
+ void mouse_down( int x, int y );
+ void mouse_up( void );
+ void mouse_motion( int x, int y, int shift, int ctrl, int alt );
+ void mouse_motion( int x, int y );
+ void set_constraints( Bool constrain_x, Bool constrain_y );
+ void set_params( vec2 center, float radius );
+ void reset_mouse( void );
+ void init( void );
+
+ Arcball( void );
+ Arcball( mat4 *mtx );
+ Arcball( vec2 center, float radius );
+};
+
+
+#endif
+
Index: external/trimesh/gluit/glui_img_radiobutton_1.c
--- external/trimesh/gluit/glui_img_radiobutton_1.c (revision 0)
+++ external/trimesh/gluit/glui_img_radiobutton_1.c (revision 0)
@@ -0,0 +1,44 @@
+
+
+int glui_img_radiobutton_1[] = { 14, 14, /* width, height */
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 255,255,255, 255,255,255, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 255,255,255, 255,255,255, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 128,128,128,
+ 192,192,192, 192,192,192, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 192,192,192, 192,192,192, 255,255,255, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 128,128,128, 0, 0, 0,
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 192,192,192, 255,255,255, 192,192,192, 192,192,192,
+ 192,192,192, 128,128,128, 0, 0, 0, 255,255,255, 255,255,255,
+ 255,255,255, 0, 0, 0, 0, 0, 0, 255,255,255, 255,255,255,
+ 255,255,255, 192,192,192, 255,255,255, 192,192,192, 192,192,192,
+ 128,128,128, 0, 0, 0, 255,255,255, 255,255,255, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 255,255,255, 255,255,255,
+ 192,192,192, 255,255,255, 192,192,192, 192,192,192, 128,128,128,
+ 0, 0, 0, 255,255,255, 255,255,255, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 255,255,255, 255,255,255, 192,192,192,
+ 255,255,255, 192,192,192, 192,192,192, 128,128,128, 0, 0, 0,
+ 255,255,255, 255,255,255, 255,255,255, 0, 0, 0, 0, 0, 0,
+ 255,255,255, 255,255,255, 255,255,255, 192,192,192, 255,255,255,
+ 192,192,192, 192,192,192, 192,192,192, 128,128,128, 0, 0, 0,
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 192,192,192, 255,255,255, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 128,128,128, 0, 0, 0, 0, 0, 0,
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 0, 0, 0,
+ 0, 0, 0, 255,255,255, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 128,128,128, 128,128,128, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 128,128,128, 128,128,128,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 128,128,128, 128,128,128,
+ 128,128,128, 128,128,128, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192,
+};
Index: external/trimesh/gluit/COPYING.glui
--- external/trimesh/gluit/COPYING.glui (revision 0)
+++ external/trimesh/gluit/COPYING.glui (revision 0)
@@ -0,0 +1,504 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+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 and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, 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 library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete 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 distribute a copy of this License along with the
+Library.
+
+ 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 Library or any portion
+of it, thus forming a work based on the Library, 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) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+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 Library, 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 Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you 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.
+
+ If distribution of 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 satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be 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.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library 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.
+
+ 9. 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 Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+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 with
+this License.
+
+ 11. 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 Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library 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 Library.
+
+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.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library 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.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser 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 Library
+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 Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+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
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "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
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. 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 LIBRARY 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
+LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. 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 library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library 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 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser 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
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
Index: external/trimesh/gluit/freeglut_misc.c
--- external/trimesh/gluit/freeglut_misc.c (revision 0)
+++ external/trimesh/gluit/freeglut_misc.c (revision 0)
@@ -0,0 +1,179 @@
+/*
+ * freeglut_misc.c
+ *
+ * Functions that didn't fit anywhere else...
+ *
+ * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
+ * Written by Pawel W. Olszta, <olszta(a)sourceforge.net>
+ * Creation date: Thu Dec 9 1999
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <GL/freeglut.h>
+#include "freeglut_internal.h"
+
+/*
+ * TODO BEFORE THE STABLE RELEASE:
+ *
+ * glutSetColor() --
+ * glutGetColor() --
+ * glutCopyColormap() --
+ * glutSetKeyRepeat() -- this is evil and should be removed from API
+ */
+
+/* -- INTERFACE FUNCTIONS -------------------------------------------------- */
+
+/*
+ * This functions checks if an OpenGL extension is supported or not
+ *
+ * XXX Wouldn't this be simpler and clearer if we used strtok()?
+ */
+int FGAPIENTRY glutExtensionSupported( const char* extension )
+{
+ const char *extensions, *start;
+ const int len = strlen( extension );
+
+ /*
+ * Make sure there is a current window, and thus a current context available
+ */
+ freeglut_assert_ready;
+ freeglut_return_val_if_fail( fgStructure.Window != NULL, 0 );
+
+ if (strchr(extension, ' '))
+ return 0;
+ start = extensions = (const char *) glGetString(GL_EXTENSIONS);
+
+ /* XXX consider printing a warning to stderr that there's no current
+ * rendering context.
+ */
+ freeglut_return_val_if_fail( extensions != NULL, 0 );
+
+ while (1) {
+ const char *p = strstr(extensions, extension);
+ if (!p)
+ return 0; /* not found */
+ /* check that the match isn't a super string */
+ if ((p == start || p[-1] == ' ') && (p[len] == ' ' || p[len]
== 0))
+ return 1;
+ /* skip the false match and continue */
+ extensions = p + len;
+ }
+
+ return 0 ;
+}
+
+/*
+ * This function reports all the OpenGL errors that happened till now
+ */
+void FGAPIENTRY glutReportErrors( void )
+{
+ GLenum error;
+ while( ( error = glGetError() ) != GL_NO_ERROR )
+ fgWarning( "GL error: %s", gluErrorString( error ) );
+}
+
+/*
+ * Control the auto-repeat of keystrokes to the current window
+ */
+void FGAPIENTRY glutIgnoreKeyRepeat( int ignore )
+{
+ freeglut_assert_ready;
+ freeglut_assert_window;
+
+ fgStructure.Window->State.IgnoreKeyRepeat = ignore ? GL_TRUE : GL_FALSE;
+}
+
+/*
+ * Set global auto-repeat of keystrokes
+ *
+ * RepeatMode should be either:
+ * GLUT_KEY_REPEAT_OFF
+ * GLUT_KEY_REPEAT_ON
+ * GLUT_KEY_REPEAT_DEFAULT
+ */
+void FGAPIENTRY glutSetKeyRepeat( int repeatMode )
+{
+ freeglut_assert_ready;
+
+ switch( repeatMode )
+ {
+ case GLUT_KEY_REPEAT_OFF:
+ case GLUT_KEY_REPEAT_ON:
+ fgState.KeyRepeat = repeatMode;
+ break;
+
+ case GLUT_KEY_REPEAT_DEFAULT:
+ fgState.KeyRepeat = GLUT_KEY_REPEAT_ON;
+ break;
+
+ default:
+ fgError ("Invalid glutSetKeyRepeat mode: %d", repeatMode);
+ break;
+ }
+}
+
+/*
+ * Forces the joystick callback to be executed
+ */
+void FGAPIENTRY glutForceJoystickFunc( void )
+{
+#if !TARGET_HOST_WINCE
+ freeglut_assert_ready;
+ freeglut_return_if_fail( fgStructure.Window != NULL );
+ freeglut_return_if_fail( FETCH_WCB( *( fgStructure.Window ), Joystick ) );
+ fgJoystickPollWindow( fgStructure.Window );
+#endif /* !TARGET_HOST_WINCE */
+}
+
+/*
+ *
+ */
+void FGAPIENTRY glutSetColor( int nColor, GLfloat red, GLfloat green, GLfloat blue )
+{
+ /*
+ *
+ */
+}
+
+/*
+ *
+ */
+GLfloat FGAPIENTRY glutGetColor( int color, int component )
+{
+ /*
+ *
+ */
+ return( 0.0f );
+}
+
+/*
+ *
+ */
+void FGAPIENTRY glutCopyColormap( int window )
+{
+ /*
+ *
+ */
+}
+
+/*** END OF FILE ***/
Index: external/trimesh/gluit/freeglut_joystick.c
--- external/trimesh/gluit/freeglut_joystick.c (revision 0)
+++ external/trimesh/gluit/freeglut_joystick.c (revision 0)
@@ -0,0 +1,1805 @@
+/*
+ * freeglut_joystick.c
+ *
+ * Joystick handling code
+ *
+ * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
+ * Written by Steve Baker, <sjbaker1(a)airmail.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * FreeBSD port by Stephen Montgomery-Smith <stephen(a)math.missouri.edu>
+ *
+ * Redone by John Fay 2/4/04 with another look from the PLIB "js" library.
+ * Many thanks for Steve Baker for permission to pull from that library.
+ */
+
+#if defined( __FreeBSD__ ) || defined( __NetBSD__ )
+# include <sys/param.h>
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <GL/freeglut.h>
+#include "freeglut_internal.h"
+
+/*
+ * Initial defines from "js.h" starting around line 33 with the existing
"freeglut_joystick.c"
+ * interspersed
+ */
+#define _JS_MAX_BUTTONS 32
+
+
+#if TARGET_HOST_MACINTOSH
+# define _JS_MAX_AXES 9
+# include <InputSprocket.h>
+#endif
+
+#if TARGET_HOST_MAC_OSX
+# define _JS_MAX_AXES 16
+# include <mach/mach.h>
+# include <IOKit/IOkitLib.h>
+# include <IOKit/hid/IOHIDLib.h>
+#endif
+
+#if TARGET_HOST_WIN32
+# define _JS_MAX_AXES 8
+# include <windows.h>
+# include <mmsystem.h>
+# include <string.h>
+# include <regstr.h>
+
+#endif
+
+#if TARGET_HOST_UNIX_X11
+# define _JS_MAX_AXES 16
+# if defined(__FreeBSD__) || defined(__NetBSD__)
+/*
+ * XXX The below hack is done until freeglut's autoconf is updated.
+ */
+# define HAVE_USB_JS 1
+
+# include <sys/ioctl.h>
+# if defined(__FreeBSD__) && __FreeBSD_version >= 500000
+# include <sys/joystick.h>
+# else
+/*
+ * XXX NetBSD/amd64 systems may find that they have to steal the
+ * XXX /usr/include/machine/joystick.h from a NetBSD/i386 system.
+ * XXX I cannot comment whether that works for the interface, but
+ * XXX it lets you compile...(^& I do not think that we can do away
+ * XXX with this header.
+ */
+# include <machine/joystick.h> /* For analog joysticks */
+# endif
+# define JS_DATA_TYPE joystick
+# define JS_RETURN (sizeof(struct JS_DATA_TYPE))
+# endif
+
+# include <unistd.h>
+# include <fcntl.h>
+# include <errno.h>
+
+# if defined(__linux__)
+# include <sys/ioctl.h>
+# include <linux/joystick.h>
+
+/* check the joystick driver version */
+# if defined(JS_VERSION) && JS_VERSION >= 0x010000
+# define JS_NEW
+# endif
+# else /* Not BSD or Linux */
+# ifndef JS_RETURN
+
+ /*
+ * We'll put these values in and that should
+ * allow the code to at least compile when there is
+ * no support. The JS open routine should error out
+ * and shut off all the code downstream anyway and if
+ * the application doesn't use a joystick we'll be fine.
+ */
+
+ struct JS_DATA_TYPE
+ {
+ int buttons;
+ int x;
+ int y;
+ };
+
+# define JS_RETURN (sizeof(struct JS_DATA_TYPE))
+# endif
+# endif
+#endif
+
+#define JS_TRUE 1
+#define JS_FALSE 0
+
+/*
+ * BSD defines from "jsBSD.cxx" around lines 42-270
+ */
+
+#if defined(__NetBSD__) || defined(__FreeBSD__)
+
+# ifdef HAVE_USB_JS
+# if defined(__NetBSD__)
+/*
+ * XXX The below hack is done until freeglut's autoconf is updated.
+ */
+# define HAVE_USBHID_H 1
+# ifdef HAVE_USBHID_H
+# include <usbhid.h>
+# else
+# include <usb.h>
+# endif
+# elif defined(__FreeBSD__)
+# if __FreeBSD_version < 500000
+# include <libusbhid.h>
+# else
+/*
+ * XXX The below hack is done until freeglut's autoconf is updated.
+ */
+# define HAVE_USBHID_H 1
+# include <usbhid.h>
+# endif
+# endif
+# include <dev/usb/usb.h>
+# include <dev/usb/usbhid.h>
+
+/* Compatibility with older usb.h revisions */
+# if !defined(USB_MAX_DEVNAMES) && defined(MAXDEVNAMES)
+# define USB_MAX_DEVNAMES MAXDEVNAMES
+# endif
+# endif
+
+static int hatmap_x[9] = { 0, 0, 1, 1, 1, 0, -1, -1, -1 };
+static int hatmap_y[9] = { 0, 1, 1, 0, -1, -1, -1, 0, 1 };
+struct os_specific_s {
+ char fname [128 ];
+ int fd;
+ int is_analog;
+ /* The following structure members are specific to analog joysticks */
+ struct joystick ajs;
+# ifdef HAVE_USB_JS
+ /* The following structure members are specific to USB joysticks */
+ struct hid_item *hids;
+ int hid_dlen;
+ int hid_offset;
+ char *hid_data_buf;
+ int axes_usage [ _JS_MAX_AXES ];
+# endif
+ /* We keep button and axes state ourselves, as they might not be updated
+ * on every read of a USB device
+ */
+ int cache_buttons;
+ float cache_axes [ _JS_MAX_AXES ];
+};
+
+/* Idents lower than USB_IDENT_OFFSET are for analog joysticks. */
+# define USB_IDENT_OFFSET 2
+
+# define USBDEV "/dev/usb"
+# define UHIDDEV "/dev/uhid"
+# define AJSDEV "/dev/joy"
+
+# ifdef HAVE_USB_JS
+/*
+ * fghJoystickFindUSBdev (and its helper, fghJoystickWalkUSBdev) try to locate
+ * the full name of a USB device. If /dev/usbN isn't readable, we punt and
+ * return the uhidN device name. We warn the user of this situation once.
+ */
+static char *fghJoystickWalkUSBdev(int f, char *dev, char *out, int outlen)
+{
+ struct usb_device_info di;
+ int i, a;
+ char *cp;
+
+ for (a = 1; a < USB_MAX_DEVICES; a++) {
+ di.udi_addr = a;
+ if (ioctl(f, USB_DEVICEINFO, &di) != 0)
+ return NULL;
+ for (i = 0; i < USB_MAX_DEVNAMES; i++)
+ if (di.udi_devnames[i][0] &&
+ strcmp(di.udi_devnames[i], dev) == 0) {
+ cp = calloc( 1, strlen(di.udi_vendor) + strlen(di.udi_product) + 2);
+ strcpy(cp, di.udi_vendor);
+ strcat(cp, " ");
+ strcat(cp, di.udi_product);
+ strncpy(out, cp, outlen - 1);
+ out[outlen - 1] = 0;
+ free( cp );
+ return out;
+ }
+ }
+ return NULL;
+}
+
+static int fghJoystickFindUSBdev(char *name, char *out, int outlen)
+{
+ int i, f;
+ char buf[50];
+ char *cp;
+ static int protection_warned = 0;
+
+ for (i = 0; i < 16; i++) {
+ sprintf(buf, "%s%d", USBDEV, i);
+ f = open(buf, O_RDONLY);
+ if (f >= 0) {
+ cp = fghJoystickWalkUSBdev(f, name, out, outlen);
+ close(f);
+ if (cp)
+ return 1;
+ } else if (errno == EACCES) {
+ if (!protection_warned) {
+ fprintf(stderr, "Can't open %s for read!\n",
+ buf);
+ protection_warned = 1;
+ }
+ }
+ }
+ return 0;
+}
+
+static int fghJoystickInitializeHID(struct os_specific_s *os,
+ int *num_axes, int *num_buttons)
+{
+ int size, is_joystick;
+# ifdef HAVE_USBHID_H
+ int report_id = 0;
+# endif
+ struct hid_data *d;
+ struct hid_item h;
+ report_desc_t rd;
+
+ if ( ( rd = hid_get_report_desc( os->fd ) ) == 0 )
+ {
+ fprintf( stderr, "error: %s: %s", os->fname, strerror( errno ) );
+ return FALSE;
+ }
+
+ os->hids = NULL;
+
+# ifdef HAVE_USBHID_H
+ if( ioctl( os->fd, USB_GET_REPORT_ID, &report_id ) < 0)
+ {
+ /*** XXX {report_id} may not be the right variable? ***/
+ fprintf( stderr, "error: %s%d: %s",
+ UHIDDEV, report_id, strerror( errno ) );
+ return FALSE;
+ }
+
+ size = hid_report_size( rd, hid_input, report_id );
+# else
+ size = hid_report_size( rd, 0, hid_input );
+# endif
+ os->hid_data_buf = calloc( 1, size );
+ os->hid_dlen = size;
+
+ is_joystick = 0;
+# ifdef HAVE_USBHID_H
+ d = hid_start_parse( rd, 1 << hid_input, report_id );
+# else
+ d = hid_start_parse( rd, 1 << hid_input );
+# endif
+ while( hid_get_item( d, &h ) )
+ {
+ int usage, page, interesting_hid;
+
+ page = HID_PAGE( h.usage );
+ usage = HID_USAGE( h.usage );
+
+ /* This test is somewhat too simplistic, but this is how MicroSoft
+ * does, so I guess it works for all joysticks/game pads. */
+ is_joystick = is_joystick ||
+ ( h.kind == hid_collection &&
+ page == HUP_GENERIC_DESKTOP &&
+ ( usage == HUG_JOYSTICK || usage == HUG_GAME_PAD ) );
+
+ if( h.kind != hid_input )
+ continue;
+
+ if( !is_joystick )
+ continue;
+
+ interesting_hid = TRUE;
+ if( page == HUP_GENERIC_DESKTOP )
+ {
+ switch( usage )
+ {
+ case HUG_X:
+ case HUG_RX:
+ case HUG_Y:
+ case HUG_RY:
+ case HUG_Z:
+ case HUG_RZ:
+ case HUG_SLIDER:
+ if( *num_axes < _JS_MAX_AXES )
+ {
+ os->axes_usage[ *num_axes ] = usage;
+ ( *num_axes )++;
+ }
+ break;
+ case HUG_HAT_SWITCH:
+ /* Allocate two axes for a hat */
+ if( *num_axes + 1 < _JS_MAX_AXES )
+ {
+ os->axes_usage[ *num_axes ] = usage;
+ (*num_axes)++;
+ os->axes_usage[ *num_axes ] = usage;
+ (*num_axes)++;
+ }
+ break;
+ default:
+ interesting_hid = FALSE;
+ break;
+ }
+ }
+ else if( page == HUP_BUTTON )
+ {
+ interesting_hid = ( usage > 0 ) &&
+ ( usage <= _JS_MAX_BUTTONS );
+
+ if( interesting_hid && usage - 1 > *num_buttons )
+ *num_buttons = usage - 1;
+ }
+
+ if( interesting_hid )
+ {
+ h.next = os->hids;
+ os->hids = calloc( 1, sizeof ( struct hid_item ) );
+ *os->hids = h;
+ }
+ }
+ hid_end_parse( d );
+
+ return os->hids != NULL;
+}
+# endif
+#endif
+
+/*
+ * Definition of "SFG_Joystick" structure -- based on JS's
"jsJoystick" object class.
+ * See "js.h" lines 80-178.
+ */
+typedef struct tagSFG_Joystick SFG_Joystick;
+struct tagSFG_Joystick
+{
+#if TARGET_HOST_MACINTOSH
+#define ISP_NUM_AXIS 9
+#define ISP_NUM_NEEDS 41
+ ISpElementReference isp_elem [ ISP_NUM_NEEDS ];
+ ISpNeed isp_needs [ ISP_NUM_NEEDS ];
+#endif
+
+#if TARGET_HOST_MAC_OSX
+ IOHIDDeviceInterface ** hidDev;
+ IOHIDElementCookie buttonCookies[41];
+ IOHIDElementCookie axisCookies[_JS_MAX_AXES];
+ long minReport[_JS_MAX_AXES],
+ maxReport[_JS_MAX_AXES];
+#endif
+
+#if TARGET_HOST_WIN32
+ JOYCAPS jsCaps;
+ JOYINFOEX js;
+ UINT js_id;
+#endif
+
+
+#if TARGET_HOST_UNIX_X11
+# if defined(__FreeBSD__) || defined(__NetBSD__)
+ struct os_specific_s *os;
+# endif
+
+# ifdef JS_NEW
+ struct js_event js;
+ int tmp_buttons;
+ float tmp_axes [ _JS_MAX_AXES ];
+# else
+ struct JS_DATA_TYPE js;
+# endif
+
+ char fname [ 128 ];
+ int fd;
+#endif
+
+ int id;
+ GLboolean error;
+ char name [ 128 ];
+ int num_axes;
+ int num_buttons;
+
+ float dead_band[ _JS_MAX_AXES ];
+ float saturate [ _JS_MAX_AXES ];
+ float center [ _JS_MAX_AXES ];
+ float max [ _JS_MAX_AXES ];
+ float min [ _JS_MAX_AXES ];
+};
+
+/*
+ * Functions associated with the "jsJoystick" class in PLIB
+ */
+#if TARGET_HOST_MAC_OSX
+#define K_NUM_DEVICES 32
+int numDevices;
+io_object_t ioDevices[K_NUM_DEVICES];
+
+static void fghJoystickFindDevices ( SFG_Joystick* joy, mach_port_t );
+static CFDictionaryRef fghJoystickGetCFProperties ( SFG_Joystick* joy, io_object_t );
+
+void fghJoystickEnumerateElements ( SFG_Joystick* joy, CFTypeRef element );
+/* callback for CFArrayApply */
+static void fghJoystickElementEnumerator ( SFG_Joystick* joy, void *element, void* vjs
);
+void fghJoystickParseElement ( SFG_Joystick* joy, CFDictionaryRef element );
+
+void fghJoystickAddAxisElement ( SFG_Joystick* joy, CFDictionaryRef axis );
+void fghJoystickAddButtonElement ( SFG_Joystick* joy, CFDictionaryRef button );
+void fghJoystickAddHatElement ( SFG_Joystick* joy, CFDictionaryRef hat );
+#endif
+
+
+/*
+ * The static joystick structure pointer
+ */
+#define MAX_NUM_JOYSTICKS 2
+static int fgNumberOfJoysticks = 0;
+static SFG_Joystick *fgJoystick [ MAX_NUM_JOYSTICKS ];
+
+
+/*
+ * Read the raw joystick data
+ */
+static void fghJoystickRawRead( SFG_Joystick* joy, int* buttons, float* axes )
+{
+#if TARGET_HOST_WIN32
+ MMRESULT status;
+#else
+ int status;
+#endif
+
+#if defined(__FreeBSD__) || defined(__NetBSD__)
+ int len;
+#endif
+
+ int i;
+
+ /* Defaults */
+ if( buttons )
+ *buttons = 0;
+
+ if( axes )
+ for( i = 0; i < joy->num_axes; i++ )
+ axes[ i ] = 1500.0f;
+
+ if( joy->error )
+ return;
+
+#if TARGET_HOST_MACINTOSH
+ if ( buttons )
+ {
+ *buttons = 0;
+
+ for ( i = 0; i < joy->num_buttons; i++ )
+ {
+ UInt32 state;
+ int err = ISpElement_GetSimpleState ( isp_elem [ i + isp_num_axis ],
&state);
+ ISP_CHECK_ERR(err)
+
+ *buttons |= state << i;
+ }
+ }
+
+ if ( axes )
+ {
+ for ( i = 0; i < joy->num_axes; i++ )
+ {
+ UInt32 state;
+ int err = ISpElement_GetSimpleState ( isp_elem [ i ], &state );
+ ISP_CHECK_ERR(err)
+
+ axes [i] = (float) state;
+ }
+ }
+#endif
+
+#if TARGET_HOST_MAC_OSX
+ if ( buttons != NULL )
+ {
+ *buttons = 0;
+
+ for ( i = 0; i < joy->num_buttons; i++ )
+ {
+ IOHIDEventStruct hidEvent;
+ (*(joy->hidDev))->getElementValue ( joy->hidDev, buttonCookies[i],
&hidEvent );
+ if ( hidEvent.value )
+ *buttons |= 1 << i;
+ }
+ }
+
+ if ( axes != NULL )
+ {
+ for ( i = 0; i < joy->num_axes; i++ )
+ {
+ IOHIDEventStruct hidEvent;
+ (*(joy->hidDev))->getElementValue ( joy->hidDev, axisCookies[i],
&hidEvent );
+ axes[i] = hidEvent.value;
+ }
+ }
+#endif
+
+#if TARGET_HOST_WIN32
+ status = joyGetPosEx( joy->js_id, &joy->js );
+
+ if ( status != JOYERR_NOERROR )
+ {
+ joy->error = GL_TRUE;
+ return;
+ }
+
+ if ( buttons )
+ *buttons = joy->js.dwButtons;
+
+ if ( axes )
+ {
+ /*
+ * WARNING - Fall through case clauses!!
+ */
+ switch ( joy->num_axes )
+ {
+ case 8:
+ /* Generate two POV axes from the POV hat angle.
+ * Low 16 bits of js.dwPOV gives heading (clockwise from ahead) in
+ * hundredths of a degree, or 0xFFFF when idle.
+ */
+ if ( ( joy->js.dwPOV & 0xFFFF ) == 0xFFFF )
+ {
+ axes [ 6 ] = 0.0;
+ axes [ 7 ] = 0.0;
+ }
+ else
+ {
+ /* This is the contentious bit: how to convert angle to X/Y.
+ * wk: I know of no define for PI that we could use here:
+ * SG_PI would pull in sg, M_PI is undefined for MSVC
+ * But the accuracy of the value of PI is very unimportant at
+ * this point.
+ */
+ float s = (float) sin ( ( joy->js.dwPOV & 0xFFFF ) * ( 0.01 *
3.1415926535f / 180.0f ) );
+ float c = (float) cos ( ( joy->js.dwPOV & 0xFFFF ) * ( 0.01 *
3.1415926535f / 180.0f ) );
+
+ /* Convert to coordinates on a square so that North-East
+ * is (1,1) not (.7,.7), etc.
+ * s and c cannot both be zero so we won't divide by zero.
+ */
+ if ( fabs ( s ) < fabs ( c ) )
+ {
+ axes [ 6 ] = ( c < 0.0 ) ? -s/c : s/c ;
+ axes [ 7 ] = ( c < 0.0 ) ? -1.0f : 1.0f;
+ }
+ else
+ {
+ axes [ 6 ] = ( s < 0.0 ) ? -1.0f : 1.0f;
+ axes [ 7 ] = ( s < 0.0 ) ? -c/s : c/s ;
+ }
+ }
+
+ case 6: axes[5] = (float) joy->js.dwVpos;
+ case 5: axes[4] = (float) joy->js.dwUpos;
+ case 4: axes[3] = (float) joy->js.dwRpos;
+ case 3: axes[2] = (float) joy->js.dwZpos;
+ case 2: axes[1] = (float) joy->js.dwYpos;
+ case 1: axes[0] = (float) joy->js.dwXpos;
+ }
+ }
+#endif
+
+#if TARGET_HOST_UNIX_X11
+# if defined(__FreeBSD__) || defined(__NetBSD__)
+ if ( joy->os->is_analog )
+ {
+ int status = read ( joy->os->fd, &joy->os->ajs,
sizeof(joy->os->ajs) );
+ if ( status != sizeof(joy->os->ajs) ) {
+ perror ( joy->os->fname );
+ joy->error = GL_TRUE;
+ return;
+ }
+ if ( buttons != NULL )
+ *buttons = ( joy->os->ajs.b1 ? 1 : 0 ) | ( joy->os->ajs.b2 ? 2 :
0 );
+
+ if ( axes != NULL )
+ {
+ axes[0] = (float) joy->os->ajs.x;
+ axes[1] = (float) joy->os->ajs.y;
+ }
+
+ return;
+ }
+
+# ifdef HAVE_USB_JS
+ while ( ( len = read ( joy->os->fd, joy->os->hid_data_buf,
joy->os->hid_dlen ) ) == joy->os->hid_dlen )
+ {
+ struct hid_item *h;
+
+ for ( h = joy->os->hids; h; h = h->next )
+ {
+ int d = hid_get_data ( joy->os->hid_data_buf, h );
+
+ int page = HID_PAGE ( h->usage );
+ int usage = HID_USAGE ( h->usage );
+
+ if ( page == HUP_GENERIC_DESKTOP )
+ {
+ int i;
+ for ( i = 0; i < joy->num_axes; i++ )
+ if (joy->os->axes_usage[i] == usage)
+ {
+ if (usage == HUG_HAT_SWITCH)
+ {
+ if (d < 0 || d > 8)
+ d = 0; /* safety */
+ joy->os->cache_axes[i] = (float)hatmap_x[d];
+ joy->os->cache_axes[i + 1] = (float)hatmap_y[d];
+ }
+ else
+ {
+ joy->os->cache_axes[i] = (float)d;
+ }
+ break;
+ }
+ }
+ else if (page == HUP_BUTTON)
+ {
+ if (usage > 0 && usage < _JS_MAX_BUTTONS + 1)
+ {
+ if (d)
+ joy->os->cache_buttons |= (1 << usage - 1);
+ else
+ joy->os->cache_buttons &= ~(1 << usage - 1);
+ }
+ }
+ }
+ }
+ if ( len < 0 && errno != EAGAIN )
+ {
+ perror( joy->os->fname );
+ joy->error = 1;
+ }
+ if ( buttons != NULL ) *buttons = joy->os->cache_buttons;
+ if ( axes != NULL )
+ memcpy ( axes, joy->os->cache_axes, sizeof(float) * joy->num_axes );
+# endif
+# endif
+
+# ifdef JS_NEW
+
+ while ( 1 )
+ {
+ status = read ( joy->fd, &joy->js, sizeof(struct js_event) );
+
+ if ( status != sizeof( struct js_event ) )
+ {
+ if ( errno == EAGAIN )
+ {
+ /* Use the old values */
+ if ( buttons )
+ *buttons = joy->tmp_buttons;
+ if ( axes )
+ memcpy( axes, joy->tmp_axes,
+ sizeof( float ) * joy->num_axes );
+ return;
+ }
+
+ fgWarning ( "%s", joy->fname );
+ joy->error = GL_TRUE;
+ return;
+ }
+
+ switch ( joy->js.type & ~JS_EVENT_INIT )
+ {
+ case JS_EVENT_BUTTON:
+ if( joy->js.value == 0 ) /* clear the flag */
+ joy->tmp_buttons &= ~( 1 << joy->js.number );
+ else
+ joy->tmp_buttons |= ( 1 << joy->js.number );
+ break;
+
+ case JS_EVENT_AXIS:
+ if ( joy->js.number < joy->num_axes )
+ {
+ joy->tmp_axes[ joy->js.number ] = ( float )joy->js.value;
+
+ if( axes )
+ memcpy( axes, joy->tmp_axes, sizeof(float) * joy->num_axes );
+ }
+ break;
+
+ default:
+ fgWarning ( "%s", "PLIB_JS: Unrecognised /dev/js
return!?!" );
+
+ /* use the old values */
+
+ if ( buttons != NULL ) *buttons = joy->tmp_buttons;
+ if ( axes != NULL )
+ memcpy ( axes, joy->tmp_axes, sizeof(float) * joy->num_axes );
+
+ return;
+ }
+
+ if( buttons )
+ *buttons = joy->tmp_buttons;
+ }
+# else
+
+ status = read( joy->fd, &joy->js, JS_RETURN );
+
+ if ( status != JS_RETURN )
+ {
+ fgWarning( "%s", joy->fname );
+ joy->error = GL_TRUE;
+ return;
+ }
+
+ if ( buttons )
+# if defined( __FreeBSD__ ) || defined( __NetBSD__ )
+ *buttons = ( joy->js.b1 ? 1 : 0 ) | ( joy->js.b2 ? 2 : 0 ); /* XXX Should
not be here -- BSD is handled earlier */
+# else
+ *buttons = joy->js.buttons;
+# endif
+
+ if ( axes )
+ {
+ axes[ 0 ] = (float) joy->js.x;
+ axes[ 1 ] = (float) joy->js.y;
+ }
+# endif
+#endif
+}
+
+/*
+ * Correct the joystick axis data
+ */
+static float fghJoystickFudgeAxis( SFG_Joystick* joy, float value, int axis )
+{
+ if( value < joy->center[ axis ] )
+ {
+ float xx = ( value - joy->center[ axis ] ) / ( joy->center[ axis ] -
+ joy->min[ axis ] );
+
+ if( xx < -joy->saturate[ axis ] )
+ return -1.0f;
+
+ if( xx > -joy->dead_band [ axis ] )
+ return 0.0f;
+
+ xx = ( xx + joy->dead_band[ axis ] ) / ( joy->saturate[ axis ] -
+ joy->dead_band[ axis ] );
+
+ return ( xx < -1.0f ) ? -1.0f : xx;
+ }
+ else
+ {
+ float xx = ( value - joy->center [ axis ] ) / ( joy->max[ axis ] -
+ joy->center[ axis ] );
+
+ if( xx > joy->saturate[ axis ] )
+ return 1.0f;
+
+ if( xx < joy->dead_band[ axis ] )
+ return 0.0f;
+
+ xx = ( xx - joy->dead_band[ axis ] ) / ( joy->saturate[ axis ] -
+ joy->dead_band[ axis ] );
+
+ return ( xx > 1.0f ) ? 1.0f : xx;
+ }
+}
+
+/*
+ * Read the corrected joystick data
+ */
+static void fghJoystickRead( SFG_Joystick* joy, int* buttons, float* axes )
+{
+ float raw_axes[ _JS_MAX_AXES ];
+ int i;
+
+ if( joy->error )
+ {
+ if( buttons )
+ *buttons = 0;
+
+ if( axes )
+ for ( i=0; i<joy->num_axes; i++ )
+ axes[ i ] = 0.0f;
+ }
+
+ fghJoystickRawRead( joy, buttons, raw_axes );
+
+ if( axes )
+ for( i=0; i<joy->num_axes; i++ )
+ axes[ i ] = fghJoystickFudgeAxis( joy, raw_axes[ i ], i );
+}
+
+/*
+ * Happy happy happy joy joy joy (happy new year toudi :D)
+ */
+
+
+#if TARGET_HOST_MAC_OSX
+/** open the IOKit connection, enumerate all the HID devices, add their
+interface references to the static array. We then use the array index
+as the device number when we come to open() the joystick. */
+static int fghJoystickFindDevices ( SFG_Joystick *joy, mach_port_t masterPort )
+{
+ CFMutableDictionaryRef hidMatch = NULL;
+ IOReturn rv = kIOReturnSuccess;
+
+ io_iterator_t hidIterator;
+ io_object_t ioDev;
+
+ /* build a dictionary matching HID devices */
+ hidMatch = IOServiceMatching(kIOHIDDeviceKey);
+
+ rv = IOServiceGetMatchingServices(masterPort, hidMatch, &hidIterator);
+ if (rv != kIOReturnSuccess || !hidIterator) {
+ fgWarning( "%s", "no joystick (HID) devices found" );
+ return;
+ }
+
+ /* iterate */
+ while ((ioDev = IOIteratorNext(hidIterator))) {
+ /* filter out keyboard and mouse devices */
+ CFDictionaryRef properties = getCFProperties(ioDev);
+ long usage, page;
+
+ CFTypeRef refPage = CFDictionaryGetValue (properties,
CFSTR(kIOHIDPrimaryUsagePageKey));
+ CFTypeRef refUsage = CFDictionaryGetValue (properties,
CFSTR(kIOHIDPrimaryUsageKey));
+ CFNumberGetValue((CFNumberRef) refUsage, kCFNumberLongType, &usage);
+ CFNumberGetValue((CFNumberRef) refPage, kCFNumberLongType, &page);
+
+ /* keep only joystick devices */
+ if ( ( page == kHIDPage_GenericDesktop ) && (
+ (usage == kHIDUsage_GD_Joystick)
+ || (usage == kHIDUsage_GD_GamePad)
+ || (usage == kHIDUsage_GD_MultiAxisController)
+ || (usage == kHIDUsage_GD_Hatswitch) /* last two necessary ? */
+ /* add it to the array */
+ ioDevices[numDevices++] = ioDev;
+ }
+
+ IOObjectRelease(hidIterator);
+}
+
+static CFDictionaryRef fghJoystickGetCFProperties ( SFG_Joystick *joy, io_object_t ioDev
)
+{
+ IOReturn rv;
+ CFMutableDictionaryRef cfProperties;
+
+#if 0
+ /* comment copied from darwin/SDL_sysjoystick.c */
+ /* Mac OS X currently is not mirroring all USB properties to HID page so need to look
at USB device page also
+ * get dictionary for usb properties: step up two levels and get CF dictionary for
USB properties
+ */
+
+ io_registry_entry_t parent1, parent2;
+
+ rv = IORegistryEntryGetParentEntry (ioDev, kIOServicePlane, &parent1);
+ if (rv != kIOReturnSuccess) {
+ fgWarning ( "%s", "error getting device entry parent");
+ return NULL;
+ }
+
+ rv = IORegistryEntryGetParentEntry (parent1, kIOServicePlane, &parent2);
+ if (rv != kIOReturnSuccess) {
+ fgWarning ( "%s", "error getting device entry parent 2");
+ return NULL;
+ }
+#endif
+
+ rv = IORegistryEntryCreateCFProperties( ioDev /*parent2*/,
+ &cfProperties, kCFAllocatorDefault, kNilOptions);
+ if (rv != kIOReturnSuccess || !cfProperties) {
+ fgWarning ( "%s", "error getting device properties");
+ return NULL;
+ }
+
+ return cfProperties;
+}
+
+static void fghJoystickElementEnumerator ( SFG_Joystick *joy, void *element, void* vjs )
+{
+ if (CFGetTypeID((CFTypeRef) element) != CFDictionaryGetTypeID()) {
+ fgError ( "%s", "element enumerator passed non-dictionary
value");
+ return;
+ }
+
+ static_cast<jsJoystick*>(vjs)->parseElement ( (CFDictionaryRef) element
);
+}
+
+/** element enumerator function : pass NULL for top-level*/
+static void fghJoystickEnumerateElements ( SFG_Joystick *joy, CFTypeRef element )
+{
+ assert(CFGetTypeID(element) == CFArrayGetTypeID());
+
+ CFRange range = {0, CFArrayGetCount ((CFArrayRef)element)};
+ CFArrayApplyFunction((CFArrayRef) element, range,
+ &fghJoystickElementEnumerator, joy );
+}
+
+static void fghJoystickParseElement ( SFG_Joystick *joy, CFDictionaryRef element )
+{
+ CFTypeRef refPage = CFDictionaryGetValue ((CFDictionaryRef) element,
CFSTR(kIOHIDElementUsagePageKey));
+ CFTypeRef refUsage = CFDictionaryGetValue ((CFDictionaryRef) element,
CFSTR(kIOHIDElementUsageKey));
+
+ long type, page, usage;
+
+ CFNumberGetValue((CFNumberRef)
+ CFDictionaryGetValue ((CFDictionaryRef) element, CFSTR(kIOHIDElementTypeKey)),
+ kCFNumberLongType, &type);
+
+ switch ( typ e) {
+ case kIOHIDElementTypeInput_Misc:
+ case kIOHIDElementTypeInput_Axis:
+ case kIOHIDElementTypeInput_Button:
+ printf("got input element...");
+ CFNumberGetValue( (CFNumberRef) refUsage, kCFNumberLongType, &usage );
+ CFNumberGetValue( (CFNumberRef) refPage, kCFNumberLongType, &page );
+
+ if (page == kHIDPage_GenericDesktop) {
+ switch ( usage ) /* look at usage to determine function */
+ {
+ case kHIDUsage_GD_X:
+ case kHIDUsage_GD_Y:
+ case kHIDUsage_GD_Z:
+ case kHIDUsage_GD_Rx:
+ case kHIDUsage_GD_Ry:
+ case kHIDUsage_GD_Rz:
+ case kHIDUsage_GD_Slider: /* for throttle / trim controls */
+ printf(" axis\n");
+ fghJoystickAddAxisElement((CFDictionaryRef) element);
+ break;
+
+ case kHIDUsage_GD_Hatswitch:
+ printf(" hat\n");
+ fghJoystickAddHatElement((CFDictionaryRef) element);
+ break;
+
+ default:
+ printf("input type element has weird usage (%x)\n", usage);
+ break;
+ }
+ } else if (page == kHIDPage_Button) {
+ printf(" button\n");
+ fghJoystickAddButtonElement((CFDictionaryRef) element);
+ } else
+ printf("input type element has weird page (%x)\n", page);
+ break;
+
+ case kIOHIDElementTypeCollection:
+ fghJoystickEnumerateElements (
+ CFDictionaryGetValue ( element, CFSTR(kIOHIDElementKey) )
+ );
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void fghJoystickAddAxisElement ( SFG_Joystick *joy, CFDictionaryRef axis )
+{
+ long cookie, lmin, lmax;
+ int index = joy->num_axes++;
+
+ CFNumberGetValue ((CFNumberRef)
+ CFDictionaryGetValue ( axis, CFSTR(kIOHIDElementCookieKey) ),
+ kCFNumberLongType, &cookie);
+
+ axisCookies[index] = (IOHIDElementCookie) cookie;
+
+ CFNumberGetValue ((CFNumberRef)
+ CFDictionaryGetValue ( axis, CFSTR(kIOHIDElementMinKey) ),
+ kCFNumberLongType, &lmin);
+
+ CFNumberGetValue ((CFNumberRef)
+ CFDictionaryGetValue ( axis, CFSTR(kIOHIDElementMaxKey) ),
+ kCFNumberLongType, &lmax);
+
+ joy->min[index] = lmin;
+ joy->max[index] = lmax;
+ joy->dead_band[index] = 0.0;
+ joy->saturate[index] = 1.0;
+ joy->center[index] = (lmax + lmin) * 0.5;
+}
+
+static void fghJoystickAddButtonElement ( SFG_Joystick *joy, CFDictionaryRef button )
+{
+ long cookie;
+ CFNumberGetValue ((CFNumberRef)
+ CFDictionaryGetValue ( button, CFSTR(kIOHIDElementCookieKey) ),
+ kCFNumberLongType, &cookie);
+
+ joy->buttonCookies[num_buttons++] = (IOHIDElementCookie) cookie;
+ /* anything else for buttons? */
+}
+
+static void fghJoystickAddHatElement ( SFG_Joystick *joy, CFDictionaryRef button )
+{
+ /* hatCookies[num_hats++] = (IOHIDElementCookie) cookie; */
+ /* do we map hats to axes or buttons? */
+}
+#endif
+
+#if TARGET_HOST_WIN32
+/* Inspired by
+
http://msdn.microsoft.com/archive/en-us/dnargame/html/msdn_sidewind3d.asp
+ */
+# if defined(_MSC_VER)
+# pragma comment (lib, "advapi32.lib")
+# endif
+
+static int fghJoystickGetOEMProductName ( SFG_Joystick* joy, char *buf, int buf_sz )
+{
+ char buffer [ 256 ];
+
+ char OEMKey [ 256 ];
+
+ HKEY hKey;
+ DWORD dwcb;
+ LONG lr;
+
+ if ( joy->error )
+ return 0;
+
+ /* Open .. MediaResources\CurrentJoystickSettings */
+ sprintf ( buffer, "%s\\%s\\%s",
+ REGSTR_PATH_JOYCONFIG, joy->jsCaps.szRegKey,
+ REGSTR_KEY_JOYCURR );
+
+ lr = RegOpenKeyEx ( HKEY_LOCAL_MACHINE, buffer, 0, KEY_QUERY_VALUE, &hKey);
+
+ if ( lr != ERROR_SUCCESS ) return 0;
+
+ /* Get OEM Key name */
+ dwcb = sizeof(OEMKey);
+
+ /* JOYSTICKID1-16 is zero-based; registry entries for VJOYD are 1-based. */
+ sprintf ( buffer, "Joystick%d%s", joy->js_id + 1, REGSTR_VAL_JOYOEMNAME
);
+
+ lr = RegQueryValueEx ( hKey, buffer, 0, 0, (LPBYTE) OEMKey, &dwcb);
+ RegCloseKey ( hKey );
+
+ if ( lr != ERROR_SUCCESS ) return 0;
+
+ /* Open OEM Key from ...MediaProperties */
+ sprintf ( buffer, "%s\\%s", REGSTR_PATH_JOYOEM, OEMKey );
+
+ lr = RegOpenKeyEx ( HKEY_LOCAL_MACHINE, buffer, 0, KEY_QUERY_VALUE, &hKey );
+
+ if ( lr != ERROR_SUCCESS ) return 0;
+
+ /* Get OEM Name */
+ dwcb = buf_sz;
+
+ lr = RegQueryValueEx ( hKey, REGSTR_VAL_JOYOEMNAME, 0, 0, (LPBYTE) buf,
+ &dwcb );
+ RegCloseKey ( hKey );
+
+ if ( lr != ERROR_SUCCESS ) return 0;
+
+ return 1;
+}
+#endif
+
+
+static void fghJoystickOpen( SFG_Joystick* joy )
+{
+ int i;
+#if TARGET_HOST_MACINTOSH
+ OSStatus err;
+#endif
+#if TARGET_HOST_MAC_OSX
+ IOReturn rv;
+ SInt32 score;
+ IOCFPlugInInterface **plugin;
+
+ HRESULT pluginResult;
+
+ CFDictionaryRef props;
+ CFTypeRef topLevelElement;
+#endif
+#if TARGET_HOST_UNIX_X11
+# if defined( __FreeBSD__ ) || defined( __NetBSD__ )
+ char *cp;
+# endif
+# ifdef JS_NEW
+ unsigned char u;
+# else
+ int counter;
+# endif
+#endif
+
+ /*
+ * Default values (for no joystick -- each conditional will reset the
+ * error flag)
+ */
+ joy->error = TRUE;
+ joy->num_axes = joy->num_buttons = 0;
+ joy->name[ 0 ] = '\0';
+
+#if TARGET_HOST_MACINTOSH
+ /*
+ * XXX FIXME: get joystick name in Mac
+ */
+
+ err = ISpStartup( );
+
+ if( err == noErr )
+ {
+#define ISP_CHECK_ERR(x) if( x != noErr ) { joy->error = GL_TRUE; return; }
+
+ joy->error = GL_TRUE;
+
+ /* initialize the needs structure */
+ ISpNeed temp_isp_needs[ isp_num_needs ] =
+ {
+ { "\pX-Axis", 128, 0, 0, kISpElementKind_Axis,
kISpElementLabel_None, 0, 0, 0, 0 },
+ { "\pY-Axis", 128, 0, 0, kISpElementKind_Axis,
kISpElementLabel_None, 0, 0, 0, 0 },
+ { "\pZ-Axis", 128, 0, 0, kISpElementKind_Axis,
kISpElementLabel_None, 0, 0, 0, 0 },
+ { "\pR-Axis", 128, 0, 0, kISpElementKind_Axis,
kISpElementLabel_None, 0, 0, 0, 0 },
+ { "\pAxis 4", 128, 0, 0, kISpElementKind_Axis,
kISpElementLabel_None, 0, 0, 0, 0 },
+ { "\pAxis 5", 128, 0, 0, kISpElementKind_Axis,
kISpElementLabel_None, 0, 0, 0, 0 },
+ { "\pAxis 6", 128, 0, 0, kISpElementKind_Axis,
kISpElementLabel_None, 0, 0, 0, 0 },
+ { "\pAxis 7", 128, 0, 0, kISpElementKind_Axis,
kISpElementLabel_None, 0, 0, 0, 0 },
+ { "\pAxis 8", 128, 0, 0, kISpElementKind_Axis,
kISpElementLabel_None, 0, 0, 0, 0 },
+
+ { "\pButton 0", 128, 0, 0, kISpElementKind_Button,
kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 1", 128, 0, 0, kISpElementKind_Button,
kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 2", 128, 0, 0, kISpElementKind_Button,
kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 3", 128, 0, 0, kISpElementKind_Button,
kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 4", 128, 0, 0, kISpElementKind_Button,
kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 5", 128, 0, 0, kISpElementKind_Button,
kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 6", 128, 0, 0, kISpElementKind_Button,
kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 7", 128, 0, 0, kISpElementKind_Button,
kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 8", 128, 0, 0, kISpElementKind_Button,
kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 9", 128, 0, 0, kISpElementKind_Button,
kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 10", 128, 0, 0, kISpElementKind_Button,
kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 11", 128, 0, 0, kISpElementKind_Button,
kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 12", 128, 0, 0, kISpElementKind_Button,
kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 13", 128, 0, 0, kISpElementKind_Button,
kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 14", 128, 0, 0, kISpElementKind_Button,
kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 15", 128, 0, 0, kISpElementKind_Button,
kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 16", 128, 0, 0, kISpElementKind_Button,
kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 17", 128, 0, 0, kISpElementKind_Button,
kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 18", 128, 0, 0, kISpElementKind_Button,
kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 19", 128, 0, 0, kISpElementKind_Button,
kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 20", 128, 0, 0, kISpElementKind_Button,
kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 21", 128, 0, 0, kISpElementKind_Button,
kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 22", 128, 0, 0, kISpElementKind_Button,
kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 23", 128, 0, 0, kISpElementKind_Button,
kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 24", 128, 0, 0, kISpElementKind_Button,
kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 25", 128, 0, 0, kISpElementKind_Button,
kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 26", 128, 0, 0, kISpElementKind_Button,
kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 27", 128, 0, 0, kISpElementKind_Button,
kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 28", 128, 0, 0, kISpElementKind_Button,
kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 29", 128, 0, 0, kISpElementKind_Button,
kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 30", 128, 0, 0, kISpElementKind_Button,
kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 31", 128, 0, 0, kISpElementKind_Button,
kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ };
+
+ memcpy( joy->isp_needs, temp_isp_needs, sizeof (temp_isp_needs ) );
+
+
+ /* next two calls allow keyboard and mouse to emulate other input
+ * devices (gamepads, joysticks, etc)
+ */
+ /*
+ err = ISpDevices_ActivateClass ( kISpDeviceClass_Keyboard );
+ ISP_CHECK_ERR(err)
+
+
+ err = ISpDevices_ActivateClass ( kISpDeviceClass_Mouse );
+ ISP_CHECK_ERR(err)
+ */
+
+ err = ISpElement_NewVirtualFromNeeds( joy->isp_num_needs,
+ joy->isp_needs, joy->isp_elem,
+ 0 );
+ ISP_CHECK_ERR( err )
+
+ err = ISpInit( joy->isp_num_needs, joy->isp_needs, joy->isp_elem,
+ 'freeglut', nil, 0, 128, 0 );
+ ISP_CHECK_ERR( err )
+
+ joy->num_buttons = joy->isp_num_needs - joy->isp_num_axis;
+ joy->num_axes = joy->isp_num_axis;
+
+ for( i = 0; i < joy->num_axes; i++ )
+ {
+ joy->dead_band[ i ] = 0;
+ joy->saturate [ i ] = 1;
+ joy->center [ i ] = kISpAxisMiddle;
+ joy->max [ i ] = kISpAxisMaximum;
+ joy->min [ i ] = kISpAxisMinimum;
+ }
+
+ joy->error = GL_FALSE;
+ }
+ else
+ joy->num_buttons = joy->num_axes = 0;
+#endif
+
+#if TARGET_HOST_MAC_OSX
+ if( joy->id >= numDevices )
+ {
+ fgWarning( "%s", "device index out of range in
fgJoystickOpen()" );
+ return;
+ }
+
+ /* create device interface */
+ rv = IOCreatePlugInInterfaceForService( ioDevices[ joy->id ],
+ kIOHIDDeviceUserClientTypeID,
+ kIOCFPlugInInterfaceID,
+ &plugin, &score );
+
+ if( rv != kIOReturnSuccess )
+ {
+ fgWarning( "%s", "error creating plugin for io device" );
+ return;
+ }
+
+ pluginResult = ( *plugin )->QueryInterface(
+ plugin,
+ CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID),
+ &( LPVOID )joy->hidDev
+ );
+
+ if( pluginResult != S_OK )
+ fgWarning ( "%s", "QI-ing IO plugin to HID Device interface
failed" );
+
+ ( *plugin )->Release( plugin ); /* don't leak a ref */
+ if( joy->hidDev == NULL )
+ return;
+
+ /* store the interface in this instance */
+ rv = ( *( joy->hidDev ) )->open( joy->hidDev, 0 );
+ if( rv != kIOReturnSuccess )
+ {
+ fgWarning( "error opening device interface");
+ return;
+ }
+
+ props = getCFProperties( ioDevices[ joy->id ] );
+
+ /* recursively enumerate all the bits */
+ CFTypeRef topLevelElement =
+ CFDictionaryGetValue( props, CFSTR( kIOHIDElementKey ) );
+ enumerateElements( topLevelElement );
+
+ CFRelease( props );
+#endif
+
+#if TARGET_HOST_WIN32
+ joy->js.dwFlags = JOY_RETURNALL;
+ joy->js.dwSize = sizeof( joy->js );
+
+ memset( &joy->jsCaps, 0, sizeof( joy->jsCaps ) );
+
+ joy->error =
+ ( joyGetDevCaps( joy->js_id, &joy->jsCaps, sizeof( joy->jsCaps ) )
!=
+ JOYERR_NOERROR );
+
+ if( joy->jsCaps.wNumAxes == 0 )
+ {
+ joy->num_axes = 0;
+ joy->error = GL_TRUE;
+ }
+ else
+ {
+ /* Device name from jsCaps is often "Microsoft PC-joystick driver",
+ * at least for USB. Try to get the real name from the registry.
+ */
+ if ( ! fghJoystickGetOEMProductName( joy, joy->name,
+ sizeof( joy->name ) ) )
+ {
+ fgWarning( "JS: Failed to read joystick name from registry" );
+ strncpy( joy->name, joy->jsCaps.szPname, sizeof( joy->name ) );
+ }
+
+ /* Windows joystick drivers may provide any combination of
+ * X,Y,Z,R,U,V,POV - not necessarily the first n of these.
+ */
+ if( joy->jsCaps.wCaps & JOYCAPS_HASPOV )
+ {
+ joy->num_axes = _JS_MAX_AXES;
+ joy->min[ 7 ] = -1.0; joy->max[ 7 ] = 1.0; /* POV Y */
+ joy->min[ 6 ] = -1.0; joy->max[ 6 ] = 1.0; /* POV X */
+ }
+ else
+ joy->num_axes = 6;
+
+ joy->min[ 5 ] = ( float )joy->jsCaps.wVmin;
+ joy->max[ 5 ] = ( float )joy->jsCaps.wVmax;
+ joy->min[ 4 ] = ( float )joy->jsCaps.wUmin;
+ joy->max[ 4 ] = ( float )joy->jsCaps.wUmax;
+ joy->min[ 3 ] = ( float )joy->jsCaps.wRmin;
+ joy->max[ 3 ] = ( float )joy->jsCaps.wRmax;
+ joy->min[ 2 ] = ( float )joy->jsCaps.wZmin;
+ joy->max[ 2 ] = ( float )joy->jsCaps.wZmax;
+ joy->min[ 1 ] = ( float )joy->jsCaps.wYmin;
+ joy->max[ 1 ] = ( float )joy->jsCaps.wYmax;
+ joy->min[ 0 ] = ( float )joy->jsCaps.wXmin;
+ joy->max[ 0 ] = ( float )joy->jsCaps.wXmax;
+ }
+
+ /*
+ * Guess all the rest judging on the axes extremals
+ */
+ for( i = 0; i < joy->num_axes; i++ )
+ {
+ joy->center [ i ] = ( joy->max[ i ] + joy->min[ i ] ) * 0.5f;
+ joy->dead_band[ i ] = 0.0f;
+ joy->saturate [ i ] = 1.0f;
+ }
+#endif
+
+#if TARGET_HOST_UNIX_X11
+#if defined( __FreeBSD__ ) || defined( __NetBSD__ )
+ for( i = 0; i < _JS_MAX_AXES; i++ )
+ joy->os->cache_axes[ i ] = 0.0f;
+
+ joy->os->cache_buttons = 0;
+
+ joy->os->fd = open( joy->os->fname, O_RDONLY | O_NONBLOCK);
+
+ if( joy->os->fd < 0 && errno == EACCES )
+ fgWarning ( "%s exists but is not readable by you\n",
joy->os->fname );
+
+ joy->error =( joy->os->fd < 0 );
+
+ if( joy->error )
+ return;
+
+ joy->num_axes = 0;
+ joy->num_buttons = 0;
+ if( joy->os->is_analog )
+ {
+ FILE *joyfile;
+ char joyfname[ 1024 ];
+ int noargs, in_no_axes;
+
+ float axes [ _JS_MAX_AXES ];
+ int buttons[ _JS_MAX_AXES ];
+
+ joy->num_axes = 2;
+ joy->num_buttons = 32;
+
+ fghJoystickRawRead( joy, buttons, axes );
+ joy->error = axes[ 0 ] < -1000000000.0f;
+ if( joy->error )
+ return;
+
+ sprintf( joyfname, "%s/.joy%drc", getenv( "HOME" ),
joy->id );
+
+ joyfile = fopen( joyfname, "r" );
+ joy->error =( joyfile == NULL );
+ if( joy->error )
+ return;
+
+ noargs = fscanf( joyfile, "%d%f%f%f%f%f%f", &in_no_axes,
+ &joy->min[ 0 ], &joy->center[ 0 ],
&joy->max[ 0 ],
+ &joy->min[ 1 ], &joy->center[ 1 ],
&joy->max[ 1 ] );
+ joy->error = noargs != 7 || in_no_axes != _JS_MAX_AXES;
+ fclose( joyfile );
+ if( joy->error )
+ return;
+
+ for( i = 0; i < _JS_MAX_AXES; i++ )
+ {
+ joy->dead_band[ i ] = 0.0f;
+ joy->saturate [ i ] = 1.0f;
+ }
+
+ return; /* End of analog code */
+ }
+
+# ifdef HAVE_USB_JS
+ if( ! fghJoystickInitializeHID( joy->os, &joy->num_axes,
+ &joy->num_buttons ) )
+ {
+ close( joy->os->fd );
+ joy->error = GL_TRUE;
+ return;
+ }
+
+ cp = strrchr( joy->os->fname, '/' );
+ if( cp )
+ {
+ if( fghJoystickFindUSBdev( &cp[1], joy->name, sizeof( joy->name ) ) ==
+ 0 )
+ strcpy( joy->name, &cp[1] );
+ }
+
+ if( joy->num_axes > _JS_MAX_AXES )
+ joy->num_axes = _JS_MAX_AXES;
+
+ for( i = 0; i < _JS_MAX_AXES; i++ )
+ {
+ /* We really should get this from the HID, but that data seems
+ * to be quite unreliable for analog-to-USB converters. Punt for
+ * now.
+ */
+ if( joy->os->axes_usage[ i ] == HUG_HAT_SWITCH )
+ {
+ joy->max [ i ] = 1.0f;
+ joy->center[ i ] = 0.0f;
+ joy->min [ i ] = -1.0f;
+ }
+ else
+ {
+ joy->max [ i ] = 255.0f;
+ joy->center[ i ] = 127.0f;
+ joy->min [ i ] = 0.0f;
+ }
+
+ joy->dead_band[ i ] = 0.0f;
+ joy->saturate[ i ] = 1.0f;
+ }
+# endif
+#endif
+
+#if defined( __linux__ )
+ /*
+ * Default for older Linux systems.
+ */
+ joy->num_axes = 2;
+ joy->num_buttons = 32;
+
+# ifdef JS_NEW
+ for( i = 0; i < _JS_MAX_AXES; i++ )
+ joy->tmp_axes[ i ] = 0.0f;
+
+ joy->tmp_buttons = 0;
+# endif
+
+ joy->fd = open( joy->fname, O_RDONLY );
+
+ joy->error =( joy->fd < 0 );
+
+ if( joy->error )
+ return;
+
+ /*
+ * Set the correct number of axes for the linux driver
+ */
+# ifdef JS_NEW
+ /* Melchior Franz's fixes for big-endian Linuxes since writing
+ * to the upper byte of an uninitialized word doesn't work.
+ * 9 April 2003
+ */
+ ioctl( joy->fd, JSIOCGAXES, &u );
+ joy->num_axes = u;
+ ioctl( joy->fd, JSIOCGBUTTONS, &u );
+ joy->num_buttons = u;
+ ioctl( joy->fd, JSIOCGNAME( sizeof( joy->name ) ), joy->name );
+ fcntl( joy->fd, F_SETFL, O_NONBLOCK );
+# endif
+
+ /*
+ * The Linux driver seems to return 512 for all axes
+ * when no stick is present - but there is a chance
+ * that could happen by accident - so it's gotta happen
+ * on both axes for at least 100 attempts.
+ *
+ * PWO: shouldn't be that done somehow wiser on the kernel level?
+ */
+# ifndef JS_NEW
+ counter = 0;
+
+ do
+ {
+ fghJoystickRawRead( joy, NULL, joy->center );
+ counter++;
+ } while( !joy->error &&
+ counter < 100 &&
+ joy->center[ 0 ] == 512.0f &&
+ joy->center[ 1 ] == 512.0f );
+
+ if ( counter >= 100 )
+ joy->error = GL_TRUE;
+# endif
+
+ for( i = 0; i < _JS_MAX_AXES; i++ )
+ {
+# ifdef JS_NEW
+ joy->max [ i ] = 32767.0f;
+ joy->center[ i ] = 0.0f;
+ joy->min [ i ] = -32767.0f;
+# else
+ joy->max[ i ] = joy->center[ i ] * 2.0f;
+ joy->min[ i ] = 0.0f;
+# endif
+ joy->dead_band[ i ] = 0.0f;
+ joy->saturate [ i ] = 1.0f;
+ }
+#endif
+#endif
+}
+
+/*
+ * This function replaces the constructor method in the JS library.
+ */
+void fgJoystickInit( int ident )
+{
+ if( ident >= MAX_NUM_JOYSTICKS )
+ fgError( "Too large a joystick number" );
+
+ if( fgJoystick[ ident ] )
+ fgError( "illegal attempt to initialize joystick device" );
+
+ fgJoystick[ ident ] =
+ ( SFG_Joystick * )calloc( sizeof( SFG_Joystick ), 1 );
+
+ /* Set defaults */
+ fgJoystick[ ident ]->num_axes = fgJoystick[ ident ]->num_buttons = 0;
+ fgJoystick[ ident ]->error = GL_TRUE;
+
+#if TARGET_HOST_MACINTOSH
+ fgJoystick[ ident ]->id = ident;
+ sprintf( fgJoystick[ ident ]->fname, "/dev/js%d", ident ); /* FIXME */
+ fgJoystick[ ident ]->error = GL_FALSE;
+#endif
+
+#if TARGET_HOST_MAC_OSX
+ fgJoystick[ ident ]->id = ident;
+ fgJoystick[ ident ]->error = GL_FALSE;
+ fgJoystick[ ident ]->num_axes = 0;
+ fgJoystick[ ident ]->num_buttons = 0;
+
+ if( numDevices < 0 )
+ {
+ /* do first-time init (since we can't over-ride jsInit, hmm */
+ numDevices = 0;
+
+ mach_port_t masterPort;
+ IOReturn rv = IOMasterPort( bootstrap_port, &masterPort );
+ if( rv != kIOReturnSuccess )
+ {
+ fgWarning( "%s", "error getting master Mach port" );
+ return;
+ }
+ fghJoystickFindDevices( masterPort );
+ }
+
+ if ( ident >= numDevices )
+ {
+ fgJoystick[ ident ]->error = GL_TRUE;
+ return;
+ }
+
+ /* get the name now too */
+ CFDictionaryRef properties = getCFProperties( ioDevices[ ident ] );
+ CFTypeRef ref = CFDictionaryGetValue( properties,
+ CFSTR( kIOHIDProductKey ) );
+ if (!ref)
+ ref = CFDictionaryGetValue(properties, CFSTR( "USB Product Name" ) );
+
+ if( !ref ||
+ !CFStringGetCString( ( CFStringRef )ref, name, 128,
+ CFStringGetSystemEncoding( ) ) )
+ {
+ fgWarning( "%s", "error getting device name" );
+ name[ 0 ] = '\0';
+ }
+#endif
+
+#if TARGET_HOST_WIN32
+ switch( ident )
+ {
+ case 0:
+ fgJoystick[ ident ]->js_id = JOYSTICKID1;
+ fgJoystick[ ident ]->error = GL_FALSE;
+ break;
+ case 1:
+ fgJoystick[ ident ]->js_id = JOYSTICKID2;
+ fgJoystick[ ident ]->error = GL_FALSE;
+ break;
+ default:
+ fgJoystick[ ident ]->num_axes = 0;
+ fgJoystick[ ident ]->error = GL_TRUE;
+ return;
+ }
+#endif
+
+#if TARGET_HOST_UNIX_X11
+# if defined( __FreeBSD__ ) || defined( __NetBSD__ )
+ fgJoystick[ ident ]->id = ident;
+ fgJoystick[ ident ]->error = GL_FALSE;
+
+ fgJoystick[ ident ]->os = calloc( 1, sizeof( struct os_specific_s ) );
+ memset( fgJoystick[ ident ]->os, 0, sizeof( struct os_specific_s ) );
+ if( ident < USB_IDENT_OFFSET )
+ fgJoystick[ ident ]->os->is_analog = 1;
+ if( fgJoystick[ ident ]->os->is_analog )
+ sprintf( fgJoystick[ ident ]->os->fname, "%s%d", AJSDEV, ident
);
+ else
+ sprintf( fgJoystick[ ident ]->os->fname, "%s%d", UHIDDEV,
+ ident - USB_IDENT_OFFSET );
+# elif defined( __linux__ )
+ fgJoystick[ ident ]->id = ident;
+ fgJoystick[ ident ]->error = GL_FALSE;
+
+ sprintf( fgJoystick[ident]->fname, "/dev/input/js%d", ident );
+
+ if( access( fgJoystick[ ident ]->fname, F_OK ) != 0 )
+ sprintf( fgJoystick[ ident ]->fname, "/dev/js%d", ident );
+# endif
+#endif
+
+ fghJoystickOpen( fgJoystick[ ident ] );
+}
+
+/*
+ *
+ */
+void fgJoystickClose( void )
+{
+ int ident ;
+ for( ident = 0; ident < MAX_NUM_JOYSTICKS; ident++ )
+ {
+ if( fgJoystick[ ident ] )
+ {
+
+#if TARGET_HOST_MACINTOSH
+ ISpSuspend( );
+ ISpStop( );
+ ISpShutdown( );
+#endif
+
+#if TARGET_HOST_MAC_OSX
+ ( *( fgJoystick[ ident ]->hidDev ) )->
+ close( fgJoystick[ ident ]->hidDev );
+#endif
+
+#if TARGET_HOST_WIN32
+ /* Do nothing special */
+#endif
+
+#if TARGET_HOST_UNIX_X11
+#if defined( __FreeBSD__ ) || defined( __NetBSD__ )
+ if( fgJoystick[ident]->os )
+ {
+ if( ! fgJoystick[ ident ]->error )
+ close( fgJoystick[ ident ]->os->fd );
+#ifdef HAVE_USB_JS
+ if( fgJoystick[ ident ]->os->hids )
+ free (fgJoystick[ ident ]->os->hids);
+ if( fgJoystick[ ident ]->os->hid_data_buf )
+ free( fgJoystick[ ident ]->os->hid_data_buf );
+#endif
+ free( fgJoystick[ident]->os );
+ }
+#endif
+
+ if( ! fgJoystick[ident]->error )
+ close( fgJoystick[ ident ]->fd );
+#endif
+
+ free( fgJoystick[ ident ] );
+ fgJoystick[ ident ] = NULL;
+ /* show joystick has been deinitialized */
+ }
+ }
+}
+
+/*
+ * Polls the joystick and executes the joystick callback hooked to the
+ * window specified in the function's parameter:
+ */
+void fgJoystickPollWindow( SFG_Window* window )
+{
+ float axes[ _JS_MAX_AXES ];
+ int buttons;
+ int ident;
+
+ freeglut_return_if_fail( window );
+ freeglut_return_if_fail( FETCH_WCB( *window, Joystick ) );
+
+ for( ident = 0; ident < MAX_NUM_JOYSTICKS; ident++ )
+ {
+ if( fgJoystick[ident] )
+ {
+ fghJoystickRead( fgJoystick[ident], &buttons, axes );
+
+ if( !fgJoystick[ident]->error )
+ INVOKE_WCB( *window, Joystick,
+ ( buttons,
+ (int) ( axes[ 0 ] * 1000.0f ),
+ (int) ( axes[ 1 ] * 1000.0f ),
+ (int) ( axes[ 2 ] * 1000.0f ) )
+ );
+ }
+ }
+}
+
+/*
+ * PWO: These jsJoystick class methods have not been implemented.
+ * We might consider adding such functions to freeglut-2.0.
+ */
+int glutJoystickGetNumAxes( int ident )
+{
+ return fgJoystick[ ident ]->num_axes;
+}
+int glutJoystickNotWorking( int ident )
+{
+ return fgJoystick[ ident ]->error;
+}
+
+float glutJoystickGetDeadBand( int ident, int axis )
+{
+ return fgJoystick[ ident ]->dead_band [ axis ];
+}
+void glutJoystickSetDeadBand( int ident, int axis, float db )
+{
+ fgJoystick[ ident ]->dead_band[ axis ] = db;
+}
+
+float glutJoystickGetSaturation( int ident, int axis )
+{
+ return fgJoystick[ ident ]->saturate[ axis ];
+}
+void glutJoystickSetSaturation( int ident, int axis, float st )
+{
+ fgJoystick[ ident ]->saturate [ axis ] = st;
+}
+
+void glutJoystickSetMinRange( int ident, float *axes )
+{
+ memcpy( fgJoystick[ ident ]->min, axes,
+ fgJoystick[ ident ]->num_axes * sizeof( float ) );
+}
+void glutJoystickSetMaxRange( int ident, float *axes )
+{
+ memcpy( fgJoystick[ ident ]->max, axes,
+ fgJoystick[ ident ]->num_axes * sizeof( float ) );
+}
+void glutJoystickSetCenter( int ident, float *axes )
+{
+ memcpy( fgJoystick[ ident ]->center, axes,
+ fgJoystick[ ident ]->num_axes * sizeof( float ) );
+}
+
+void glutJoystickGetMinRange( int ident, float *axes )
+{
+ memcpy( axes, fgJoystick[ ident ]->min,
+ fgJoystick[ ident ]->num_axes * sizeof( float ) );
+}
+void glutJoystickGetMaxRange( int ident, float *axes )
+{
+ memcpy( axes, fgJoystick[ ident ]->max,
+ fgJoystick[ ident ]->num_axes * sizeof( float ) );
+}
+void glutJoystickGetCenter( int ident, float *axes )
+{
+ memcpy( axes, fgJoystick[ ident ]->center,
+ fgJoystick[ ident ]->num_axes * sizeof( float ) );
+}
+
+/*** END OF FILE ***/
Index: external/trimesh/gluit/freeglut_font_data.c
--- external/trimesh/gluit/freeglut_font_data.c (revision 0)
+++ external/trimesh/gluit/freeglut_font_data.c (revision 0)
@@ -0,0 +1,2024 @@
+/*
+ \file og_font_data.c
+ \brief Bitmapped font data for OpenGLUT fonts.
+*/
+
+/*
+ * This file has been automatically generated by the
+ * genfonts utility.
+ *
+ * The legal status of this file is a bit vague. The font glyphs
+ * themselves come from XFree86 v4.3.0 (as of this writing), and as
+ * part of the X server may be subject to the XFree86 copyrights.
+ * The original freeglut fonts were extracted by a utility written
+ * by Pawel W. Olszta (see below) and the generated fonts contained
+ * his copyright exclusively. Steve Baker asserts that Pawel
+ * assigned intellectual property writes to Steve Baker. Steve
+ * Baker also asserts that fonts cannot be copyrighted. He has
+ * neither stripped the copyright from the freeglut fonts nor
+ * formally retitled anything in his name. Since that time, the
+ * OpenGLUT project has branched from freeglut, and has made
+ * necessary modifications to Pawel's ``genfonts'' utility.
+ * To that extent, OpenGLUT may have some title to this file.
+ * What is fairly clear is that the font data is licensed under
+ * the XFree86 license (which is variously termed ``XFree'' and
+ * ``MIT'' by the freeglut project). It is believed that all
+ * title holders wish this file to be as useful as possible, and
+ * that either the ``XFree'' or ``MIT'' license works.
+ *
+ * Portions copyright (c) 2004, the OpenGLUT project contributors.
+ * OpenGLUT branched from freeglut in February, 2004.
+ *
+ * Copyright (c) 1999-2000 by Pawel W. Olszta
+ * Written by Pawel W. Olszta, <olszta(a)sourceforge.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Sotware.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <GL/freeglut.h>
+#include "freeglut_internal.h"
+
+/*
+ * The following bitmapped fonts are defined in this file:
+ *
+ * 1. fgFontFixed8x13
+ * -misc-fixed-medium-r-normal--13-120-75-75-C-80-iso8859-1
+ * 2. fgFontFixed9x15
+ * -misc-fixed-medium-r-normal--15-140-75-75-C-90-iso8859-1
+ * 3. fgFontHelvetica10
+ * -adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1
+ * 4. fgFontHelvetica12
+ * -adobe-helvetica-medium-r-normal--12-120-75-75-p-67-iso8859-1
+ * 5. fgFontHelvetica18
+ * -adobe-helvetica-medium-r-normal--18-180-75-75-p-98-iso8859-1
+ * 6. fgFontTimesRoman10
+ * -adobe-times-medium-r-normal--10-100-75-75-p-54-iso8859-1
+ * 7. fgFontTimesRoman24
+ * -adobe-times-medium-r-normal--24-240-75-75-p-124-iso8859-1
+ */
+
+static const GLubyte Fixed8x13_Character_000[] = { 8, 0, 0, 0,170, 0,130, 0,130,
0,130, 0,170, 0, 0};
+static const GLubyte Fixed8x13_Character_001[] = { 8, 0, 0, 0, 0, 16,
56,124,254,124, 56, 16, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_002[] = { 8, 0,170, 85,170, 85,170, 85,170,
85,170, 85,170, 85,170};
+static const GLubyte Fixed8x13_Character_003[] = { 8, 0, 0, 0, 4, 4, 4,
4,174,160,224,160,160, 0, 0};
+static const GLubyte Fixed8x13_Character_004[] = { 8, 0, 0, 0, 8, 8, 12,
8,142,128,192,128,224, 0, 0};
+static const GLubyte Fixed8x13_Character_005[] = { 8, 0, 0, 0, 10, 10, 12,
10,108,128,128,128, 96, 0, 0};
+static const GLubyte Fixed8x13_Character_006[] = { 8, 0, 0, 0, 8, 8, 12,
8,238,128,128,128,128, 0, 0};
+static const GLubyte Fixed8x13_Character_007[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0,
24, 36, 36, 24, 0, 0};
+static const GLubyte Fixed8x13_Character_008[] = { 8, 0, 0, 0, 0,124, 0, 16,
16,124, 16, 16, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_009[] = { 8, 0, 0, 0, 14, 8, 8,
8,168,160,160,160,192, 0, 0};
+static const GLubyte Fixed8x13_Character_010[] = { 8, 0, 0, 0, 4, 4, 4, 4, 46,
80, 80,136,136, 0, 0};
+static const GLubyte Fixed8x13_Character_011[] = { 8, 0, 0, 0, 0, 0, 0, 0,240,
16, 16, 16, 16, 16, 16};
+static const GLubyte Fixed8x13_Character_012[] = { 8, 0, 16, 16, 16, 16, 16, 16,240,
0, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_013[] = { 8, 0, 16, 16, 16, 16, 16, 16, 31,
0, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_014[] = { 8, 0, 0, 0, 0, 0, 0, 0, 31,
16, 16, 16, 16, 16, 16};
+static const GLubyte Fixed8x13_Character_015[] = { 8, 0, 16, 16, 16, 16, 16, 16,255,
16, 16, 16, 16, 16, 16};
+static const GLubyte Fixed8x13_Character_016[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0,255};
+static const GLubyte Fixed8x13_Character_017[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,255, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_018[] = { 8, 0, 0, 0, 0, 0, 0, 0,255,
0, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_019[] = { 8, 0, 0, 0, 0,255, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_020[] = { 8, 0,255, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_021[] = { 8, 0, 16, 16, 16, 16, 16, 16, 31,
16, 16, 16, 16, 16, 16};
+static const GLubyte Fixed8x13_Character_022[] = { 8, 0, 16, 16, 16, 16, 16, 16,240,
16, 16, 16, 16, 16, 16};
+static const GLubyte Fixed8x13_Character_023[] = { 8, 0, 0, 0, 0, 0, 0, 0,255,
16, 16, 16, 16, 16, 16};
+static const GLubyte Fixed8x13_Character_024[] = { 8, 0, 16, 16, 16, 16, 16, 16,255,
0, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_025[] = { 8, 0, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16};
+static const GLubyte Fixed8x13_Character_026[] = { 8, 0, 0, 0,254, 0, 14, 48,192,
48, 14, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_027[] = { 8, 0, 0, 0,254, 0,224, 24, 6,
24,224, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_028[] = { 8, 0, 0, 0, 68, 68, 68, 68,
68,254, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_029[] = { 8, 0, 0, 0, 32, 32,126, 16,
8,126, 4, 4, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_030[] = { 8, 0, 0, 0,220, 98, 32, 32,
32,112, 32, 34, 28, 0, 0};
+static const GLubyte Fixed8x13_Character_031[] = { 8, 0, 0, 0, 0, 0, 0, 0, 24,
0, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_032[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_033[] = { 8, 0, 0, 0, 16, 0, 16, 16, 16,
16, 16, 16, 16, 0, 0};
+static const GLubyte Fixed8x13_Character_034[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0,
0, 36, 36, 36, 0, 0};
+static const GLubyte Fixed8x13_Character_035[] = { 8, 0, 0, 0, 0, 36, 36,126,
36,126, 36, 36, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_036[] = { 8, 0, 0, 0, 16,120, 20, 20, 56,
80, 80, 60, 16, 0, 0};
+static const GLubyte Fixed8x13_Character_037[] = { 8, 0, 0, 0, 68, 42, 36, 16, 8,
8, 36, 82, 34, 0, 0};
+static const GLubyte Fixed8x13_Character_038[] = { 8, 0, 0, 0, 58, 68, 74, 48, 72,
72, 48, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_039[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0,
0, 64, 48, 56, 0, 0};
+static const GLubyte Fixed8x13_Character_040[] = { 8, 0, 0, 0, 4, 8, 8, 16, 16,
16, 8, 8, 4, 0, 0};
+static const GLubyte Fixed8x13_Character_041[] = { 8, 0, 0, 0, 32, 16, 16, 8, 8,
8, 16, 16, 32, 0, 0};
+static const GLubyte Fixed8x13_Character_042[] = { 8, 0, 0, 0, 0, 0, 36, 24,126,
24, 36, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_043[] = { 8, 0, 0, 0, 0, 0, 16, 16,124,
16, 16, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_044[] = { 8, 0, 0, 64, 48, 56, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_045[] = { 8, 0, 0, 0, 0, 0, 0, 0,126,
0, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_046[] = { 8, 0, 0, 16, 56, 16, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_047[] = { 8, 0, 0, 0,128,128, 64, 32, 16,
8, 4, 2, 2, 0, 0};
+static const GLubyte Fixed8x13_Character_048[] = { 8, 0, 0, 0, 24, 36, 66, 66, 66,
66, 66, 36, 24, 0, 0};
+static const GLubyte Fixed8x13_Character_049[] = { 8, 0, 0, 0,124, 16, 16, 16, 16,
16, 80, 48, 16, 0, 0};
+static const GLubyte Fixed8x13_Character_050[] = { 8, 0, 0, 0,126, 64, 32, 24, 4,
2, 66, 66, 60, 0, 0};
+static const GLubyte Fixed8x13_Character_051[] = { 8, 0, 0, 0, 60, 66, 2, 2, 28,
8, 4, 2,126, 0, 0};
+static const GLubyte Fixed8x13_Character_052[] = { 8, 0, 0, 0, 4, 4,126, 68, 68,
36, 20, 12, 4, 0, 0};
+static const GLubyte Fixed8x13_Character_053[] = { 8, 0, 0, 0, 60, 66, 2, 2, 98,
92, 64, 64,126, 0, 0};
+static const GLubyte Fixed8x13_Character_054[] = { 8, 0, 0, 0, 60, 66, 66, 98, 92,
64, 64, 32, 28, 0, 0};
+static const GLubyte Fixed8x13_Character_055[] = { 8, 0, 0, 0, 32, 32, 16, 16, 8,
8, 4, 2,126, 0, 0};
+static const GLubyte Fixed8x13_Character_056[] = { 8, 0, 0, 0, 60, 66, 66, 66, 60,
66, 66, 66, 60, 0, 0};
+static const GLubyte Fixed8x13_Character_057[] = { 8, 0, 0, 0, 56, 4, 2, 2, 58,
70, 66, 66, 60, 0, 0};
+static const GLubyte Fixed8x13_Character_058[] = { 8, 0, 0, 16, 56, 16, 0, 0, 16,
56, 16, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_059[] = { 8, 0, 0, 64, 48, 56, 0, 0, 16,
56, 16, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_060[] = { 8, 0, 0, 0, 2, 4, 8, 16, 32,
16, 8, 4, 2, 0, 0};
+static const GLubyte Fixed8x13_Character_061[] = { 8, 0, 0, 0, 0, 0,126, 0,
0,126, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_062[] = { 8, 0, 0, 0, 64, 32, 16, 8, 4,
8, 16, 32, 64, 0, 0};
+static const GLubyte Fixed8x13_Character_063[] = { 8, 0, 0, 0, 8, 0, 8, 8, 4,
2, 66, 66, 60, 0, 0};
+static const GLubyte Fixed8x13_Character_064[] = { 8, 0, 0, 0, 60, 64, 74, 86, 82,
78, 66, 66, 60, 0, 0};
+static const GLubyte Fixed8x13_Character_065[] = { 8, 0, 0, 0, 66, 66, 66,126, 66,
66, 66, 36, 24, 0, 0};
+static const GLubyte Fixed8x13_Character_066[] = { 8, 0, 0, 0,252, 66, 66, 66,124,
66, 66, 66,252, 0, 0};
+static const GLubyte Fixed8x13_Character_067[] = { 8, 0, 0, 0, 60, 66, 64, 64, 64,
64, 64, 66, 60, 0, 0};
+static const GLubyte Fixed8x13_Character_068[] = { 8, 0, 0, 0,252, 66, 66, 66, 66,
66, 66, 66,252, 0, 0};
+static const GLubyte Fixed8x13_Character_069[] = { 8, 0, 0, 0,126, 64, 64, 64,120,
64, 64, 64,126, 0, 0};
+static const GLubyte Fixed8x13_Character_070[] = { 8, 0, 0, 0, 64, 64, 64, 64,120,
64, 64, 64,126, 0, 0};
+static const GLubyte Fixed8x13_Character_071[] = { 8, 0, 0, 0, 58, 70, 66, 78, 64,
64, 64, 66, 60, 0, 0};
+static const GLubyte Fixed8x13_Character_072[] = { 8, 0, 0, 0, 66, 66, 66, 66,126,
66, 66, 66, 66, 0, 0};
+static const GLubyte Fixed8x13_Character_073[] = { 8, 0, 0, 0,124, 16, 16, 16, 16,
16, 16, 16,124, 0, 0};
+static const GLubyte Fixed8x13_Character_074[] = { 8, 0, 0, 0, 56, 68, 4, 4, 4,
4, 4, 4, 31, 0, 0};
+static const GLubyte Fixed8x13_Character_075[] = { 8, 0, 0, 0, 66, 68, 72, 80, 96,
80, 72, 68, 66, 0, 0};
+static const GLubyte Fixed8x13_Character_076[] = { 8, 0, 0, 0,126, 64, 64, 64, 64,
64, 64, 64, 64, 0, 0};
+static const GLubyte Fixed8x13_Character_077[] = { 8, 0, 0,
0,130,130,130,146,146,170,198,130,130, 0, 0};
+static const GLubyte Fixed8x13_Character_078[] = { 8, 0, 0, 0, 66, 66, 66, 70, 74,
82, 98, 66, 66, 0, 0};
+static const GLubyte Fixed8x13_Character_079[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66,
66, 66, 66, 60, 0, 0};
+static const GLubyte Fixed8x13_Character_080[] = { 8, 0, 0, 0, 64, 64, 64, 64,124,
66, 66, 66,124, 0, 0};
+static const GLubyte Fixed8x13_Character_081[] = { 8, 0, 0, 2, 60, 74, 82, 66, 66,
66, 66, 66, 60, 0, 0};
+static const GLubyte Fixed8x13_Character_082[] = { 8, 0, 0, 0, 66, 68, 72, 80,124,
66, 66, 66,124, 0, 0};
+static const GLubyte Fixed8x13_Character_083[] = { 8, 0, 0, 0, 60, 66, 2, 2, 60,
64, 64, 66, 60, 0, 0};
+static const GLubyte Fixed8x13_Character_084[] = { 8, 0, 0, 0, 16, 16, 16, 16, 16,
16, 16, 16,254, 0, 0};
+static const GLubyte Fixed8x13_Character_085[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66,
66, 66, 66, 66, 0, 0};
+static const GLubyte Fixed8x13_Character_086[] = { 8, 0, 0, 0, 16, 40, 40, 40, 68,
68, 68,130,130, 0, 0};
+static const GLubyte Fixed8x13_Character_087[] = { 8, 0, 0, 0,
68,170,146,146,146,130,130,130,130, 0, 0};
+static const GLubyte Fixed8x13_Character_088[] = { 8, 0, 0, 0,130,130, 68, 40, 16,
40, 68,130,130, 0, 0};
+static const GLubyte Fixed8x13_Character_089[] = { 8, 0, 0, 0, 16, 16, 16, 16, 16,
40, 68,130,130, 0, 0};
+static const GLubyte Fixed8x13_Character_090[] = { 8, 0, 0, 0,126, 64, 64, 32, 16,
8, 4, 2,126, 0, 0};
+static const GLubyte Fixed8x13_Character_091[] = { 8, 0, 0, 0, 60, 32, 32, 32, 32,
32, 32, 32, 60, 0, 0};
+static const GLubyte Fixed8x13_Character_092[] = { 8, 0, 0, 0, 2, 2, 4, 8, 16,
32, 64,128,128, 0, 0};
+static const GLubyte Fixed8x13_Character_093[] = { 8, 0, 0, 0,120, 8, 8, 8, 8,
8, 8, 8,120, 0, 0};
+static const GLubyte Fixed8x13_Character_094[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0,
0, 68, 40, 16, 0, 0};
+static const GLubyte Fixed8x13_Character_095[] = { 8, 0, 0,254, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_096[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0,
0, 4, 24, 56, 0, 0};
+static const GLubyte Fixed8x13_Character_097[] = { 8, 0, 0, 0, 58, 70, 66, 62, 2,
60, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_098[] = { 8, 0, 0, 0, 92, 98, 66, 66, 98,
92, 64, 64, 64, 0, 0};
+static const GLubyte Fixed8x13_Character_099[] = { 8, 0, 0, 0, 60, 66, 64, 64, 66,
60, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_100[] = { 8, 0, 0, 0, 58, 70, 66, 66, 70,
58, 2, 2, 2, 0, 0};
+static const GLubyte Fixed8x13_Character_101[] = { 8, 0, 0, 0, 60, 66, 64,126, 66,
60, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_102[] = { 8, 0, 0, 0, 32, 32, 32, 32,124,
32, 32, 34, 28, 0, 0};
+static const GLubyte Fixed8x13_Character_103[] = { 8, 0, 60, 66, 60, 64, 56, 68, 68,
58, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_104[] = { 8, 0, 0, 0, 66, 66, 66, 66, 98,
92, 64, 64, 64, 0, 0};
+static const GLubyte Fixed8x13_Character_105[] = { 8, 0, 0, 0,124, 16, 16, 16, 16,
48, 0, 16, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_106[] = { 8, 0, 56, 68, 68, 4, 4, 4, 4,
12, 0, 4, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_107[] = { 8, 0, 0, 0, 66, 68, 72,112, 72,
68, 64, 64, 64, 0, 0};
+static const GLubyte Fixed8x13_Character_108[] = { 8, 0, 0, 0,124, 16, 16, 16, 16,
16, 16, 16, 48, 0, 0};
+static const GLubyte Fixed8x13_Character_109[] = { 8, 0, 0,
0,130,146,146,146,146,236, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_110[] = { 8, 0, 0, 0, 66, 66, 66, 66, 98,
92, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_111[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66,
60, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_112[] = { 8, 0, 64, 64, 64, 92, 98, 66, 98,
92, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_113[] = { 8, 0, 2, 2, 2, 58, 70, 66, 70,
58, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_114[] = { 8, 0, 0, 0, 32, 32, 32, 32, 34,
92, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_115[] = { 8, 0, 0, 0, 60, 66, 12, 48, 66,
60, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_116[] = { 8, 0, 0, 0, 28, 34, 32, 32,
32,124, 32, 32, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_117[] = { 8, 0, 0, 0, 58, 68, 68, 68, 68,
68, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_118[] = { 8, 0, 0, 0, 16, 40, 40, 68, 68,
68, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_119[] = { 8, 0, 0, 0,
68,170,146,146,130,130, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_120[] = { 8, 0, 0, 0, 66, 36, 24, 24, 36,
66, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_121[] = { 8, 0, 60, 66, 2, 58, 70, 66, 66,
66, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_122[] = { 8, 0, 0, 0,126, 32, 16, 8,
4,126, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_123[] = { 8, 0, 0, 0, 14, 16, 16, 8, 48,
8, 16, 16, 14, 0, 0};
+static const GLubyte Fixed8x13_Character_124[] = { 8, 0, 0, 0, 16, 16, 16, 16, 16,
16, 16, 16, 16, 0, 0};
+static const GLubyte Fixed8x13_Character_125[] = { 8, 0, 0, 0,112, 8, 8, 16, 12,
16, 8, 8,112, 0, 0};
+static const GLubyte Fixed8x13_Character_126[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0,
0, 72, 84, 36, 0, 0};
+static const GLubyte Fixed8x13_Character_127[] = { 9, 0, 0, 0, 0, 0, 0,170, 0,
0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_128[] = { 9, 0, 0, 0, 0, 0, 0,170, 0,
0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_129[] = { 9, 0, 0, 0, 0, 0, 0,170, 0,
0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_130[] = { 9, 0, 0, 0, 0, 0, 0,170, 0,
0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_131[] = { 9, 0, 0, 0, 0, 0, 0,170, 0,
0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_132[] = { 9, 0, 0, 0, 0, 0, 0,170, 0,
0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_133[] = { 9, 0, 0, 0, 0, 0, 0,170, 0,
0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_134[] = { 9, 0, 0, 0, 0, 0, 0,170, 0,
0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_135[] = { 9, 0, 0, 0, 0, 0, 0,170, 0,
0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_136[] = { 9, 0, 0, 0, 0, 0, 0,170, 0,
0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_137[] = { 9, 0, 0, 0, 0, 0, 0,170, 0,
0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_138[] = { 9, 0, 0, 0, 0, 0, 0,170, 0,
0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_139[] = { 9, 0, 0, 0, 0, 0, 0,170, 0,
0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_140[] = { 9, 0, 0, 0, 0, 0, 0,170, 0,
0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_141[] = { 9, 0, 0, 0, 0, 0, 0,170, 0,
0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_142[] = { 9, 0, 0, 0, 0, 0, 0,170, 0,
0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_143[] = { 9, 0, 0, 0, 0, 0, 0,170, 0,
0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_144[] = { 9, 0, 0, 0, 0, 0, 0,170, 0,
0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_145[] = { 9, 0, 0, 0, 0, 0, 0,170, 0,
0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_146[] = { 9, 0, 0, 0, 0, 0, 0,170, 0,
0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_147[] = { 9, 0, 0, 0, 0, 0, 0,170, 0,
0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_148[] = { 9, 0, 0, 0, 0, 0, 0,170, 0,
0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_149[] = { 9, 0, 0, 0, 0, 0, 0,170, 0,
0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_150[] = { 9, 0, 0, 0, 0, 0, 0,170, 0,
0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_151[] = { 9, 0, 0, 0, 0, 0, 0,170, 0,
0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_152[] = { 9, 0, 0, 0, 0, 0, 0,170, 0,
0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_153[] = { 9, 0, 0, 0, 0, 0, 0,170, 0,
0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_154[] = { 9, 0, 0, 0, 0, 0, 0,170, 0,
0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_155[] = { 9, 0, 0, 0, 0, 0, 0,170, 0,
0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_156[] = { 9, 0, 0, 0, 0, 0, 0,170, 0,
0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_157[] = { 9, 0, 0, 0, 0, 0, 0,170, 0,
0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_158[] = { 9, 0, 0, 0, 0, 0, 0,170, 0,
0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_159[] = { 9, 0, 0, 0, 0, 0, 0,170, 0,
0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_160[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_161[] = { 8, 0, 0, 0, 16, 16, 16, 16, 16,
16, 16, 0, 16, 0, 0};
+static const GLubyte Fixed8x13_Character_162[] = { 8, 0, 0, 0, 0, 16, 56, 84, 80,
80, 84, 56, 16, 0, 0};
+static const GLubyte Fixed8x13_Character_163[] = { 8, 0, 0, 0,220, 98, 32, 32,
32,112, 32, 34, 28, 0, 0};
+static const GLubyte Fixed8x13_Character_164[] = { 8, 0, 0, 0, 0, 66, 60, 36, 36,
60, 66, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_165[] = { 8, 0, 0, 0, 16, 16,124, 16,124,
40, 68,130,130, 0, 0};
+static const GLubyte Fixed8x13_Character_166[] = { 8, 0, 0, 0, 16, 16, 16, 16, 0,
16, 16, 16, 16, 0, 0};
+static const GLubyte Fixed8x13_Character_167[] = { 8, 0, 0, 0, 24, 36, 4, 24, 36,
36, 24, 32, 36, 24, 0};
+static const GLubyte Fixed8x13_Character_168[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0,108, 0, 0};
+static const GLubyte Fixed8x13_Character_169[] = { 8, 0, 0, 0, 0, 56,
68,146,170,162,170,146, 68, 56, 0};
+static const GLubyte Fixed8x13_Character_170[] = { 8, 0, 0, 0, 0, 0,124, 0, 60,
68, 60, 4, 56, 0, 0};
+static const GLubyte Fixed8x13_Character_171[] = { 8, 0, 0, 0, 0, 18, 36, 72,144,
72, 36, 18, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_172[] = { 8, 0, 0, 0, 0, 2, 2, 2,126,
0, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_173[] = { 8, 0, 0, 0, 0, 0, 0, 0, 60,
0, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_174[] = { 8, 0, 0, 0, 0, 56,
68,170,178,170,170,146, 68, 56, 0};
+static const GLubyte Fixed8x13_Character_175[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0,126, 0, 0};
+static const GLubyte Fixed8x13_Character_176[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0,
24, 36, 36, 24, 0, 0};
+static const GLubyte Fixed8x13_Character_177[] = { 8, 0, 0, 0, 0,124, 0, 16,
16,124, 16, 16, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_178[] = { 8, 0, 0, 0, 0, 0, 0, 0,120,
64, 48, 8, 72, 48, 0};
+static const GLubyte Fixed8x13_Character_179[] = { 8, 0, 0, 0, 0, 0, 0, 0, 48,
72, 8, 16, 72, 48, 0};
+static const GLubyte Fixed8x13_Character_180[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 16, 8, 0};
+static const GLubyte Fixed8x13_Character_181[] = { 8, 0, 0, 64, 90,102, 66, 66, 66,
66, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_182[] = { 8, 0, 0, 0, 20, 20, 20, 20,
52,116,116,116, 62, 0, 0};
+static const GLubyte Fixed8x13_Character_183[] = { 8, 0, 0, 0, 0, 0, 0, 0, 24,
0, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_184[] = { 8, 0, 24, 8, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_185[] = { 8, 0, 0, 0, 0, 0, 0, 0,112,
32, 32, 32, 96, 32, 0};
+static const GLubyte Fixed8x13_Character_186[] = { 8, 0, 0, 0, 0, 0, 0,120, 0,
48, 72, 72, 48, 0, 0};
+static const GLubyte Fixed8x13_Character_187[] = { 8, 0, 0, 0, 0,144, 72, 36, 18,
36, 72,144, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_188[] = { 8, 0, 0, 0, 6, 26, 18, 10,230,
66, 64, 64,192, 64, 0};
+static const GLubyte Fixed8x13_Character_189[] = { 8, 0, 0, 0, 30, 16, 12, 2,242,
76, 64, 64,192, 64, 0};
+static const GLubyte Fixed8x13_Character_190[] = { 8, 0, 0, 0, 6, 26, 18,
10,102,146, 16, 32,144, 96, 0};
+static const GLubyte Fixed8x13_Character_191[] = { 8, 0, 0, 0, 60, 66, 66, 64, 32,
16, 16, 0, 16, 0, 0};
+static const GLubyte Fixed8x13_Character_192[] = { 8, 0, 0, 0, 66, 66,126, 66, 66,
36, 24, 0, 8, 16, 0};
+static const GLubyte Fixed8x13_Character_193[] = { 8, 0, 0, 0, 66, 66,126, 66, 66,
36, 24, 0, 16, 8, 0};
+static const GLubyte Fixed8x13_Character_194[] = { 8, 0, 0, 0, 66, 66,126, 66, 66,
36, 24, 0, 36, 24, 0};
+static const GLubyte Fixed8x13_Character_195[] = { 8, 0, 0, 0, 66, 66,126, 66, 66,
36, 24, 0, 76, 50, 0};
+static const GLubyte Fixed8x13_Character_196[] = { 8, 0, 0, 0, 66, 66,126, 66, 66,
36, 24, 0, 36, 36, 0};
+static const GLubyte Fixed8x13_Character_197[] = { 8, 0, 0, 0, 66, 66,126, 66, 66,
36, 24, 24, 36, 24, 0};
+static const GLubyte Fixed8x13_Character_198[] = { 8, 0, 0,
0,158,144,144,240,156,144,144,144,110, 0, 0};
+static const GLubyte Fixed8x13_Character_199[] = { 8, 0, 16, 8, 60, 66, 64, 64, 64,
64, 64, 66, 60, 0, 0};
+static const GLubyte Fixed8x13_Character_200[] = { 8, 0, 0, 0,126, 64, 64,120, 64,
64,126, 0, 8, 16, 0};
+static const GLubyte Fixed8x13_Character_201[] = { 8, 0, 0, 0,126, 64, 64,120, 64,
64,126, 0, 16, 8, 0};
+static const GLubyte Fixed8x13_Character_202[] = { 8, 0, 0, 0,126, 64, 64,120, 64,
64,126, 0, 36, 24, 0};
+static const GLubyte Fixed8x13_Character_203[] = { 8, 0, 0, 0,126, 64, 64,120, 64,
64,126, 0, 36, 36, 0};
+static const GLubyte Fixed8x13_Character_204[] = { 8, 0, 0, 0,124, 16, 16, 16, 16,
16,124, 0, 16, 32, 0};
+static const GLubyte Fixed8x13_Character_205[] = { 8, 0, 0, 0,124, 16, 16, 16, 16,
16,124, 0, 16, 8, 0};
+static const GLubyte Fixed8x13_Character_206[] = { 8, 0, 0, 0,124, 16, 16, 16, 16,
16,124, 0, 36, 24, 0};
+static const GLubyte Fixed8x13_Character_207[] = { 8, 0, 0, 0,124, 16, 16, 16, 16,
16,124, 0, 40, 40, 0};
+static const GLubyte Fixed8x13_Character_208[] = { 8, 0, 0, 0,120, 68, 66, 66,226,
66, 66, 68,120, 0, 0};
+static const GLubyte Fixed8x13_Character_209[] = { 8, 0, 0,
0,130,134,138,146,162,194,130, 0,152,100, 0};
+static const GLubyte Fixed8x13_Character_210[] = { 8, 0, 0,
0,124,130,130,130,130,130,124, 0, 16, 32, 0};
+static const GLubyte Fixed8x13_Character_211[] = { 8, 0, 0,
0,124,130,130,130,130,130,124, 0, 16, 8, 0};
+static const GLubyte Fixed8x13_Character_212[] = { 8, 0, 0,
0,124,130,130,130,130,130,124, 0, 36, 24, 0};
+static const GLubyte Fixed8x13_Character_213[] = { 8, 0, 0,
0,124,130,130,130,130,130,124, 0,152,100, 0};
+static const GLubyte Fixed8x13_Character_214[] = { 8, 0, 0,
0,124,130,130,130,130,130,124, 0, 40, 40, 0};
+static const GLubyte Fixed8x13_Character_215[] = { 8, 0, 0, 0, 0, 66, 36, 24, 24,
36, 66, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_216[] = { 8, 0, 0, 64, 60, 98, 82, 82, 82,
74, 74, 70, 60, 2, 0};
+static const GLubyte Fixed8x13_Character_217[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66,
66, 66, 0, 8, 16, 0};
+static const GLubyte Fixed8x13_Character_218[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66,
66, 66, 0, 16, 8, 0};
+static const GLubyte Fixed8x13_Character_219[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66,
66, 66, 0, 36, 24, 0};
+static const GLubyte Fixed8x13_Character_220[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66,
66, 66, 0, 36, 36, 0};
+static const GLubyte Fixed8x13_Character_221[] = { 8, 0, 0, 0, 16, 16, 16, 16, 40,
68, 68, 0, 16, 8, 0};
+static const GLubyte Fixed8x13_Character_222[] = { 8, 0, 0, 0, 64, 64, 64,124, 66,
66, 66,124, 64, 0, 0};
+static const GLubyte Fixed8x13_Character_223[] = { 8, 0, 0, 0, 92, 66, 66, 76, 80,
72, 68, 68, 56, 0, 0};
+static const GLubyte Fixed8x13_Character_224[] = { 8, 0, 0, 0, 58, 70, 66, 62, 2,
60, 0, 0, 8, 16, 0};
+static const GLubyte Fixed8x13_Character_225[] = { 8, 0, 0, 0, 58, 70, 66, 62, 2,
60, 0, 0, 8, 4, 0};
+static const GLubyte Fixed8x13_Character_226[] = { 8, 0, 0, 0, 58, 70, 66, 62, 2,
60, 0, 0, 36, 24, 0};
+static const GLubyte Fixed8x13_Character_227[] = { 8, 0, 0, 0, 58, 70, 66, 62, 2,
60, 0, 0, 76, 50, 0};
+static const GLubyte Fixed8x13_Character_228[] = { 8, 0, 0, 0, 58, 70, 66, 62, 2,
60, 0, 0, 36, 36, 0};
+static const GLubyte Fixed8x13_Character_229[] = { 8, 0, 0, 0, 58, 70, 66, 62, 2,
60, 0, 24, 36, 24, 0};
+static const GLubyte Fixed8x13_Character_230[] = { 8, 0, 0, 0,108,146,144,124,
18,108, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_231[] = { 8, 0, 16, 8, 60, 66, 64, 64, 66,
60, 0, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_232[] = { 8, 0, 0, 0, 60, 66, 64,126, 66,
60, 0, 0, 8, 16, 0};
+static const GLubyte Fixed8x13_Character_233[] = { 8, 0, 0, 0, 60, 66, 64,126, 66,
60, 0, 0, 16, 8, 0};
+static const GLubyte Fixed8x13_Character_234[] = { 8, 0, 0, 0, 60, 66, 64,126, 66,
60, 0, 0, 36, 24, 0};
+static const GLubyte Fixed8x13_Character_235[] = { 8, 0, 0, 0, 60, 66, 64,126, 66,
60, 0, 0, 36, 36, 0};
+static const GLubyte Fixed8x13_Character_236[] = { 8, 0, 0, 0,124, 16, 16, 16, 16,
48, 0, 0, 16, 32, 0};
+static const GLubyte Fixed8x13_Character_237[] = { 8, 0, 0, 0,124, 16, 16, 16, 16,
48, 0, 0, 32, 16, 0};
+static const GLubyte Fixed8x13_Character_238[] = { 8, 0, 0, 0,124, 16, 16, 16, 16,
48, 0, 0, 72, 48, 0};
+static const GLubyte Fixed8x13_Character_239[] = { 8, 0, 0, 0,124, 16, 16, 16, 16,
48, 0, 0, 40, 40, 0};
+static const GLubyte Fixed8x13_Character_240[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66,
60, 4, 40, 24, 36, 0};
+static const GLubyte Fixed8x13_Character_241[] = { 8, 0, 0, 0, 66, 66, 66, 66, 98,
92, 0, 0, 76, 50, 0};
+static const GLubyte Fixed8x13_Character_242[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66,
60, 0, 0, 16, 32, 0};
+static const GLubyte Fixed8x13_Character_243[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66,
60, 0, 0, 16, 8, 0};
+static const GLubyte Fixed8x13_Character_244[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66,
60, 0, 0, 36, 24, 0};
+static const GLubyte Fixed8x13_Character_245[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66,
60, 0, 0, 76, 50, 0};
+static const GLubyte Fixed8x13_Character_246[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66,
60, 0, 0, 36, 36, 0};
+static const GLubyte Fixed8x13_Character_247[] = { 8, 0, 0, 0, 0, 16, 16, 0,124,
0, 16, 16, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_248[] = { 8, 0, 0, 64, 60, 98, 82, 74, 70,
60, 2, 0, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_249[] = { 8, 0, 0, 0, 58, 68, 68, 68, 68,
68, 0, 0, 16, 32, 0};
+static const GLubyte Fixed8x13_Character_250[] = { 8, 0, 0, 0, 58, 68, 68, 68, 68,
68, 0, 0, 16, 8, 0};
+static const GLubyte Fixed8x13_Character_251[] = { 8, 0, 0, 0, 58, 68, 68, 68, 68,
68, 0, 0, 36, 24, 0};
+static const GLubyte Fixed8x13_Character_252[] = { 8, 0, 0, 0, 58, 68, 68, 68, 68,
68, 0, 0, 40, 40, 0};
+static const GLubyte Fixed8x13_Character_253[] = { 8, 0, 60, 66, 2, 58, 70, 66, 66,
66, 0, 0, 16, 8, 0};
+static const GLubyte Fixed8x13_Character_254[] = { 8, 0, 64, 64, 92, 98, 66, 66, 98,
92, 64, 64, 0, 0, 0};
+static const GLubyte Fixed8x13_Character_255[] = { 8, 0, 60, 66, 2, 58, 70, 66, 66,
66, 0, 0, 36, 36, 0};
+
+/* The font characters mapping: */
+static const GLubyte* Fixed8x13_Character_Map[] =
{Fixed8x13_Character_000,Fixed8x13_Character_001,Fixed8x13_Character_002,Fixed8x13_Character_003,Fixed8x13_Character_004,Fixed8x13_Character_005,Fixed8x13_Character_006,Fixed8x13_Character_007,Fixed8x13_Character_008,Fixed8x13_Character_009,Fixed8x13_Character_010,Fixed8x13_Character_011,Fixed8x13_Character_012,Fixed8x13_Character_013,Fixed8x13_Character_014,Fixed8x13_Character_015,
+
Fixed8x13_Character_016,Fixed8x13_Character_017,Fixed8x13_Character_018,Fixed8x13_Character_019,Fixed8x13_Character_020,Fixed8x13_Character_021,Fixed8x13_Character_022,Fixed8x13_Character_023,Fixed8x13_Character_024,Fixed8x13_Character_025,Fixed8x13_Character_026,Fixed8x13_Character_027,Fixed8x13_Character_028,Fixed8x13_Character_029,Fixed8x13_Character_030,Fixed8x13_Character_031,
+
Fixed8x13_Character_032,Fixed8x13_Character_033,Fixed8x13_Character_034,Fixed8x13_Character_035,Fixed8x13_Character_036,Fixed8x13_Character_037,Fixed8x13_Character_038,Fixed8x13_Character_039,Fixed8x13_Character_040,Fixed8x13_Character_041,Fixed8x13_Character_042,Fixed8x13_Character_043,Fixed8x13_Character_044,Fixed8x13_Character_045,Fixed8x13_Character_046,Fixed8x13_Character_047,
+
Fixed8x13_Character_048,Fixed8x13_Character_049,Fixed8x13_Character_050,Fixed8x13_Character_051,Fixed8x13_Character_052,Fixed8x13_Character_053,Fixed8x13_Character_054,Fixed8x13_Character_055,Fixed8x13_Character_056,Fixed8x13_Character_057,Fixed8x13_Character_058,Fixed8x13_Character_059,Fixed8x13_Character_060,Fixed8x13_Character_061,Fixed8x13_Character_062,Fixed8x13_Character_063,
+
Fixed8x13_Character_064,Fixed8x13_Character_065,Fixed8x13_Character_066,Fixed8x13_Character_067,Fixed8x13_Character_068,Fixed8x13_Character_069,Fixed8x13_Character_070,Fixed8x13_Character_071,Fixed8x13_Character_072,Fixed8x13_Character_073,Fixed8x13_Character_074,Fixed8x13_Character_075,Fixed8x13_Character_076,Fixed8x13_Character_077,Fixed8x13_Character_078,Fixed8x13_Character_079,
+
Fixed8x13_Character_080,Fixed8x13_Character_081,Fixed8x13_Character_082,Fixed8x13_Character_083,Fixed8x13_Character_084,Fixed8x13_Character_085,Fixed8x13_Character_086,Fixed8x13_Character_087,Fixed8x13_Character_088,Fixed8x13_Character_089,Fixed8x13_Character_090,Fixed8x13_Character_091,Fixed8x13_Character_092,Fixed8x13_Character_093,Fixed8x13_Character_094,Fixed8x13_Character_095,
+
Fixed8x13_Character_096,Fixed8x13_Character_097,Fixed8x13_Character_098,Fixed8x13_Character_099,Fixed8x13_Character_100,Fixed8x13_Character_101,Fixed8x13_Character_102,Fixed8x13_Character_103,Fixed8x13_Character_104,Fixed8x13_Character_105,Fixed8x13_Character_106,Fixed8x13_Character_107,Fixed8x13_Character_108,Fixed8x13_Character_109,Fixed8x13_Character_110,Fixed8x13_Character_111,
+
Fixed8x13_Character_112,Fixed8x13_Character_113,Fixed8x13_Character_114,Fixed8x13_Character_115,Fixed8x13_Character_116,Fixed8x13_Character_117,Fixed8x13_Character_118,Fixed8x13_Character_119,Fixed8x13_Character_120,Fixed8x13_Character_121,Fixed8x13_Character_122,Fixed8x13_Character_123,Fixed8x13_Character_124,Fixed8x13_Character_125,Fixed8x13_Character_126,Fixed8x13_Character_032,
+
Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,
+
Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,
+
Fixed8x13_Character_160,Fixed8x13_Character_161,Fixed8x13_Character_162,Fixed8x13_Character_163,Fixed8x13_Character_164,Fixed8x13_Character_165,Fixed8x13_Character_166,Fixed8x13_Character_167,Fixed8x13_Character_168,Fixed8x13_Character_169,Fixed8x13_Character_170,Fixed8x13_Character_171,Fixed8x13_Character_172,Fixed8x13_Character_173,Fixed8x13_Character_174,Fixed8x13_Character_175,
+
Fixed8x13_Character_176,Fixed8x13_Character_177,Fixed8x13_Character_178,Fixed8x13_Character_179,Fixed8x13_Character_180,Fixed8x13_Character_181,Fixed8x13_Character_182,Fixed8x13_Character_183,Fixed8x13_Character_184,Fixed8x13_Character_185,Fixed8x13_Character_186,Fixed8x13_Character_187,Fixed8x13_Character_188,Fixed8x13_Character_189,Fixed8x13_Character_190,Fixed8x13_Character_191,
+
Fixed8x13_Character_192,Fixed8x13_Character_193,Fixed8x13_Character_194,Fixed8x13_Character_195,Fixed8x13_Character_196,Fixed8x13_Character_197,Fixed8x13_Character_198,Fixed8x13_Character_199,Fixed8x13_Character_200,Fixed8x13_Character_201,Fixed8x13_Character_202,Fixed8x13_Character_203,Fixed8x13_Character_204,Fixed8x13_Character_205,Fixed8x13_Character_206,Fixed8x13_Character_207,
+
Fixed8x13_Character_208,Fixed8x13_Character_209,Fixed8x13_Character_210,Fixed8x13_Character_211,Fixed8x13_Character_212,Fixed8x13_Character_213,Fixed8x13_Character_214,Fixed8x13_Character_215,Fixed8x13_Character_216,Fixed8x13_Character_217,Fixed8x13_Character_218,Fixed8x13_Character_219,Fixed8x13_Character_220,Fixed8x13_Character_221,Fixed8x13_Character_222,Fixed8x13_Character_223,
+
Fixed8x13_Character_224,Fixed8x13_Character_225,Fixed8x13_Character_226,Fixed8x13_Character_227,Fixed8x13_Character_228,Fixed8x13_Character_229,Fixed8x13_Character_230,Fixed8x13_Character_231,Fixed8x13_Character_232,Fixed8x13_Character_233,Fixed8x13_Character_234,Fixed8x13_Character_235,Fixed8x13_Character_236,Fixed8x13_Character_237,Fixed8x13_Character_238,Fixed8x13_Character_239,
+
Fixed8x13_Character_240,Fixed8x13_Character_241,Fixed8x13_Character_242,Fixed8x13_Character_243,Fixed8x13_Character_244,Fixed8x13_Character_245,Fixed8x13_Character_246,Fixed8x13_Character_247,Fixed8x13_Character_248,Fixed8x13_Character_249,Fixed8x13_Character_250,Fixed8x13_Character_251,Fixed8x13_Character_252,Fixed8x13_Character_253,Fixed8x13_Character_254,Fixed8x13_Character_255,NULL};
+
+/* The font structure: */
+const SFG_Font fgFontFixed8x13 = {
"-misc-fixed-medium-r-normal--13-120-75-75-C-80-iso8859-1", 256, 14,
Fixed8x13_Character_Map, 0, 3 };
+
+static const GLubyte Fixed9x15_Character_000[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_001[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
8, 0, 28, 0, 62, 0,127, 0,255,128,127, 0, 62, 0, 28, 0, 8, 0, 0, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_002[] = { 9, 0, 0,170,128, 85, 0,170,128,
85, 0,170,128, 85, 0,170,128, 85, 0,170,128, 85, 0,170,128, 85, 0,170,128, 85,
0,170,128};
+static const GLubyte Fixed9x15_Character_003[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
4, 0, 4, 0, 4, 0, 4, 0, 31, 0, 0, 0, 72, 0, 72, 0,120, 0, 72, 0, 72, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_004[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
8, 0, 8, 0, 8, 0, 14, 0, 72, 0, 79, 0, 64, 0,112, 0, 64, 0,120, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_005[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
9, 0, 9, 0, 14, 0, 9, 0, 14, 0, 0, 0, 56, 0, 64, 0, 64, 0, 64, 0, 56, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_006[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
8, 0, 8, 0, 14, 0, 8, 0, 15, 0, 0, 0,120, 0, 64, 0, 64, 0, 64, 0, 64, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_007[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 18, 0, 18, 0, 12, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_008[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,127, 0, 0, 0, 8, 0, 8, 0, 8, 0,127, 0, 8, 0, 8, 0, 8, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_009[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
15, 0, 8, 0, 8, 0, 8, 0, 8, 0, 0, 0, 68, 0, 76, 0, 84, 0,100, 0, 68, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_010[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
4, 0, 4, 0, 4, 0, 4, 0, 31, 0, 0, 0, 16, 0, 40, 0, 40, 0, 68, 0, 68, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_011[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,248, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8,
0};
+static const GLubyte Fixed9x15_Character_012[] = { 9, 0, 0, 8, 0, 8, 0, 8, 0,
8, 0, 8, 0, 8, 0, 8, 0,248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_013[] = { 9, 0, 0, 8, 0, 8, 0, 8, 0,
8, 0, 8, 0, 8, 0, 8, 0, 15,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_014[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 15,128, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8,
0};
+static const GLubyte Fixed9x15_Character_015[] = { 9, 0, 0, 8, 0, 8, 0, 8, 0,
8, 0, 8, 0, 8, 0, 8, 0,255,128, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8,
0};
+static const GLubyte Fixed9x15_Character_016[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0,255,128};
+static const GLubyte Fixed9x15_Character_017[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,128, 0, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_018[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,255,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_019[] = { 9, 0, 0, 0, 0, 0, 0, 0,
0,255,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_020[] = { 9, 0, 0,255,128, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_021[] = { 9, 0, 0, 8, 0, 8, 0, 8, 0,
8, 0, 8, 0, 8, 0, 8, 0, 15,128, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8,
0};
+static const GLubyte Fixed9x15_Character_022[] = { 9, 0, 0, 8, 0, 8, 0, 8, 0,
8, 0, 8, 0, 8, 0, 8, 0,248, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8,
0};
+static const GLubyte Fixed9x15_Character_023[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,255,128, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8,
0};
+static const GLubyte Fixed9x15_Character_024[] = { 9, 0, 0, 8, 0, 8, 0, 8, 0,
8, 0, 8, 0, 8, 0, 8, 0,255,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_025[] = { 9, 0, 0, 8, 0, 8, 0, 8, 0,
8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8,
0};
+static const GLubyte Fixed9x15_Character_026[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,127, 0, 0, 0, 3, 0, 28, 0, 96, 0, 28, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_027[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,127, 0, 0, 0, 96, 0, 28, 0, 3, 0, 28, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_028[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
34, 0, 34, 0, 34, 0, 34, 0, 34, 0, 34, 0,127, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_029[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 16, 0, 16, 0,127, 0, 8, 0,127, 0, 4, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_030[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
46, 0, 81, 0, 48, 0, 16, 0, 16, 0,124, 0, 16, 0, 16, 0, 17, 0, 14, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_031[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_032[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_033[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
8, 0, 8, 0, 0, 0, 0, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_034[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 18, 0, 18, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_035[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 36, 0, 36, 0,126, 0, 36, 0, 36, 0,126, 0, 36, 0, 36, 0, 0, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_036[] = { 9, 0, 0, 0, 0, 0, 0, 8, 0,
62, 0, 73, 0, 9, 0, 9, 0, 10, 0, 28, 0, 40, 0, 72, 0, 73, 0, 62, 0, 8, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_037[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
66, 0, 37, 0, 37, 0, 18, 0, 8, 0, 8, 0, 36, 0, 82, 0, 82, 0, 33, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_038[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
49, 0, 74, 0, 68, 0, 74, 0, 49, 0, 48, 0, 72, 0, 72, 0, 72, 0, 48, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_039[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 8, 0, 4, 0, 6, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_040[] = { 9, 0, 0, 0, 0, 0, 0, 4, 0,
8, 0, 8, 0, 16, 0, 16, 0, 16, 0, 16, 0, 16, 0, 16, 0, 8, 0, 8, 0, 4, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_041[] = { 9, 0, 0, 0, 0, 0, 0, 16, 0,
8, 0, 8, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 8, 0, 8, 0, 16, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_042[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 8, 0, 73, 0, 42, 0, 28, 0, 42, 0, 73, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_043[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 8, 0, 8, 0, 8, 0,127, 0, 8, 0, 8, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_044[] = { 9, 0, 0, 8, 0, 4, 0, 4, 0,
12, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_045[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_046[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
12, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_047[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
64, 0, 32, 0, 32, 0, 16, 0, 8, 0, 8, 0, 4, 0, 2, 0, 2, 0, 1, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_048[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
28, 0, 34, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 34, 0, 28, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_049[] = { 9, 0, 0, 0, 0, 0, 0, 0,
0,127, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 72, 0, 40, 0, 24, 0, 8, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_050[] = { 9, 0, 0, 0, 0, 0, 0, 0,
0,127, 0, 64, 0, 32, 0, 16, 0, 8, 0, 4, 0, 2, 0, 65, 0, 65, 0, 62, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_051[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
62, 0, 65, 0, 1, 0, 1, 0, 1, 0, 14, 0, 4, 0, 2, 0, 1, 0,127, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_052[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
2, 0, 2, 0, 2, 0,127, 0, 66, 0, 34, 0, 18, 0, 10, 0, 6, 0, 2, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_053[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
62, 0, 65, 0, 1, 0, 1, 0, 1, 0, 97, 0, 94, 0, 64, 0, 64, 0,127, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_054[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
62, 0, 65, 0, 65, 0, 65, 0, 97, 0, 94, 0, 64, 0, 64, 0, 32, 0, 30, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_055[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
32, 0, 32, 0, 16, 0, 16, 0, 8, 0, 4, 0, 2, 0, 1, 0, 1, 0,127, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_056[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
28, 0, 34, 0, 65, 0, 65, 0, 34, 0, 28, 0, 34, 0, 65, 0, 34, 0, 28, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_057[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
60, 0, 2, 0, 1, 0, 1, 0, 61, 0, 67, 0, 65, 0, 65, 0, 65, 0, 62, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_058[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
12, 0, 12, 0, 0, 0, 0, 0, 0, 0, 12, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_059[] = { 9, 0, 0, 8, 0, 4, 0, 4, 0,
12, 0, 12, 0, 0, 0, 0, 0, 0, 0, 12, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_060[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
2, 0, 4, 0, 8, 0, 16, 0, 32, 0, 32, 0, 16, 0, 8, 0, 4, 0, 2, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_061[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0,127, 0, 0, 0, 0, 0,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_062[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
32, 0, 16, 0, 8, 0, 4, 0, 2, 0, 2, 0, 4, 0, 8, 0, 16, 0, 32, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_063[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
8, 0, 0, 0, 8, 0, 8, 0, 4, 0, 2, 0, 1, 0, 65, 0, 65, 0, 62, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_064[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
62, 0, 64, 0, 64, 0, 77, 0, 83, 0, 81, 0, 79, 0, 65, 0, 65, 0, 62, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_065[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
65, 0, 65, 0, 65, 0,127, 0, 65, 0, 65, 0, 65, 0, 34, 0, 20, 0, 8, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_066[] = { 9, 0, 0, 0, 0, 0, 0, 0,
0,126, 0, 33, 0, 33, 0, 33, 0, 33, 0,126, 0, 33, 0, 33, 0, 33, 0,126, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_067[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
62, 0, 65, 0, 64, 0, 64, 0, 64, 0, 64, 0, 64, 0, 64, 0, 65, 0, 62, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_068[] = { 9, 0, 0, 0, 0, 0, 0, 0,
0,126, 0, 33, 0, 33, 0, 33, 0, 33, 0, 33, 0, 33, 0, 33, 0, 33, 0,126, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_069[] = { 9, 0, 0, 0, 0, 0, 0, 0,
0,127, 0, 32, 0, 32, 0, 32, 0, 32, 0, 60, 0, 32, 0, 32, 0, 32, 0,127, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_070[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 60, 0, 32, 0, 32, 0, 32, 0,127, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_071[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
62, 0, 65, 0, 65, 0, 65, 0, 71, 0, 64, 0, 64, 0, 64, 0, 65, 0, 62, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_072[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
65, 0, 65, 0, 65, 0, 65, 0, 65, 0,127, 0, 65, 0, 65, 0, 65, 0, 65, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_073[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
62, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 62, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_074[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
60, 0, 66, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 15,128, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_075[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
65, 0, 66, 0, 68, 0, 72, 0, 80, 0,112, 0, 72, 0, 68, 0, 66, 0, 65, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_076[] = { 9, 0, 0, 0, 0, 0, 0, 0,
0,127, 0, 64, 0, 64, 0, 64, 0, 64, 0, 64, 0, 64, 0, 64, 0, 64, 0, 64, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_077[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
65, 0, 65, 0, 65, 0, 73, 0, 73, 0, 85, 0, 85, 0, 99, 0, 65, 0, 65, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_078[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
65, 0, 65, 0, 65, 0, 67, 0, 69, 0, 73, 0, 81, 0, 97, 0, 65, 0, 65, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_079[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
62, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 62, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_080[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
64, 0, 64, 0, 64, 0, 64, 0, 64, 0,126, 0, 65, 0, 65, 0, 65, 0,126, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_081[] = { 9, 0, 0, 0, 0, 3, 0, 4, 0,
62, 0, 73, 0, 81, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 62, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_082[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
65, 0, 65, 0, 66, 0, 68, 0, 72, 0,126, 0, 65, 0, 65, 0, 65, 0,126, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_083[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
62, 0, 65, 0, 65, 0, 1, 0, 6, 0, 56, 0, 64, 0, 65, 0, 65, 0, 62, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_084[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0,127, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_085[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
62, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_086[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
8, 0, 20, 0, 20, 0, 20, 0, 34, 0, 34, 0, 34, 0, 65, 0, 65, 0, 65, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_087[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
34, 0, 85, 0, 73, 0, 73, 0, 73, 0, 73, 0, 65, 0, 65, 0, 65, 0, 65, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_088[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
65, 0, 65, 0, 34, 0, 20, 0, 8, 0, 8, 0, 20, 0, 34, 0, 65, 0, 65, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_089[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 20, 0, 34, 0, 65, 0, 65, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_090[] = { 9, 0, 0, 0, 0, 0, 0, 0,
0,127, 0, 64, 0, 64, 0, 32, 0, 16, 0, 8, 0, 4, 0, 2, 0, 1, 0,127, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_091[] = { 9, 0, 0, 0, 0, 0, 0, 30, 0,
16, 0, 16, 0, 16, 0, 16, 0, 16, 0, 16, 0, 16, 0, 16, 0, 16, 0, 16, 0, 30, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_092[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 2, 0, 2, 0, 4, 0, 8, 0, 8, 0, 16, 0, 32, 0, 32, 0, 64, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_093[] = { 9, 0, 0, 0, 0, 0, 0, 60, 0,
4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 60, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_094[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 34, 0, 20, 0, 8, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_095[] = { 9, 0, 0, 0, 0, 0, 0,255, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_096[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 8, 0, 16, 0, 48, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_097[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
61, 0, 67, 0, 65, 0, 63, 0, 1, 0, 1, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_098[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
94, 0, 97, 0, 65, 0, 65, 0, 65, 0, 97, 0, 94, 0, 64, 0, 64, 0, 64, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_099[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
62, 0, 65, 0, 64, 0, 64, 0, 64, 0, 65, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_100[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
61, 0, 67, 0, 65, 0, 65, 0, 65, 0, 67, 0, 61, 0, 1, 0, 1, 0, 1, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_101[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
62, 0, 64, 0, 64, 0,127, 0, 65, 0, 65, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_102[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
16, 0, 16, 0, 16, 0, 16, 0,124, 0, 16, 0, 16, 0, 17, 0, 17, 0, 14, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_103[] = { 9, 0, 0, 62, 0, 65, 0, 65, 0,
62, 0, 64, 0, 60, 0, 66, 0, 66, 0, 66, 0, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_104[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 97, 0, 94, 0, 64, 0, 64, 0, 64, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_105[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
62, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 56, 0, 0, 0, 0, 0, 24, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_106[] = { 9, 0, 0, 60, 0, 66, 0, 66, 0,
66, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 14, 0, 0, 0, 0, 0, 6, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_107[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
65, 0, 70, 0, 88, 0, 96, 0, 88, 0, 70, 0, 65, 0, 64, 0, 64, 0, 64, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_108[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
62, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 56, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_109[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
65, 0, 73, 0, 73, 0, 73, 0, 73, 0, 73, 0,118, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_110[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 97, 0, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_111[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
62, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_112[] = { 9, 0, 0, 64, 0, 64, 0, 64, 0,
94, 0, 97, 0, 65, 0, 65, 0, 65, 0, 97, 0, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_113[] = { 9, 0, 0, 1, 0, 1, 0, 1, 0,
61, 0, 67, 0, 65, 0, 65, 0, 65, 0, 67, 0, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_114[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
32, 0, 32, 0, 32, 0, 32, 0, 33, 0, 49, 0, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_115[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
62, 0, 65, 0, 1, 0, 62, 0, 64, 0, 65, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_116[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
14, 0, 17, 0, 16, 0, 16, 0, 16, 0, 16, 0,126, 0, 16, 0, 16, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_117[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
61, 0, 66, 0, 66, 0, 66, 0, 66, 0, 66, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_118[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
8, 0, 20, 0, 20, 0, 34, 0, 34, 0, 65, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_119[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
34, 0, 85, 0, 73, 0, 73, 0, 73, 0, 65, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_120[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
65, 0, 34, 0, 20, 0, 8, 0, 20, 0, 34, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_121[] = { 9, 0, 0, 60, 0, 66, 0, 2, 0,
58, 0, 70, 0, 66, 0, 66, 0, 66, 0, 66, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_122[] = { 9, 0, 0, 0, 0, 0, 0, 0,
0,127, 0, 32, 0, 16, 0, 8, 0, 4, 0, 2, 0,127, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_123[] = { 9, 0, 0, 0, 0, 0, 0, 7, 0,
8, 0, 8, 0, 8, 0, 4, 0, 24, 0, 24, 0, 4, 0, 8, 0, 8, 0, 8, 0, 7, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_124[] = { 9, 0, 0, 0, 0, 0, 0, 8, 0,
8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_125[] = { 9, 0, 0, 0, 0, 0, 0,112, 0,
8, 0, 8, 0, 8, 0, 16, 0, 12, 0, 12, 0, 16, 0, 8, 0, 8, 0, 8, 0,112, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_126[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 0, 73, 0, 49, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_127[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_128[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_129[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_130[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_131[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_132[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_133[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_134[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_135[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_136[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_137[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_138[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_139[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_140[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_141[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_142[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_143[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_144[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_145[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_146[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_147[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_148[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_149[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_150[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_151[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_152[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_153[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_154[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_155[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_156[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_157[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_158[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_159[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_160[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_161[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 0, 0, 0, 0, 8, 0, 8, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_162[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
32, 0, 60, 0, 82, 0, 80, 0, 72, 0, 74, 0, 60, 0, 4, 0, 0, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_163[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
46, 0, 81, 0, 48, 0, 16, 0, 16, 0,124, 0, 16, 0, 16, 0, 17, 0, 14, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_164[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 65, 0, 62, 0, 34, 0, 34, 0, 62, 0, 65, 0, 0, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_165[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
8, 0, 8, 0, 8, 0, 62, 0, 8, 0, 62, 0, 20, 0, 34, 0, 65, 0, 65, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_166[] = { 9, 0, 0, 0, 0, 0, 0, 8, 0,
8, 0, 8, 0, 8, 0, 8, 0, 0, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_167[] = { 9, 0, 0, 0, 0, 0, 0, 24, 0,
36, 0, 4, 0, 24, 0, 36, 0, 36, 0, 36, 0, 24, 0, 32, 0, 36, 0, 24, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_168[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 34, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_169[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 60, 0, 66, 0,153, 0,165, 0,161, 0,165, 0,153, 0, 66, 0, 60, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_170[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,124, 0, 0, 0, 60, 0, 72, 0, 56, 0, 72, 0, 48, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_171[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 9, 0, 18, 0, 36, 0, 72, 0, 72, 0, 36, 0, 18, 0, 9, 0, 0, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_172[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 2, 0, 2, 0, 2, 0,126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_173[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_174[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 60, 0, 66, 0,165, 0,169, 0,185, 0,165, 0,185, 0, 66, 0, 60, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_175[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_176[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 18, 0, 18, 0, 12, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_177[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,127, 0, 0, 0, 8, 0, 8, 0, 8, 0,127, 0, 8, 0, 8, 0, 8, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_178[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,120, 0, 64, 0, 48, 0, 8, 0, 72, 0, 48, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_179[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 72, 0, 8, 0, 16, 0, 72, 0, 48, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_180[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 8, 0, 4, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_181[] = { 9, 0, 0, 0, 0, 64, 0, 64, 0,
93, 0, 99, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_182[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 61, 0, 69, 0, 69, 0, 69, 0, 63, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_183[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_184[] = { 9, 0, 0, 24, 0, 36, 0, 12, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_185[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,112, 0, 32, 0, 32, 0, 32, 0, 96, 0, 32, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_186[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,124, 0, 0, 0, 56, 0, 68, 0, 68, 0, 56, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_187[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 72, 0, 36, 0, 18, 0, 9, 0, 9, 0, 18, 0, 36, 0, 72, 0, 0, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_188[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
3, 0, 13, 0, 9, 0, 5, 0,115, 0, 33, 0, 32, 0, 32, 0, 96, 0, 32, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_189[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
15, 0, 8, 0, 6, 0, 1, 0,121, 0, 38, 0, 32, 0, 32, 0, 96, 0, 32, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_190[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
3, 0, 13, 0, 9, 0, 5, 0, 51, 0, 73, 0, 8, 0, 16, 0, 72, 0, 48, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_191[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
62, 0, 65, 0, 65, 0, 64, 0, 32, 0, 16, 0, 8, 0, 8, 0, 0, 0, 8, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_192[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
65, 0, 65, 0, 65, 0,127, 0, 65, 0, 65, 0, 34, 0, 28, 0, 0, 0, 8, 0, 16, 0,
32, 0};
+static const GLubyte Fixed9x15_Character_193[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
65, 0, 65, 0, 65, 0,127, 0, 65, 0, 65, 0, 34, 0, 28, 0, 0, 0, 8, 0, 4, 0,
2, 0};
+static const GLubyte Fixed9x15_Character_194[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
65, 0, 65, 0, 65, 0,127, 0, 65, 0, 65, 0, 34, 0, 28, 0, 0, 0, 34, 0, 20, 0,
8, 0};
+static const GLubyte Fixed9x15_Character_195[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
65, 0, 65, 0, 65, 0,127, 0, 65, 0, 65, 0, 34, 0, 28, 0, 0, 0, 78, 0, 49, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_196[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
65, 0, 65, 0, 65, 0,127, 0, 65, 0, 65, 0, 34, 0, 28, 0, 0, 0, 34, 0, 34, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_197[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
65, 0, 65, 0, 65, 0,127, 0, 65, 0, 65, 0, 34, 0, 20, 0, 28, 0, 34, 0, 28, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_198[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
79, 0, 72, 0, 72, 0, 72, 0,126, 0, 72, 0, 72, 0, 72, 0, 72, 0, 55, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_199[] = { 9, 0, 0, 24, 0, 36, 0, 12, 0,
62, 0, 65, 0, 64, 0, 64, 0, 64, 0, 64, 0, 64, 0, 64, 0, 65, 0, 62, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_200[] = { 9, 0, 0, 0, 0, 0, 0, 0,
0,127, 0, 32, 0, 32, 0, 32, 0, 60, 0, 32, 0, 32, 0,127, 0, 0, 0, 8, 0, 16, 0,
32, 0};
+static const GLubyte Fixed9x15_Character_201[] = { 9, 0, 0, 0, 0, 0, 0, 0,
0,127, 0, 32, 0, 32, 0, 32, 0, 60, 0, 32, 0, 32, 0,127, 0, 0, 0, 8, 0, 4, 0,
2, 0};
+static const GLubyte Fixed9x15_Character_202[] = { 9, 0, 0, 0, 0, 0, 0, 0,
0,127, 0, 32, 0, 32, 0, 32, 0, 60, 0, 32, 0, 32, 0,127, 0, 0, 0, 34, 0, 20, 0,
8, 0};
+static const GLubyte Fixed9x15_Character_203[] = { 9, 0, 0, 0, 0, 0, 0, 0,
0,127, 0, 32, 0, 32, 0, 32, 0, 60, 0, 32, 0, 32, 0,127, 0, 0, 0, 34, 0, 34, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_204[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
62, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 62, 0, 0, 0, 8, 0, 16, 0,
32, 0};
+static const GLubyte Fixed9x15_Character_205[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
62, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 62, 0, 0, 0, 8, 0, 4, 0,
2, 0};
+static const GLubyte Fixed9x15_Character_206[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
62, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 62, 0, 0, 0, 34, 0, 20, 0,
8, 0};
+static const GLubyte Fixed9x15_Character_207[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
62, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 62, 0, 0, 0, 34, 0, 34, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_208[] = { 9, 0, 0, 0, 0, 0, 0, 0,
0,124, 0, 33, 0, 33, 0, 33, 0, 33, 0,225, 0, 33, 0, 33, 0, 33, 0,124, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_209[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
65, 0, 67, 0, 69, 0, 73, 0, 73, 0, 81, 0, 97, 0, 65, 0, 0, 0, 78, 0, 49, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_210[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
62, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 62, 0, 0, 0, 8, 0, 16, 0,
32, 0};
+static const GLubyte Fixed9x15_Character_211[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
62, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 62, 0, 0, 0, 8, 0, 4, 0,
2, 0};
+static const GLubyte Fixed9x15_Character_212[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
62, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 62, 0, 0, 0, 34, 0, 20, 0,
8, 0};
+static const GLubyte Fixed9x15_Character_213[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
62, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 62, 0, 0, 0, 78, 0, 49, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_214[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
62, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 62, 0, 0, 0, 34, 0, 34, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_215[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 65, 0, 34, 0, 20, 0, 8, 0, 20, 0, 34, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_216[] = { 9, 0, 0, 0, 0, 0, 0, 64, 0,
62, 0, 97, 0, 81, 0, 81, 0, 73, 0, 73, 0, 69, 0, 69, 0, 67, 0, 62, 0, 1, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_217[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
62, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 0, 0, 8, 0, 16, 0,
32, 0};
+static const GLubyte Fixed9x15_Character_218[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
62, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 0, 0, 8, 0, 4, 0,
2, 0};
+static const GLubyte Fixed9x15_Character_219[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
62, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 0, 0, 34, 0, 20, 0,
8, 0};
+static const GLubyte Fixed9x15_Character_220[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
62, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 0, 0, 34, 0, 34, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_221[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
8, 0, 8, 0, 8, 0, 8, 0, 20, 0, 34, 0, 65, 0, 65, 0, 0, 0, 8, 0, 4, 0, 2,
0};
+static const GLubyte Fixed9x15_Character_222[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
64, 0, 64, 0, 64, 0,126, 0, 65, 0, 65, 0, 65, 0,126, 0, 64, 0, 64, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_223[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
44, 0, 34, 0, 34, 0, 34, 0, 36, 0,104, 0, 36, 0, 34, 0, 34, 0, 28, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_224[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
61, 0, 67, 0, 65, 0, 63, 0, 1, 0, 1, 0, 62, 0, 0, 0, 4, 0, 8, 0, 16, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_225[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
61, 0, 67, 0, 65, 0, 63, 0, 1, 0, 1, 0, 62, 0, 0, 0, 8, 0, 4, 0, 2, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_226[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
61, 0, 67, 0, 65, 0, 63, 0, 1, 0, 1, 0, 62, 0, 0, 0, 34, 0, 20, 0, 8, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_227[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
61, 0, 67, 0, 65, 0, 63, 0, 1, 0, 1, 0, 62, 0, 0, 0, 38, 0, 25, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_228[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
61, 0, 67, 0, 65, 0, 63, 0, 1, 0, 1, 0, 62, 0, 0, 0, 34, 0, 34, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_229[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
61, 0, 67, 0, 65, 0, 63, 0, 1, 0, 1, 0, 62, 0, 0, 0, 12, 0, 18, 0, 12, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_230[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
55, 0, 73, 0, 72, 0, 62, 0, 9, 0, 73, 0, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_231[] = { 9, 0, 0, 24, 0, 36, 0, 12, 0,
62, 0, 65, 0, 64, 0, 64, 0, 64, 0, 65, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_232[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
62, 0, 64, 0, 64, 0,127, 0, 65, 0, 65, 0, 62, 0, 0, 0, 8, 0, 16, 0, 32, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_233[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
62, 0, 64, 0, 64, 0,127, 0, 65, 0, 65, 0, 62, 0, 0, 0, 8, 0, 4, 0, 2, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_234[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
62, 0, 64, 0, 64, 0,127, 0, 65, 0, 65, 0, 62, 0, 0, 0, 34, 0, 20, 0, 8, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_235[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
62, 0, 64, 0, 64, 0,127, 0, 65, 0, 65, 0, 62, 0, 0, 0, 34, 0, 34, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_236[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
62, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 56, 0, 0, 0, 8, 0, 16, 0, 32, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_237[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
62, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 56, 0, 0, 0, 16, 0, 8, 0, 4, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_238[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
62, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 56, 0, 0, 0, 68, 0, 40, 0, 16, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_239[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
62, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 56, 0, 0, 0, 36, 0, 36, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_240[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
62, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 62, 0, 4, 0, 40, 0, 24, 0, 36, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_241[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 97, 0, 94, 0, 0, 0, 78, 0, 49, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_242[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
62, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 62, 0, 0, 0, 8, 0, 16, 0, 32, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_243[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
62, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 62, 0, 0, 0, 8, 0, 4, 0, 2, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_244[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
62, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 62, 0, 0, 0, 34, 0, 20, 0, 8, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_245[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
62, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 62, 0, 0, 0, 78, 0, 49, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_246[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
62, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 62, 0, 0, 0, 34, 0, 34, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_247[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
8, 0, 28, 0, 8, 0, 0, 0,127, 0, 0, 0, 8, 0, 28, 0, 8, 0, 0, 0, 0, 0, 0,
0};
+static const GLubyte Fixed9x15_Character_248[] = { 9, 0, 0, 0, 0, 0, 0, 64, 0,
62, 0, 81, 0, 81, 0, 73, 0, 69, 0, 69, 0, 62, 0, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_249[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
61, 0, 66, 0, 66, 0, 66, 0, 66, 0, 66, 0, 66, 0, 0, 0, 8, 0, 16, 0, 32, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_250[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
61, 0, 66, 0, 66, 0, 66, 0, 66, 0, 66, 0, 66, 0, 0, 0, 8, 0, 4, 0, 2, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_251[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
61, 0, 66, 0, 66, 0, 66, 0, 66, 0, 66, 0, 66, 0, 0, 0, 34, 0, 20, 0, 8, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_252[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
61, 0, 66, 0, 66, 0, 66, 0, 66, 0, 66, 0, 66, 0, 0, 0, 36, 0, 36, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_253[] = { 9, 0, 0, 60, 0, 66, 0, 2, 0,
58, 0, 70, 0, 66, 0, 66, 0, 66, 0, 66, 0, 66, 0, 0, 0, 16, 0, 8, 0, 4, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_254[] = { 9, 0, 0, 64, 0, 64, 0, 64, 0,
94, 0, 97, 0, 65, 0, 65, 0, 97, 0, 94, 0, 64, 0, 64, 0, 64, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Fixed9x15_Character_255[] = { 9, 0, 0, 60, 0, 66, 0, 2, 0,
58, 0, 70, 0, 66, 0, 66, 0, 66, 0, 66, 0, 66, 0, 0, 0, 36, 0, 36, 0, 0, 0,
0, 0};
+
+/* The font characters mapping: */
+static const GLubyte* Fixed9x15_Character_Map[] =
{Fixed9x15_Character_000,Fixed9x15_Character_001,Fixed9x15_Character_002,Fixed9x15_Character_003,Fixed9x15_Character_004,Fixed9x15_Character_005,Fixed9x15_Character_006,Fixed9x15_Character_007,Fixed9x15_Character_008,Fixed9x15_Character_009,Fixed9x15_Character_010,Fixed9x15_Character_011,Fixed9x15_Character_012,Fixed9x15_Character_013,Fixed9x15_Character_014,Fixed9x15_Character_015,
+
Fixed9x15_Character_016,Fixed9x15_Character_017,Fixed9x15_Character_018,Fixed9x15_Character_019,Fixed9x15_Character_020,Fixed9x15_Character_021,Fixed9x15_Character_022,Fixed9x15_Character_023,Fixed9x15_Character_024,Fixed9x15_Character_025,Fixed9x15_Character_026,Fixed9x15_Character_027,Fixed9x15_Character_028,Fixed9x15_Character_029,Fixed9x15_Character_030,Fixed9x15_Character_031,
+
Fixed9x15_Character_032,Fixed9x15_Character_033,Fixed9x15_Character_034,Fixed9x15_Character_035,Fixed9x15_Character_036,Fixed9x15_Character_037,Fixed9x15_Character_038,Fixed9x15_Character_039,Fixed9x15_Character_040,Fixed9x15_Character_041,Fixed9x15_Character_042,Fixed9x15_Character_043,Fixed9x15_Character_044,Fixed9x15_Character_045,Fixed9x15_Character_046,Fixed9x15_Character_047,
+
Fixed9x15_Character_048,Fixed9x15_Character_049,Fixed9x15_Character_050,Fixed9x15_Character_051,Fixed9x15_Character_052,Fixed9x15_Character_053,Fixed9x15_Character_054,Fixed9x15_Character_055,Fixed9x15_Character_056,Fixed9x15_Character_057,Fixed9x15_Character_058,Fixed9x15_Character_059,Fixed9x15_Character_060,Fixed9x15_Character_061,Fixed9x15_Character_062,Fixed9x15_Character_063,
+
Fixed9x15_Character_064,Fixed9x15_Character_065,Fixed9x15_Character_066,Fixed9x15_Character_067,Fixed9x15_Character_068,Fixed9x15_Character_069,Fixed9x15_Character_070,Fixed9x15_Character_071,Fixed9x15_Character_072,Fixed9x15_Character_073,Fixed9x15_Character_074,Fixed9x15_Character_075,Fixed9x15_Character_076,Fixed9x15_Character_077,Fixed9x15_Character_078,Fixed9x15_Character_079,
+
Fixed9x15_Character_080,Fixed9x15_Character_081,Fixed9x15_Character_082,Fixed9x15_Character_083,Fixed9x15_Character_084,Fixed9x15_Character_085,Fixed9x15_Character_086,Fixed9x15_Character_087,Fixed9x15_Character_088,Fixed9x15_Character_089,Fixed9x15_Character_090,Fixed9x15_Character_091,Fixed9x15_Character_092,Fixed9x15_Character_093,Fixed9x15_Character_094,Fixed9x15_Character_095,
+
Fixed9x15_Character_096,Fixed9x15_Character_097,Fixed9x15_Character_098,Fixed9x15_Character_099,Fixed9x15_Character_100,Fixed9x15_Character_101,Fixed9x15_Character_102,Fixed9x15_Character_103,Fixed9x15_Character_104,Fixed9x15_Character_105,Fixed9x15_Character_106,Fixed9x15_Character_107,Fixed9x15_Character_108,Fixed9x15_Character_109,Fixed9x15_Character_110,Fixed9x15_Character_111,
+
Fixed9x15_Character_112,Fixed9x15_Character_113,Fixed9x15_Character_114,Fixed9x15_Character_115,Fixed9x15_Character_116,Fixed9x15_Character_117,Fixed9x15_Character_118,Fixed9x15_Character_119,Fixed9x15_Character_120,Fixed9x15_Character_121,Fixed9x15_Character_122,Fixed9x15_Character_123,Fixed9x15_Character_124,Fixed9x15_Character_125,Fixed9x15_Character_126,Fixed9x15_Character_032,
+
Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,
+
Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,
+
Fixed9x15_Character_160,Fixed9x15_Character_161,Fixed9x15_Character_162,Fixed9x15_Character_163,Fixed9x15_Character_164,Fixed9x15_Character_165,Fixed9x15_Character_166,Fixed9x15_Character_167,Fixed9x15_Character_168,Fixed9x15_Character_169,Fixed9x15_Character_170,Fixed9x15_Character_171,Fixed9x15_Character_172,Fixed9x15_Character_173,Fixed9x15_Character_174,Fixed9x15_Character_175,
+
Fixed9x15_Character_176,Fixed9x15_Character_177,Fixed9x15_Character_178,Fixed9x15_Character_179,Fixed9x15_Character_180,Fixed9x15_Character_181,Fixed9x15_Character_182,Fixed9x15_Character_183,Fixed9x15_Character_184,Fixed9x15_Character_185,Fixed9x15_Character_186,Fixed9x15_Character_187,Fixed9x15_Character_188,Fixed9x15_Character_189,Fixed9x15_Character_190,Fixed9x15_Character_191,
+
Fixed9x15_Character_192,Fixed9x15_Character_193,Fixed9x15_Character_194,Fixed9x15_Character_195,Fixed9x15_Character_196,Fixed9x15_Character_197,Fixed9x15_Character_198,Fixed9x15_Character_199,Fixed9x15_Character_200,Fixed9x15_Character_201,Fixed9x15_Character_202,Fixed9x15_Character_203,Fixed9x15_Character_204,Fixed9x15_Character_205,Fixed9x15_Character_206,Fixed9x15_Character_207,
+
Fixed9x15_Character_208,Fixed9x15_Character_209,Fixed9x15_Character_210,Fixed9x15_Character_211,Fixed9x15_Character_212,Fixed9x15_Character_213,Fixed9x15_Character_214,Fixed9x15_Character_215,Fixed9x15_Character_216,Fixed9x15_Character_217,Fixed9x15_Character_218,Fixed9x15_Character_219,Fixed9x15_Character_220,Fixed9x15_Character_221,Fixed9x15_Character_222,Fixed9x15_Character_223,
+
Fixed9x15_Character_224,Fixed9x15_Character_225,Fixed9x15_Character_226,Fixed9x15_Character_227,Fixed9x15_Character_228,Fixed9x15_Character_229,Fixed9x15_Character_230,Fixed9x15_Character_231,Fixed9x15_Character_232,Fixed9x15_Character_233,Fixed9x15_Character_234,Fixed9x15_Character_235,Fixed9x15_Character_236,Fixed9x15_Character_237,Fixed9x15_Character_238,Fixed9x15_Character_239,
+
Fixed9x15_Character_240,Fixed9x15_Character_241,Fixed9x15_Character_242,Fixed9x15_Character_243,Fixed9x15_Character_244,Fixed9x15_Character_245,Fixed9x15_Character_246,Fixed9x15_Character_247,Fixed9x15_Character_248,Fixed9x15_Character_249,Fixed9x15_Character_250,Fixed9x15_Character_251,Fixed9x15_Character_252,Fixed9x15_Character_253,Fixed9x15_Character_254,Fixed9x15_Character_255,NULL};
+
+/* The font structure: */
+const SFG_Font fgFontFixed9x15 = {
"-misc-fixed-medium-r-normal--15-140-75-75-C-90-iso8859-1", 256, 16,
Fixed9x15_Character_Map, 0, 4 };
+
+static const GLubyte Helvetica10_Character_000[] = { 8, 0, 0, 0, 84, 0, 68, 0, 68,
0, 84, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_001[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_002[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_003[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_004[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_005[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_006[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_007[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_008[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_009[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_010[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_011[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_012[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_013[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_014[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_015[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_016[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_017[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_018[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_019[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_020[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_021[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_022[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_023[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_024[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_025[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_026[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_027[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_028[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_029[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_030[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_031[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_032[] = { 3, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_033[] = { 3, 0, 0, 0, 64, 0, 64, 64, 64,
64, 64, 64, 0, 0, 0};
+static const GLubyte Helvetica10_Character_034[] = { 4, 0, 0, 0, 0, 0, 0, 0, 0,
0, 80, 80, 0, 0, 0};
+static const GLubyte Helvetica10_Character_035[] = { 6, 0, 0, 0, 80, 80,248, 40,124,
40, 40, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_036[] = { 6, 0, 0, 32,112,168,
40,112,160,168,112, 32, 0, 0, 0};
+static const GLubyte Helvetica10_Character_037[] = { 9, 0, 0, 0, 0, 0, 0, 38, 0,
41, 0, 22, 0, 16, 0, 8, 0,104, 0,148, 0,100, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_038[] = { 8, 0, 0, 0, 50, 76, 76, 82, 48,
40, 40, 16, 0, 0, 0};
+static const GLubyte Helvetica10_Character_039[] = { 3, 0, 0, 0, 0, 0, 0, 0, 0,
64, 32, 32, 0, 0, 0};
+static const GLubyte Helvetica10_Character_040[] = { 4, 0, 32, 64, 64,128,128,128,128,
64, 64, 32, 0, 0, 0};
+static const GLubyte Helvetica10_Character_041[] = { 4, 0, 64, 32, 32, 16, 16, 16, 16,
32, 32, 64, 0, 0, 0};
+static const GLubyte Helvetica10_Character_042[] = { 4, 0, 0, 0, 0, 0, 0, 0,
0,160, 64,160, 0, 0, 0};
+static const GLubyte Helvetica10_Character_043[] = { 6, 0, 0, 0, 0, 32, 32,248, 32,
32, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_044[] = { 3, 0,128, 64, 64, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_045[] = { 7, 0, 0, 0, 0, 0, 0,124, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_046[] = { 3, 0, 0, 0, 64, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_047[] = { 3, 0, 0, 0,128,128, 64, 64, 64,
64, 32, 32, 0, 0, 0};
+static const GLubyte Helvetica10_Character_048[] = { 6, 0, 0,
0,112,136,136,136,136,136,136,112, 0, 0, 0};
+static const GLubyte Helvetica10_Character_049[] = { 6, 0, 0, 0, 32, 32, 32, 32, 32,
32, 96, 32, 0, 0, 0};
+static const GLubyte Helvetica10_Character_050[] = { 6, 0, 0, 0,248,128, 64, 48, 8,
8,136,112, 0, 0, 0};
+static const GLubyte Helvetica10_Character_051[] = { 6, 0, 0, 0,112,136, 8, 8, 48,
8,136,112, 0, 0, 0};
+static const GLubyte Helvetica10_Character_052[] = { 6, 0, 0, 0, 16, 16,248,144, 80,
80, 48, 16, 0, 0, 0};
+static const GLubyte Helvetica10_Character_053[] = { 6, 0, 0, 0,112,136, 8,
8,240,128,128,248, 0, 0, 0};
+static const GLubyte Helvetica10_Character_054[] = { 6, 0, 0,
0,112,136,136,200,176,128,136,112, 0, 0, 0};
+static const GLubyte Helvetica10_Character_055[] = { 6, 0, 0, 0, 64, 64, 32, 32, 16,
16, 8,248, 0, 0, 0};
+static const GLubyte Helvetica10_Character_056[] = { 6, 0, 0,
0,112,136,136,136,112,136,136,112, 0, 0, 0};
+static const GLubyte Helvetica10_Character_057[] = { 6, 0, 0, 0,112,136,
8,104,152,136,136,112, 0, 0, 0};
+static const GLubyte Helvetica10_Character_058[] = { 3, 0, 0, 0, 64, 0, 0, 0, 0,
64, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_059[] = { 3, 0,128, 64, 64, 0, 0, 0, 0,
64, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_060[] = { 6, 0, 0, 0, 0, 16, 32, 64, 32,
16, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_061[] = { 5, 0, 0, 0, 0, 0,240, 0,240,
0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_062[] = { 6, 0, 0, 0, 0, 64, 32, 16, 32,
64, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_063[] = { 6, 0, 0, 0, 32, 0, 32, 32, 16,
8, 72, 48, 0, 0, 0};
+static const GLubyte Helvetica10_Character_064[] = { 11, 0, 0, 62, 0, 64, 0,155,
0,164,128,164,128,162, 64,146, 64, 77, 64, 32,128, 31, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_065[] = { 7, 0, 0, 0,130,130,124, 68, 40,
40, 16, 16, 0, 0, 0};
+static const GLubyte Helvetica10_Character_066[] = { 7, 0, 0, 0,120, 68, 68, 68,120,
68, 68,120, 0, 0, 0};
+static const GLubyte Helvetica10_Character_067[] = { 8, 0, 0, 0, 60, 66, 64, 64, 64,
64, 66, 60, 0, 0, 0};
+static const GLubyte Helvetica10_Character_068[] = { 8, 0, 0, 0,120, 68, 66, 66, 66,
66, 68,120, 0, 0, 0};
+static const GLubyte Helvetica10_Character_069[] = { 7, 0, 0, 0,124, 64, 64, 64,124,
64, 64,124, 0, 0, 0};
+static const GLubyte Helvetica10_Character_070[] = { 6, 0, 0, 0, 64, 64, 64, 64,120,
64, 64,124, 0, 0, 0};
+static const GLubyte Helvetica10_Character_071[] = { 8, 0, 0, 0, 58, 70, 66, 70, 64,
64, 66, 60, 0, 0, 0};
+static const GLubyte Helvetica10_Character_072[] = { 8, 0, 0, 0, 66, 66, 66, 66,126,
66, 66, 66, 0, 0, 0};
+static const GLubyte Helvetica10_Character_073[] = { 3, 0, 0, 0, 64, 64, 64, 64, 64,
64, 64, 64, 0, 0, 0};
+static const GLubyte Helvetica10_Character_074[] = { 5, 0, 0, 0, 96,144, 16, 16, 16,
16, 16, 16, 0, 0, 0};
+static const GLubyte Helvetica10_Character_075[] = { 7, 0, 0, 0, 68, 68, 72, 72,112,
80, 72, 68, 0, 0, 0};
+static const GLubyte Helvetica10_Character_076[] = { 6, 0, 0, 0,120, 64, 64, 64, 64,
64, 64, 64, 0, 0, 0};
+static const GLubyte Helvetica10_Character_077[] = { 9, 0, 0, 0, 0, 0, 0, 73, 0,
73, 0, 73, 0, 85, 0, 85, 0, 99, 0, 99, 0, 65, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_078[] = { 8, 0, 0, 0, 70, 70, 74, 74, 82,
82, 98, 98, 0, 0, 0};
+static const GLubyte Helvetica10_Character_079[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66,
66, 66, 60, 0, 0, 0};
+static const GLubyte Helvetica10_Character_080[] = { 7, 0, 0, 0, 64, 64, 64, 64,120,
68, 68,120, 0, 0, 0};
+static const GLubyte Helvetica10_Character_081[] = { 8, 0, 0, 1, 62, 70, 74, 66, 66,
66, 66, 60, 0, 0, 0};
+static const GLubyte Helvetica10_Character_082[] = { 7, 0, 0, 0, 68, 68, 68, 68,120,
68, 68,120, 0, 0, 0};
+static const GLubyte Helvetica10_Character_083[] = { 7, 0, 0, 0, 56, 68, 68, 4, 56,
64, 68, 56, 0, 0, 0};
+static const GLubyte Helvetica10_Character_084[] = { 5, 0, 0, 0, 32, 32, 32, 32, 32,
32, 32,248, 0, 0, 0};
+static const GLubyte Helvetica10_Character_085[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66,
66, 66, 66, 0, 0, 0};
+static const GLubyte Helvetica10_Character_086[] = { 7, 0, 0, 0, 16, 40, 40, 68, 68,
68,130,130, 0, 0, 0};
+static const GLubyte Helvetica10_Character_087[] = { 9, 0, 0, 0, 0, 0, 0, 34, 0,
34, 0, 34, 0, 85, 0, 73, 0, 73, 0,136,128,136,128, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_088[] = { 7, 0, 0, 0, 68, 68, 40, 40, 16,
40, 68, 68, 0, 0, 0};
+static const GLubyte Helvetica10_Character_089[] = { 7, 0, 0, 0, 16, 16, 16, 40, 40,
68, 68,130, 0, 0, 0};
+static const GLubyte Helvetica10_Character_090[] = { 7, 0, 0, 0,124, 64, 32, 16, 16,
8, 4,124, 0, 0, 0};
+static const GLubyte Helvetica10_Character_091[] = { 3, 0, 96, 64, 64, 64, 64, 64, 64,
64, 64, 96, 0, 0, 0};
+static const GLubyte Helvetica10_Character_092[] = { 3, 0, 0, 0, 32, 32, 64, 64, 64,
64,128,128, 0, 0, 0};
+static const GLubyte Helvetica10_Character_093[] = { 3, 0,192, 64, 64, 64, 64, 64, 64,
64, 64,192, 0, 0, 0};
+static const GLubyte Helvetica10_Character_094[] = { 6, 0, 0, 0, 0, 0, 0,136, 80,
80, 32, 32, 0, 0, 0};
+static const GLubyte Helvetica10_Character_095[] = { 6, 0,252, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_096[] = { 3, 0, 0, 0, 0, 0, 0, 0, 0,
63, 64, 32, 0, 0, 0};
+static const GLubyte Helvetica10_Character_097[] = { 5, 0, 0, 0,104,144,144,112,
16,224, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_098[] = { 6, 0, 0,
0,176,200,136,136,200,176,128,128, 0, 0, 0};
+static const GLubyte Helvetica10_Character_099[] = { 5, 0, 0, 0, 96,144,128,128,144,
96, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_100[] = { 6, 0, 0,
0,104,152,136,136,152,104, 8, 8, 0, 0, 0};
+static const GLubyte Helvetica10_Character_101[] = { 5, 0, 0, 0, 96,144,128,240,144,
96, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_102[] = { 4, 0, 0, 0, 64, 64, 64, 64,
64,224, 64, 48, 0, 0, 0};
+static const GLubyte Helvetica10_Character_103[] = { 6, 0,112,
8,104,152,136,136,152,104, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_104[] = { 6, 0, 0,
0,136,136,136,136,200,176,128,128, 0, 0, 0};
+static const GLubyte Helvetica10_Character_105[] = { 2, 0, 0,
0,128,128,128,128,128,128, 0,128, 0, 0, 0};
+static const GLubyte Helvetica10_Character_106[] = { 2, 0,
0,128,128,128,128,128,128,128, 0,128, 0, 0, 0};
+static const GLubyte Helvetica10_Character_107[] = { 5, 0, 0,
0,144,144,160,192,160,144,128,128, 0, 0, 0};
+static const GLubyte Helvetica10_Character_108[] = { 2, 0, 0,
0,128,128,128,128,128,128,128,128, 0, 0, 0};
+static const GLubyte Helvetica10_Character_109[] = { 8, 0, 0,
0,146,146,146,146,146,236, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_110[] = { 6, 0, 0,
0,136,136,136,136,200,176, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_111[] = { 6, 0, 0,
0,112,136,136,136,136,112, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_112[] = { 6,
0,128,128,176,200,136,136,200,176, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_113[] = { 6, 0, 8,
8,104,152,136,136,152,104, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_114[] = { 4, 0, 0,
0,128,128,128,128,192,160, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_115[] = { 5, 0, 0, 0, 96,144, 16, 96,144,
96, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_116[] = { 4, 0, 0, 0, 96, 64, 64, 64,
64,224, 64, 64, 0, 0, 0};
+static const GLubyte Helvetica10_Character_117[] = { 5, 0, 0,
0,112,144,144,144,144,144, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_118[] = { 6, 0, 0, 0, 32, 32, 80,
80,136,136, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_119[] = { 8, 0, 0, 0, 40, 40, 84,
84,146,146, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_120[] = { 6, 0, 0, 0,136,136, 80, 32,
80,136, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_121[] = { 5, 0,128, 64, 64,
96,160,160,144,144, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_122[] = { 5, 0, 0, 0,240,128, 64, 32,
16,240, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_123[] = { 3, 0, 32, 64, 64, 64, 64,128, 64,
64, 64, 32, 0, 0, 0};
+static const GLubyte Helvetica10_Character_124[] = { 3, 0, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 0, 0, 0};
+static const GLubyte Helvetica10_Character_125[] = { 3, 0,128, 64, 64, 64, 64, 32, 64,
64, 64,128, 0, 0, 0};
+static const GLubyte Helvetica10_Character_126[] = { 7, 0, 0, 0, 0, 0, 0,152,100,
0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_127[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_128[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_129[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_130[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_131[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_132[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_133[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_134[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_135[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_136[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_137[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_138[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_139[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_140[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_141[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_142[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_143[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_144[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_145[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_146[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_147[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_148[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_149[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_150[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_151[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_152[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_153[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_154[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_155[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_156[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_157[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_158[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_159[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0,
0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_160[] = { 3, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_161[] = { 3, 0, 64, 64, 64, 64, 64, 64, 0,
64, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_162[] = { 6, 0, 0,
64,112,168,160,160,168,112, 16, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_163[] = { 6, 0, 0, 0,176, 72, 64, 64,224,
64, 72, 48, 0, 0, 0};
+static const GLubyte Helvetica10_Character_164[] = { 5, 0, 0, 0, 0,144, 96,144,144,
96,144, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_165[] = { 6, 0, 0, 0, 32,248, 32,248, 80,
80,136,136, 0, 0, 0};
+static const GLubyte Helvetica10_Character_166[] = { 3, 0, 64, 64, 64, 64, 0, 0, 64,
64, 64, 64, 0, 0, 0};
+static const GLubyte Helvetica10_Character_167[] = { 6, 0,112,136,
24,112,200,152,112,192,136,112, 0, 0, 0};
+static const GLubyte Helvetica10_Character_168[] = { 3, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,160, 0, 0, 0};
+static const GLubyte Helvetica10_Character_169[] = { 9, 0, 0, 0, 0, 0, 0, 28, 0,
34, 0, 77, 0, 81, 0, 77, 0, 34, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_170[] = { 4, 0, 0, 0, 0, 0, 0,224,
0,160, 32,224, 0, 0, 0};
+static const GLubyte Helvetica10_Character_171[] = { 6, 0, 0, 0, 40, 80,160, 80, 40,
0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_172[] = { 7, 0, 0, 0, 0, 0, 4, 4,124,
0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_173[] = { 4, 0, 0, 0, 0, 0, 0,224, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_174[] = { 9, 0, 0, 0, 0, 0, 0, 28, 0,
34, 0, 85, 0, 89, 0, 93, 0, 34, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_175[] = { 3, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,224, 0, 0, 0};
+static const GLubyte Helvetica10_Character_176[] = { 4, 0, 0, 0, 0, 0, 0,
96,144,144, 96, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_177[] = { 6, 0, 0, 0,248, 0, 32, 32,248,
32, 32, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_178[] = { 3, 0, 0, 0, 0, 0, 0,224,
64,160, 96, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_179[] = { 3, 0, 0, 0, 0, 0, 0,192, 32,
64,224, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_180[] = { 3, 0, 0, 0, 0, 0, 0, 0, 0,
0,128, 64, 0, 0, 0};
+static const GLubyte Helvetica10_Character_181[] = { 5,
0,128,128,240,144,144,144,144,144, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_182[] = { 6, 0, 40, 40, 40, 40,
40,104,232,232,232,124, 0, 0, 0};
+static const GLubyte Helvetica10_Character_183[] = { 3, 0, 0, 0, 0, 0, 0,192, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_184[] = { 3, 0,192, 64, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_185[] = { 3, 0, 0, 0, 0, 0, 0, 64,
64,192, 64, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_186[] = { 4, 0, 0, 0, 0, 0, 0,224,
0,224,160,224, 0, 0, 0};
+static const GLubyte Helvetica10_Character_187[] = { 6, 0, 0, 0,160, 80, 40, 80,160,
0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_188[] = { 9, 0, 0, 0, 0, 0, 0, 33, 0,
23,128, 19, 0, 9, 0, 72, 0, 68, 0,196, 0, 66, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_189[] = { 9, 0, 0, 0, 0, 0, 0, 39, 0,
18, 0, 21, 0, 11, 0, 72, 0, 68, 0,196, 0, 66, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_190[] = { 9, 0, 0, 0, 0, 0, 0, 33, 0,
23,128, 19, 0, 9, 0,200, 0, 36, 0, 68, 0,226, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_191[] = { 6, 0, 48, 72, 64, 32, 16, 16, 0,
16, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_192[] = { 7, 0, 0, 0,130,130,124, 68, 40,
40, 16, 16, 0, 16, 32};
+static const GLubyte Helvetica10_Character_193[] = { 7, 0, 0, 0,130,130,124, 68, 40,
40, 16, 16, 0, 16, 8};
+static const GLubyte Helvetica10_Character_194[] = { 7, 0, 0, 0,130,130,124, 68, 40,
40, 16, 16, 0, 40, 16};
+static const GLubyte Helvetica10_Character_195[] = { 7, 0, 0, 0,130,130,124, 68, 40,
40, 16, 16, 0, 40, 20};
+static const GLubyte Helvetica10_Character_196[] = { 7, 0, 0, 0,130,130,124, 68, 40,
40, 16, 16, 0, 40, 0};
+static const GLubyte Helvetica10_Character_197[] = { 7, 0, 0, 0,130,130,124, 68, 40,
40, 16, 16, 16, 40, 16};
+static const GLubyte Helvetica10_Character_198[] = { 10, 0, 0, 0, 0, 0,
0,143,128,136, 0,120, 0, 72, 0, 47,128, 40, 0, 24, 0, 31,128, 0, 0, 0, 0, 0,
0};
+static const GLubyte Helvetica10_Character_199[] = { 8, 0, 24, 8, 60, 66, 64, 64, 64,
64, 66, 60, 0, 0, 0};
+static const GLubyte Helvetica10_Character_200[] = { 7, 0, 0, 0,124, 64, 64, 64,124,
64, 64,124, 0, 16, 32};
+static const GLubyte Helvetica10_Character_201[] = { 7, 0, 0, 0,124, 64, 64, 64,124,
64, 64,124, 0, 16, 8};
+static const GLubyte Helvetica10_Character_202[] = { 7, 0, 0, 0,124, 64, 64,124, 64,
64, 64,124, 0, 40, 16};
+static const GLubyte Helvetica10_Character_203[] = { 7, 0, 0, 0,124, 64, 64, 64,124,
64, 64,124, 0, 40, 0};
+static const GLubyte Helvetica10_Character_204[] = { 3, 0, 0, 0, 64, 64, 64, 64, 64,
64, 64, 64, 0, 64,128};
+static const GLubyte Helvetica10_Character_205[] = { 3, 0, 0, 0, 64, 64, 64, 64, 64,
64, 64, 64, 0, 64, 32};
+static const GLubyte Helvetica10_Character_206[] = { 3, 0, 0, 0, 64, 64, 64, 64, 64,
64, 64, 64, 0,160, 64};
+static const GLubyte Helvetica10_Character_207[] = { 3, 0, 0, 0, 64, 64, 64, 64, 64,
64, 64, 64, 0,160, 0};
+static const GLubyte Helvetica10_Character_208[] = { 8, 0, 0, 0,120, 68, 66, 66,242,
66, 68,120, 0, 0, 0};
+static const GLubyte Helvetica10_Character_209[] = { 8, 0, 0, 0, 70, 70, 74, 74, 82,
82, 98, 98, 0, 40, 20};
+static const GLubyte Helvetica10_Character_210[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66,
66, 66, 60, 0, 8, 16};
+static const GLubyte Helvetica10_Character_211[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66,
66, 66, 60, 0, 8, 4};
+static const GLubyte Helvetica10_Character_212[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66,
66, 66, 60, 0, 20, 8};
+static const GLubyte Helvetica10_Character_213[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66,
66, 66, 60, 0, 40, 20};
+static const GLubyte Helvetica10_Character_214[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66,
66, 66, 60, 0, 36, 0};
+static const GLubyte Helvetica10_Character_215[] = { 6, 0, 0, 0, 0,136, 80, 32,
80,136, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_216[] = { 8, 0, 0, 64, 60, 98, 82, 82, 74,
74, 70, 60, 2, 0, 0};
+static const GLubyte Helvetica10_Character_217[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66,
66, 66, 66, 0, 8, 16};
+static const GLubyte Helvetica10_Character_218[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66,
66, 66, 66, 0, 16, 8};
+static const GLubyte Helvetica10_Character_219[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66,
66, 66, 66, 0, 20, 8};
+static const GLubyte Helvetica10_Character_220[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66,
66, 66, 66, 0, 36, 0};
+static const GLubyte Helvetica10_Character_221[] = { 7, 0, 0, 0, 16, 16, 16, 40, 40,
68, 68,130, 0, 16, 8};
+static const GLubyte Helvetica10_Character_222[] = { 7, 0, 0, 0, 64, 64,120, 68,
68,120, 64, 64, 0, 0, 0};
+static const GLubyte Helvetica10_Character_223[] = { 5, 0, 0,
0,160,144,144,144,160,144,144, 96, 0, 0, 0};
+static const GLubyte Helvetica10_Character_224[] = { 5, 0, 0, 0,104,144,144,112,
16,224, 0, 32, 64, 0, 0};
+static const GLubyte Helvetica10_Character_225[] = { 5, 0, 0, 0,104,144,144,112,
16,224, 0, 32, 16, 0, 0};
+static const GLubyte Helvetica10_Character_226[] = { 5, 0, 0, 0,104,144,144,112,
16,224, 0, 80, 32, 0, 0};
+static const GLubyte Helvetica10_Character_227[] = { 5, 0, 0, 0,104,144,144,112,
16,224, 0,160, 80, 0, 0};
+static const GLubyte Helvetica10_Character_228[] = { 5, 0, 0, 0,104,144,144,112,
16,224, 0, 80, 0, 0, 0};
+static const GLubyte Helvetica10_Character_229[] = { 5, 0, 0, 0,104,144,144,112,
16,224, 32, 80, 32, 0, 0};
+static const GLubyte Helvetica10_Character_230[] = { 8, 0, 0, 0,108,146,144,126,
18,236, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_231[] = { 5, 0, 96, 32, 96,144,128,128,144,
96, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_232[] = { 5, 0, 0, 0, 96,144,128,240,144,
96, 0, 32, 64, 0, 0};
+static const GLubyte Helvetica10_Character_233[] = { 5, 0, 0, 0, 96,144,128,240,144,
96, 0, 64, 32, 0, 0};
+static const GLubyte Helvetica10_Character_234[] = { 5, 0, 0, 0, 96,144,128,240,144,
96, 0, 80, 32, 0, 0};
+static const GLubyte Helvetica10_Character_235[] = { 5, 0, 0, 0, 96,144,128,240,144,
96, 0, 80, 0, 0, 0};
+static const GLubyte Helvetica10_Character_236[] = { 2, 0, 0,
0,128,128,128,128,128,128, 0,128, 0, 0, 0};
+static const GLubyte Helvetica10_Character_237[] = { 2, 0, 0,
0,128,128,128,128,128,128, 0,128, 64, 0, 0};
+static const GLubyte Helvetica10_Character_238[] = { 2, 0, 0,
0,128,128,128,128,128,128, 0, 64,128, 0, 0};
+static const GLubyte Helvetica10_Character_239[] = { 2, 0, 0, 0, 64, 64, 64, 64, 64,
64, 0,160, 0, 0, 0};
+static const GLubyte Helvetica10_Character_240[] = { 6, 0, 0,
0,112,136,136,136,136,120,144, 96, 80, 0, 0};
+static const GLubyte Helvetica10_Character_241[] = { 5, 0, 0,
0,144,144,144,144,144,224, 0,160, 80, 0, 0};
+static const GLubyte Helvetica10_Character_242[] = { 6, 0, 0,
0,112,136,136,136,136,112, 0, 32, 64, 0, 0};
+static const GLubyte Helvetica10_Character_243[] = { 6, 0, 0,
0,112,136,136,136,136,112, 0, 32, 16, 0, 0};
+static const GLubyte Helvetica10_Character_244[] = { 6, 0, 0,
0,112,136,136,136,136,112, 0, 80, 32, 0, 0};
+static const GLubyte Helvetica10_Character_245[] = { 6, 0, 0,
0,112,136,136,136,136,112, 0, 80, 40, 0, 0};
+static const GLubyte Helvetica10_Character_246[] = { 6, 0, 0,
0,112,136,136,136,136,112, 0, 80, 0, 0, 0};
+static const GLubyte Helvetica10_Character_247[] = { 6, 0, 0, 0, 0, 32, 0,248, 0,
32, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_248[] = { 6, 0, 0,
0,112,136,200,168,152,116, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica10_Character_249[] = { 5, 0, 0,
0,112,144,144,144,144,144, 0, 32, 64, 0, 0};
+static const GLubyte Helvetica10_Character_250[] = { 5, 0, 0,
0,112,144,144,144,144,144, 0, 64, 32, 0, 0};
+static const GLubyte Helvetica10_Character_251[] = { 5, 0, 0,
0,112,144,144,144,144,144, 0, 80, 32, 0, 0};
+static const GLubyte Helvetica10_Character_252[] = { 5, 0, 0,
0,112,144,144,144,144,144, 0, 80, 0, 0, 0};
+static const GLubyte Helvetica10_Character_253[] = { 5, 0,128, 64, 64,
96,160,160,144,144, 0, 32, 16, 0, 0};
+static const GLubyte Helvetica10_Character_254[] = { 6,
0,128,128,176,200,136,136,200,176,128,128, 0, 0, 0};
+static const GLubyte Helvetica10_Character_255[] = { 5, 0,128, 64, 64,
96,160,160,144,144, 0, 80, 0, 0, 0};
+
+/* The font characters mapping: */
+static const GLubyte* Helvetica10_Character_Map[] =
{Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,
+
Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,
+
Helvetica10_Character_032,Helvetica10_Character_033,Helvetica10_Character_034,Helvetica10_Character_035,Helvetica10_Character_036,Helvetica10_Character_037,Helvetica10_Character_038,Helvetica10_Character_039,Helvetica10_Character_040,Helvetica10_Character_041,Helvetica10_Character_042,Helvetica10_Character_043,Helvetica10_Character_044,Helvetica10_Character_045,Helvetica10_Character_046,Helvetica10_Character_047,
+
Helvetica10_Character_048,Helvetica10_Character_049,Helvetica10_Character_050,Helvetica10_Character_051,Helvetica10_Character_052,Helvetica10_Character_053,Helvetica10_Character_054,Helvetica10_Character_055,Helvetica10_Character_056,Helvetica10_Character_057,Helvetica10_Character_058,Helvetica10_Character_059,Helvetica10_Character_060,Helvetica10_Character_061,Helvetica10_Character_062,Helvetica10_Character_063,
+
Helvetica10_Character_064,Helvetica10_Character_065,Helvetica10_Character_066,Helvetica10_Character_067,Helvetica10_Character_068,Helvetica10_Character_069,Helvetica10_Character_070,Helvetica10_Character_071,Helvetica10_Character_072,Helvetica10_Character_073,Helvetica10_Character_074,Helvetica10_Character_075,Helvetica10_Character_076,Helvetica10_Character_077,Helvetica10_Character_078,Helvetica10_Character_079,
+
Helvetica10_Character_080,Helvetica10_Character_081,Helvetica10_Character_082,Helvetica10_Character_083,Helvetica10_Character_084,Helvetica10_Character_085,Helvetica10_Character_086,Helvetica10_Character_087,Helvetica10_Character_088,Helvetica10_Character_089,Helvetica10_Character_090,Helvetica10_Character_091,Helvetica10_Character_092,Helvetica10_Character_093,Helvetica10_Character_094,Helvetica10_Character_095,
+
Helvetica10_Character_096,Helvetica10_Character_097,Helvetica10_Character_098,Helvetica10_Character_099,Helvetica10_Character_100,Helvetica10_Character_101,Helvetica10_Character_102,Helvetica10_Character_103,Helvetica10_Character_104,Helvetica10_Character_105,Helvetica10_Character_106,Helvetica10_Character_107,Helvetica10_Character_108,Helvetica10_Character_109,Helvetica10_Character_110,Helvetica10_Character_111,
+
Helvetica10_Character_112,Helvetica10_Character_113,Helvetica10_Character_114,Helvetica10_Character_115,Helvetica10_Character_116,Helvetica10_Character_117,Helvetica10_Character_118,Helvetica10_Character_119,Helvetica10_Character_120,Helvetica10_Character_121,Helvetica10_Character_122,Helvetica10_Character_123,Helvetica10_Character_124,Helvetica10_Character_125,Helvetica10_Character_126,Helvetica10_Character_032,
+
Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,
+
Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,
+
Helvetica10_Character_160,Helvetica10_Character_161,Helvetica10_Character_162,Helvetica10_Character_163,Helvetica10_Character_164,Helvetica10_Character_165,Helvetica10_Character_166,Helvetica10_Character_167,Helvetica10_Character_168,Helvetica10_Character_169,Helvetica10_Character_170,Helvetica10_Character_171,Helvetica10_Character_172,Helvetica10_Character_173,Helvetica10_Character_174,Helvetica10_Character_175,
+
Helvetica10_Character_176,Helvetica10_Character_177,Helvetica10_Character_178,Helvetica10_Character_179,Helvetica10_Character_180,Helvetica10_Character_181,Helvetica10_Character_182,Helvetica10_Character_183,Helvetica10_Character_184,Helvetica10_Character_185,Helvetica10_Character_186,Helvetica10_Character_187,Helvetica10_Character_188,Helvetica10_Character_189,Helvetica10_Character_190,Helvetica10_Character_191,
+
Helvetica10_Character_192,Helvetica10_Character_193,Helvetica10_Character_194,Helvetica10_Character_195,Helvetica10_Character_196,Helvetica10_Character_197,Helvetica10_Character_198,Helvetica10_Character_199,Helvetica10_Character_200,Helvetica10_Character_201,Helvetica10_Character_202,Helvetica10_Character_203,Helvetica10_Character_204,Helvetica10_Character_205,Helvetica10_Character_206,Helvetica10_Character_207,
+
Helvetica10_Character_208,Helvetica10_Character_209,Helvetica10_Character_210,Helvetica10_Character_211,Helvetica10_Character_212,Helvetica10_Character_213,Helvetica10_Character_214,Helvetica10_Character_215,Helvetica10_Character_216,Helvetica10_Character_217,Helvetica10_Character_218,Helvetica10_Character_219,Helvetica10_Character_220,Helvetica10_Character_221,Helvetica10_Character_222,Helvetica10_Character_223,
+
Helvetica10_Character_224,Helvetica10_Character_225,Helvetica10_Character_226,Helvetica10_Character_227,Helvetica10_Character_228,Helvetica10_Character_229,Helvetica10_Character_230,Helvetica10_Character_231,Helvetica10_Character_232,Helvetica10_Character_233,Helvetica10_Character_234,Helvetica10_Character_235,Helvetica10_Character_236,Helvetica10_Character_237,Helvetica10_Character_238,Helvetica10_Character_239,
+
Helvetica10_Character_240,Helvetica10_Character_241,Helvetica10_Character_242,Helvetica10_Character_243,Helvetica10_Character_244,Helvetica10_Character_245,Helvetica10_Character_246,Helvetica10_Character_247,Helvetica10_Character_248,Helvetica10_Character_249,Helvetica10_Character_250,Helvetica10_Character_251,Helvetica10_Character_252,Helvetica10_Character_253,Helvetica10_Character_254,Helvetica10_Character_255,NULL};
+
+/* The font structure: */
+const SFG_Font fgFontHelvetica10 = {
"-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1", 256, 14,
Helvetica10_Character_Map, 0, 3 };
+
+static const GLubyte Helvetica12_Character_000[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_001[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_002[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_003[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_004[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_005[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_006[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_007[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_008[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_009[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_010[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_011[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_012[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_013[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_014[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_015[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_016[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_017[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_018[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_019[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_020[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_021[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_022[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_023[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_024[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_025[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_026[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_027[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_028[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_029[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_030[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_031[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_032[] = { 4, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_033[] = { 3, 0, 0, 0, 0, 64, 0, 64, 64,
64, 64, 64, 64, 64, 0, 0, 0};
+static const GLubyte Helvetica12_Character_034[] = { 5, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 80, 80, 80, 0, 0, 0};
+static const GLubyte Helvetica12_Character_035[] = { 7, 0, 0, 0, 0, 80, 80, 80,252,
40,252, 40, 40, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_036[] = { 7, 0, 0, 0, 16, 56, 84, 84, 20,
56, 80, 84, 56, 16, 0, 0, 0};
+static const GLubyte Helvetica12_Character_037[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0,
17,128, 10, 64, 10, 64, 9,128, 4, 0, 52, 0, 74, 0, 74, 0, 49, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_038[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
57, 0, 70, 0, 66, 0, 69, 0, 40, 0, 24, 0, 36, 0, 36, 0, 24, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_039[] = { 3, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 64, 32, 96, 0, 0, 0};
+static const GLubyte Helvetica12_Character_040[] = { 4, 0, 16, 32, 32, 64, 64, 64, 64,
64, 64, 32, 32, 16, 0, 0, 0};
+static const GLubyte Helvetica12_Character_041[] = { 4, 0,128, 64, 64, 32, 32, 32, 32,
32, 32, 64, 64,128, 0, 0, 0};
+static const GLubyte Helvetica12_Character_042[] = { 5, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 80, 32, 80, 0, 0, 0};
+static const GLubyte Helvetica12_Character_043[] = { 7, 0, 0, 0, 0, 0, 16, 16,124,
16, 16, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_044[] = { 4, 0, 0, 64, 32, 32, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_045[] = { 8, 0, 0, 0, 0, 0, 0, 0,124,
0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_046[] = { 3, 0, 0, 0, 0, 64, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_047[] = { 4, 0, 0, 0, 0,128,128, 64, 64,
64, 32, 32, 16, 16, 0, 0, 0};
+static const GLubyte Helvetica12_Character_048[] = { 7, 0, 0, 0, 0, 56, 68, 68, 68,
68, 68, 68, 68, 56, 0, 0, 0};
+static const GLubyte Helvetica12_Character_049[] = { 7, 0, 0, 0, 0, 16, 16, 16, 16,
16, 16, 16,112, 16, 0, 0, 0};
+static const GLubyte Helvetica12_Character_050[] = { 7, 0, 0, 0, 0,124, 64, 64, 32,
16, 8, 4, 68, 56, 0, 0, 0};
+static const GLubyte Helvetica12_Character_051[] = { 7, 0, 0, 0, 0, 56, 68, 68, 4,
4, 24, 4, 68, 56, 0, 0, 0};
+static const GLubyte Helvetica12_Character_052[] = { 7, 0, 0, 0, 0, 8, 8,252,136,
72, 40, 40, 24, 8, 0, 0, 0};
+static const GLubyte Helvetica12_Character_053[] = { 7, 0, 0, 0, 0, 56, 68, 68, 4,
4,120, 64, 64,124, 0, 0, 0};
+static const GLubyte Helvetica12_Character_054[] = { 7, 0, 0, 0, 0, 56, 68, 68,
68,100, 88, 64, 68, 56, 0, 0, 0};
+static const GLubyte Helvetica12_Character_055[] = { 7, 0, 0, 0, 0, 32, 32, 16, 16,
16, 8, 8, 4,124, 0, 0, 0};
+static const GLubyte Helvetica12_Character_056[] = { 7, 0, 0, 0, 0, 56, 68, 68, 68,
68, 56, 68, 68, 56, 0, 0, 0};
+static const GLubyte Helvetica12_Character_057[] = { 7, 0, 0, 0, 0, 56, 68, 4, 4,
60, 68, 68, 68, 56, 0, 0, 0};
+static const GLubyte Helvetica12_Character_058[] = { 3, 0, 0, 0, 0, 64, 0, 0, 0,
0, 64, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_059[] = { 3, 0, 0,128, 64, 64, 0, 0, 0,
0, 64, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_060[] = { 7, 0, 0, 0, 0, 0, 12, 48,192,
48, 12, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_061[] = { 7, 0, 0, 0, 0, 0, 0,124,
0,124, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_062[] = { 7, 0, 0, 0, 0, 0, 96, 24, 6,
24, 96, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_063[] = { 7, 0, 0, 0, 0, 16, 0, 16, 16,
8, 8, 68, 68, 56, 0, 0, 0};
+static const GLubyte Helvetica12_Character_064[] = { 12, 0, 0, 0, 0, 0, 0, 31, 0,
32, 0, 77,128, 83, 64, 81, 32, 81, 32, 73, 32, 38,160, 48, 64, 15,128, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_065[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
65, 0, 65, 0, 65, 0, 62, 0, 34, 0, 34, 0, 20, 0, 20, 0, 8, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_066[] = { 8, 0, 0, 0, 0,124, 66, 66,
66,124, 66, 66, 66,124, 0, 0, 0};
+static const GLubyte Helvetica12_Character_067[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
30, 0, 33, 0, 64, 0, 64, 0, 64, 0, 64, 0, 64, 0, 33, 0, 30, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_068[] = { 9, 0, 0, 0, 0, 0, 0, 0,
0,124, 0, 66, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 66, 0,124, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_069[] = { 8, 0, 0, 0, 0,126, 64, 64,
64,126, 64, 64, 64,126, 0, 0, 0};
+static const GLubyte Helvetica12_Character_070[] = { 8, 0, 0, 0, 0, 64, 64, 64,
64,124, 64, 64, 64,126, 0, 0, 0};
+static const GLubyte Helvetica12_Character_071[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
29, 0, 35, 0, 65, 0, 65, 0, 71, 0, 64, 0, 64, 0, 33, 0, 30, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_072[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
65, 0, 65, 0, 65, 0, 65, 0,127, 0, 65, 0, 65, 0, 65, 0, 65, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_073[] = { 3, 0, 0, 0, 0, 64, 64, 64, 64,
64, 64, 64, 64, 64, 0, 0, 0};
+static const GLubyte Helvetica12_Character_074[] = { 7, 0, 0, 0, 0, 56, 68, 68, 4,
4, 4, 4, 4, 4, 0, 0, 0};
+static const GLubyte Helvetica12_Character_075[] = { 8, 0, 0, 0, 0, 65, 66, 68,
72,112, 80, 72, 68, 66, 0, 0, 0};
+static const GLubyte Helvetica12_Character_076[] = { 7, 0, 0, 0, 0,124, 64, 64, 64,
64, 64, 64, 64, 64, 0, 0, 0};
+static const GLubyte Helvetica12_Character_077[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0,
68, 64, 68, 64, 74, 64, 74, 64, 81, 64, 81, 64, 96,192, 96,192, 64, 64, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_078[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
65, 0, 67, 0, 69, 0, 69, 0, 73, 0, 81, 0, 81, 0, 97, 0, 65, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_079[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
30, 0, 33, 0, 64,128, 64,128, 64,128, 64,128, 64,128, 33, 0, 30, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_080[] = { 8, 0, 0, 0, 0, 64, 64, 64,
64,124, 66, 66, 66,124, 0, 0, 0};
+static const GLubyte Helvetica12_Character_081[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
30,128, 33, 0, 66,128, 68,128, 64,128, 64,128, 64,128, 33, 0, 30, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_082[] = { 8, 0, 0, 0, 0, 66, 66, 66,
68,124, 66, 66, 66,124, 0, 0, 0};
+static const GLubyte Helvetica12_Character_083[] = { 8, 0, 0, 0, 0, 60, 66, 66, 2,
12, 48, 64, 66, 60, 0, 0, 0};
+static const GLubyte Helvetica12_Character_084[] = { 7, 0, 0, 0, 0, 16, 16, 16, 16,
16, 16, 16, 16,254, 0, 0, 0};
+static const GLubyte Helvetica12_Character_085[] = { 8, 0, 0, 0, 0, 60, 66, 66, 66,
66, 66, 66, 66, 66, 0, 0, 0};
+static const GLubyte Helvetica12_Character_086[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
8, 0, 8, 0, 20, 0, 20, 0, 34, 0, 34, 0, 34, 0, 65, 0, 65, 0, 0, 0, 0, 0, 0,
0};
+static const GLubyte Helvetica12_Character_087[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0,
17, 0, 17, 0, 17, 0, 42,128, 42,128, 36,128, 68, 64, 68, 64, 68, 64, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_088[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
65, 0, 34, 0, 34, 0, 20, 0, 8, 0, 20, 0, 34, 0, 34, 0, 65, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_089[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
8, 0, 8, 0, 8, 0, 8, 0, 20, 0, 34, 0, 34, 0, 65, 0, 65, 0, 0, 0, 0, 0, 0,
0};
+static const GLubyte Helvetica12_Character_090[] = { 9, 0, 0, 0, 0, 0, 0, 0,
0,127, 0, 64, 0, 32, 0, 16, 0, 8, 0, 4, 0, 2, 0, 1, 0,127, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_091[] = { 3, 0, 96, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 96, 0, 0, 0};
+static const GLubyte Helvetica12_Character_092[] = { 4, 0, 0, 0, 0, 16, 16, 32, 32,
32, 64, 64,128,128, 0, 0, 0};
+static const GLubyte Helvetica12_Character_093[] = { 3, 0,192, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64,192, 0, 0, 0};
+static const GLubyte Helvetica12_Character_094[] = { 6, 0, 0, 0, 0, 0, 0, 0, 0,
0,136, 80, 32, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_095[] = { 7, 0, 0,254, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_096[] = { 3, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,192,128, 64, 0, 0, 0};
+static const GLubyte Helvetica12_Character_097[] = { 7, 0, 0, 0, 0, 58, 68, 68, 60,
4, 68, 56, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_098[] = { 7, 0, 0, 0, 0, 88,100, 68, 68,
68,100, 88, 64, 64, 0, 0, 0};
+static const GLubyte Helvetica12_Character_099[] = { 7, 0, 0, 0, 0, 56, 68, 64, 64,
64, 68, 56, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_100[] = { 7, 0, 0, 0, 0, 52, 76, 68, 68,
68, 76, 52, 4, 4, 0, 0, 0};
+static const GLubyte Helvetica12_Character_101[] = { 7, 0, 0, 0, 0, 56, 68, 64,124,
68, 68, 56, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_102[] = { 3, 0, 0, 0, 0, 64, 64, 64, 64,
64, 64,224, 64, 48, 0, 0, 0};
+static const GLubyte Helvetica12_Character_103[] = { 7, 0, 56, 68, 4, 52, 76, 68, 68,
68, 76, 52, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_104[] = { 7, 0, 0, 0, 0, 68, 68, 68, 68,
68,100, 88, 64, 64, 0, 0, 0};
+static const GLubyte Helvetica12_Character_105[] = { 3, 0, 0, 0, 0, 64, 64, 64, 64,
64, 64, 64, 0, 64, 0, 0, 0};
+static const GLubyte Helvetica12_Character_106[] = { 3, 0,128, 64, 64, 64, 64, 64, 64,
64, 64, 64, 0, 64, 0, 0, 0};
+static const GLubyte Helvetica12_Character_107[] = { 6, 0, 0, 0, 0, 68, 72, 80, 96,
96, 80, 72, 64, 64, 0, 0, 0};
+static const GLubyte Helvetica12_Character_108[] = { 3, 0, 0, 0, 0, 64, 64, 64, 64,
64, 64, 64, 64, 64, 0, 0, 0};
+static const GLubyte Helvetica12_Character_109[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
73, 0, 73, 0, 73, 0, 73, 0, 73, 0,109, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_110[] = { 7, 0, 0, 0, 0, 68, 68, 68, 68,
68,100, 88, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_111[] = { 7, 0, 0, 0, 0, 56, 68, 68, 68,
68, 68, 56, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_112[] = { 7, 0, 64, 64, 64, 88,100, 68, 68,
68,100, 88, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_113[] = { 7, 0, 4, 4, 4, 52, 76, 68, 68,
68, 76, 52, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_114[] = { 4, 0, 0, 0, 0, 64, 64, 64, 64,
64, 96, 80, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_115[] = { 6, 0, 0, 0, 0, 48, 72, 8, 48,
64, 72, 48, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_116[] = { 3, 0, 0, 0, 0, 96, 64, 64, 64,
64, 64,224, 64, 64, 0, 0, 0};
+static const GLubyte Helvetica12_Character_117[] = { 7, 0, 0, 0, 0, 52, 76, 68, 68,
68, 68, 68, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_118[] = { 7, 0, 0, 0, 0, 16, 16, 40, 40,
68, 68, 68, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_119[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
34, 0, 34, 0, 85, 0, 73, 0, 73, 0,136,128,136,128, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_120[] = { 6, 0, 0, 0, 0,132,132, 72, 48,
48, 72,132, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_121[] = { 7, 0, 64, 32, 16, 16, 40, 40, 72,
68, 68, 68, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_122[] = { 6, 0, 0, 0, 0,120, 64, 32, 32,
16, 8,120, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_123[] = { 4, 0, 48, 64, 64, 64, 64, 64,128,
64, 64, 64, 64, 48, 0, 0, 0};
+static const GLubyte Helvetica12_Character_124[] = { 3, 0, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 0, 0, 0};
+static const GLubyte Helvetica12_Character_125[] = { 4, 0,192, 32, 32, 32, 32, 32, 16,
32, 32, 32, 32,192, 0, 0, 0};
+static const GLubyte Helvetica12_Character_126[] = { 7, 0, 0, 0, 0, 0, 0,
0,152,100, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_127[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_128[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_129[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_130[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_131[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_132[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_133[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_134[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_135[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_136[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_137[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_138[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_139[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_140[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_141[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_142[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_143[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_144[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_145[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_146[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_147[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_148[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_149[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_150[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_151[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_152[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_153[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_154[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_155[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_156[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_157[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_158[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_159[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_160[] = { 4, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_161[] = { 3, 0, 64, 64, 64, 64, 64, 64, 64,
64, 0, 64, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_162[] = { 7, 0, 0, 0, 32, 56,100, 80, 80,
80, 84, 56, 8, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_163[] = { 7, 0, 0, 0, 0, 88, 36, 16,
16,120, 32, 32, 36, 24, 0, 0, 0};
+static const GLubyte Helvetica12_Character_164[] = { 7, 0, 0, 0, 0, 0,132,120, 72,
72,120,132, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_165[] = { 7, 0, 0, 0, 0, 16, 16,124,
16,124, 16, 40, 68, 68, 0, 0, 0};
+static const GLubyte Helvetica12_Character_166[] = { 3, 0, 0, 64, 64, 64, 64, 0, 0,
0, 64, 64, 64, 64, 0, 0, 0};
+static const GLubyte Helvetica12_Character_167[] = { 6, 0,112,136, 8, 48,
72,136,136,144, 96,128,136,112, 0, 0, 0};
+static const GLubyte Helvetica12_Character_168[] = { 3, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0,160, 0, 0, 0};
+static const GLubyte Helvetica12_Character_169[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0,
31, 0, 32,128, 78, 64, 81, 64, 80, 64, 81, 64, 78, 64, 32,128, 31, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_170[] = { 5, 0, 0, 0, 0, 0, 0, 0,
0,112, 0, 80, 16,112, 0, 0, 0};
+static const GLubyte Helvetica12_Character_171[] = { 7, 0, 0, 0, 0, 0, 20, 40, 80,
40, 20, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_172[] = { 8, 0, 0, 0, 0, 0, 0, 2, 2,
2,126, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_173[] = { 5, 0, 0, 0, 0, 0, 0, 0,240,
0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_174[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0,
31, 0, 32,128, 74, 64, 74, 64, 76, 64, 74, 64, 78, 64, 32,128, 31, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_175[] = { 4, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0,240, 0, 0, 0};
+static const GLubyte Helvetica12_Character_176[] = { 5, 0, 0, 0, 0, 0, 0, 0, 0,
96,144,144, 96, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_177[] = { 7, 0, 0, 0, 0,124, 0, 16,
16,124, 16, 16, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_178[] = { 4, 0, 0, 0, 0, 0, 0, 0,240,
64, 32,144, 96, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_179[] = { 4, 0, 0, 0, 0, 0, 0, 0,192,
32, 64, 32,224, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_180[] = { 2, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0,128, 64, 0, 0};
+static const GLubyte Helvetica12_Character_181[] = { 7, 0, 64, 64, 64,116, 76, 68, 68,
68, 68, 68, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_182[] = { 7, 0, 40, 40, 40, 40, 40,
40,104,232,232,232,104, 60, 0, 0, 0};
+static const GLubyte Helvetica12_Character_183[] = { 3, 0, 0, 0, 0, 0, 0, 0, 64,
0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_184[] = { 3, 0,192, 32, 32, 64, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_185[] = { 4, 0, 0, 0, 0, 0, 0, 0, 32,
32, 32, 96, 32, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_186[] = { 5, 0, 0, 0, 0, 0, 0, 0,
0,112, 0,112, 80,112, 0, 0, 0};
+static const GLubyte Helvetica12_Character_187[] = { 7, 0, 0, 0, 0, 0, 80, 40, 20,
40, 80, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_188[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
65, 0, 39,128, 21, 0, 19, 0, 73, 0, 68, 0, 68, 0,194, 0, 65, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_189[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
71,128, 34, 0, 17, 0, 20,128, 75, 0, 72, 0, 68, 0,194, 0, 65, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_190[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
33, 0, 23,128, 21, 0, 11, 0,201, 0, 36, 0, 68, 0, 34, 0,225, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_191[] = { 7, 0, 56, 68, 68, 32, 32, 16, 16,
0, 16, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_192[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
65, 0, 65, 0, 65, 0, 62, 0, 34, 0, 34, 0, 20, 0, 8, 0, 8, 0, 0, 0, 8, 0,
16, 0};
+static const GLubyte Helvetica12_Character_193[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
65, 0, 65, 0, 65, 0, 62, 0, 34, 0, 34, 0, 20, 0, 8, 0, 8, 0, 0, 0, 8, 0,
4, 0};
+static const GLubyte Helvetica12_Character_194[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
65, 0, 65, 0, 65, 0, 62, 0, 34, 0, 34, 0, 20, 0, 8, 0, 8, 0, 0, 0, 20, 0,
8, 0};
+static const GLubyte Helvetica12_Character_195[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
65, 0, 65, 0, 65, 0, 62, 0, 34, 0, 34, 0, 20, 0, 8, 0, 8, 0, 0, 0, 20, 0,
10, 0};
+static const GLubyte Helvetica12_Character_196[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
65, 0, 65, 0, 65, 0, 62, 0, 34, 0, 34, 0, 20, 0, 8, 0, 8, 0, 0, 0, 20, 0,
0, 0};
+static const GLubyte Helvetica12_Character_197[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
65, 0, 65, 0, 65, 0, 62, 0, 34, 0, 34, 0, 20, 0, 8, 0, 8, 0, 8, 0, 20, 0,
8, 0};
+static const GLubyte Helvetica12_Character_198[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0,
71,192, 68, 0, 68, 0, 60, 0, 39,192, 36, 0, 20, 0, 20, 0, 15,192, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_199[] = { 9, 0, 0, 24, 0, 4, 0, 4, 0,
30, 0, 33, 0, 64, 0, 64, 0, 64, 0, 64, 0, 64, 0, 33, 0, 30, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_200[] = { 8, 0, 0, 0, 0,126, 64, 64,
64,126, 64, 64, 64,126, 0, 8, 16};
+static const GLubyte Helvetica12_Character_201[] = { 8, 0, 0, 0, 0,126, 64, 64,
64,126, 64, 64, 64,126, 0, 8, 4};
+static const GLubyte Helvetica12_Character_202[] = { 8, 0, 0, 0, 0,126, 64, 64,
64,126, 64, 64, 64,126, 0, 20, 8};
+static const GLubyte Helvetica12_Character_203[] = { 8, 0, 0, 0, 0,126, 64, 64,
64,126, 64, 64, 64,126, 0, 20, 0};
+static const GLubyte Helvetica12_Character_204[] = { 3, 0, 0, 0, 0, 64, 64, 64, 64,
64, 64, 64, 64, 64, 0, 64,128};
+static const GLubyte Helvetica12_Character_205[] = { 3, 0, 0, 0, 0, 64, 64, 64, 64,
64, 64, 64, 64, 64, 0, 64, 32};
+static const GLubyte Helvetica12_Character_206[] = { 3, 0, 0, 0, 0, 64, 64, 64, 64,
64, 64, 64, 64, 64, 0,160, 64};
+static const GLubyte Helvetica12_Character_207[] = { 3, 0, 0, 0, 0, 64, 64, 64, 64,
64, 64, 64, 64, 64, 0,160, 0};
+static const GLubyte Helvetica12_Character_208[] = { 9, 0, 0, 0, 0, 0, 0, 0,
0,124, 0, 66, 0, 65, 0, 65, 0,241, 0, 65, 0, 65, 0, 66, 0,124, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_209[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
65, 0, 67, 0, 69, 0, 69, 0, 73, 0, 81, 0, 81, 0, 97, 0, 65, 0, 0, 0, 20, 0,
10, 0};
+static const GLubyte Helvetica12_Character_210[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
30, 0, 33, 0, 64,128, 64,128, 64,128, 64,128, 64,128, 33, 0, 30, 0, 0, 0, 4, 0,
8, 0};
+static const GLubyte Helvetica12_Character_211[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
30, 0, 33, 0, 64,128, 64,128, 64,128, 64,128, 64,128, 33, 0, 30, 0, 0, 0, 4, 0,
2, 0};
+static const GLubyte Helvetica12_Character_212[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
30, 0, 33, 0, 64,128, 64,128, 64,128, 64,128, 64,128, 33, 0, 30, 0, 0, 0, 10, 0,
4, 0};
+static const GLubyte Helvetica12_Character_213[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
30, 0, 33, 0, 64,128, 64,128, 64,128, 64,128, 64,128, 33, 0, 30, 0, 0, 0, 20, 0,
10, 0};
+static const GLubyte Helvetica12_Character_214[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
30, 0, 33, 0, 64,128, 64,128, 64,128, 64,128, 64,128, 33, 0, 30, 0, 0, 0, 18, 0,
0, 0};
+static const GLubyte Helvetica12_Character_215[] = { 7, 0, 0, 0, 0, 0, 68, 40, 16,
40, 68, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_216[] = { 10, 0, 0, 0, 0, 0, 0,128, 0,
94, 0, 33, 0, 80,128, 72,128, 68,128, 68,128, 66,128, 33, 0, 30,128, 0, 64, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_217[] = { 8, 0, 0, 0, 0, 60, 66, 66, 66,
66, 66, 66, 66, 66, 0, 8, 16};
+static const GLubyte Helvetica12_Character_218[] = { 8, 0, 0, 0, 0, 60, 66, 66, 66,
66, 66, 66, 66, 66, 0, 8, 4};
+static const GLubyte Helvetica12_Character_219[] = { 8, 0, 0, 0, 0, 60, 66, 66, 66,
66, 66, 66, 66, 66, 0, 20, 8};
+static const GLubyte Helvetica12_Character_220[] = { 8, 0, 0, 0, 0, 60, 66, 66, 66,
66, 66, 66, 66, 66, 0, 36, 0};
+static const GLubyte Helvetica12_Character_221[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
8, 0, 8, 0, 8, 0, 8, 0, 20, 0, 34, 0, 34, 0, 65, 0, 65, 0, 0, 0, 8, 0, 4,
0};
+static const GLubyte Helvetica12_Character_222[] = { 8, 0, 0, 0, 0, 64, 64,124, 66,
66, 66,124, 64, 64, 0, 0, 0};
+static const GLubyte Helvetica12_Character_223[] = { 7, 0, 0, 0, 0, 88, 68, 68, 68,
88, 68, 68, 68, 56, 0, 0, 0};
+static const GLubyte Helvetica12_Character_224[] = { 7, 0, 0, 0, 0, 58, 68, 68, 60,
4, 68, 56, 0, 8, 16, 0, 0};
+static const GLubyte Helvetica12_Character_225[] = { 7, 0, 0, 0, 0, 58, 68, 68, 60,
4, 68, 56, 0, 16, 8, 0, 0};
+static const GLubyte Helvetica12_Character_226[] = { 7, 0, 0, 0, 0, 58, 68, 68, 60,
4, 68, 56, 0, 40, 16, 0, 0};
+static const GLubyte Helvetica12_Character_227[] = { 7, 0, 0, 0, 0, 58, 68, 68, 60,
4, 68, 56, 0, 40, 20, 0, 0};
+static const GLubyte Helvetica12_Character_228[] = { 7, 0, 0, 0, 0, 58, 68, 68, 60,
4, 68, 56, 0, 40, 0, 0, 0};
+static const GLubyte Helvetica12_Character_229[] = { 7, 0, 0, 0, 0, 58, 68, 68, 60,
4, 68, 56, 24, 36, 24, 0, 0};
+static const GLubyte Helvetica12_Character_230[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0,
59,128, 68, 64, 68, 0, 63,192, 4, 64, 68, 64, 59,128, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0};
+static const GLubyte Helvetica12_Character_231[] = { 7, 0, 48, 8, 16, 56, 68, 64, 64,
64, 68, 56, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_232[] = { 7, 0, 0, 0, 0, 56, 68, 64,124,
68, 68, 56, 0, 16, 32, 0, 0};
+static const GLubyte Helvetica12_Character_233[] = { 7, 0, 0, 0, 0, 56, 68, 64,124,
68, 68, 56, 0, 16, 8, 0, 0};
+static const GLubyte Helvetica12_Character_234[] = { 7, 0, 0, 0, 0, 56, 68, 64,124,
68, 68, 56, 0, 40, 16, 0, 0};
+static const GLubyte Helvetica12_Character_235[] = { 7, 0, 0, 0, 0, 56, 68, 64,124,
68, 68, 56, 0, 40, 0, 0, 0};
+static const GLubyte Helvetica12_Character_236[] = { 3, 0, 0, 0, 0, 64, 64, 64, 64,
64, 64, 64, 0, 64,128, 0, 0};
+static const GLubyte Helvetica12_Character_237[] = { 3, 0, 0, 0, 0, 64, 64, 64, 64,
64, 64, 64, 0, 64, 32, 0, 0};
+static const GLubyte Helvetica12_Character_238[] = { 3, 0, 0, 0, 0, 64, 64, 64, 64,
64, 64, 64, 0,160, 64, 0, 0};
+static const GLubyte Helvetica12_Character_239[] = { 3, 0, 0, 0, 0, 64, 64, 64, 64,
64, 64, 64, 0,160, 0, 0, 0};
+static const GLubyte Helvetica12_Character_240[] = { 7, 0, 0, 0, 0, 56, 68, 68, 68,
68, 60, 4, 40, 24, 52, 0, 0};
+static const GLubyte Helvetica12_Character_241[] = { 7, 0, 0, 0, 0, 68, 68, 68, 68,
68,100, 88, 0, 40, 20, 0, 0};
+static const GLubyte Helvetica12_Character_242[] = { 7, 0, 0, 0, 0, 56, 68, 68, 68,
68, 68, 56, 0, 16, 32, 0, 0};
+static const GLubyte Helvetica12_Character_243[] = { 7, 0, 0, 0, 0, 56, 68, 68, 68,
68, 68, 56, 0, 16, 8, 0, 0};
+static const GLubyte Helvetica12_Character_244[] = { 7, 0, 0, 0, 0, 56, 68, 68, 68,
68, 68, 56, 0, 40, 16, 0, 0};
+static const GLubyte Helvetica12_Character_245[] = { 7, 0, 0, 0, 0, 56, 68, 68, 68,
68, 68, 56, 0, 40, 20, 0, 0};
+static const GLubyte Helvetica12_Character_246[] = { 7, 0, 0, 0, 0, 56, 68, 68, 68,
68, 68, 56, 0, 40, 0, 0, 0};
+static const GLubyte Helvetica12_Character_247[] = { 7, 0, 0, 0, 0, 0, 16, 0,124,
0, 16, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_248[] = { 7, 0, 0, 0, 0,184, 68,100, 84,
76, 68, 58, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica12_Character_249[] = { 7, 0, 0, 0, 0, 52, 76, 68, 68,
68, 68, 68, 0, 16, 32, 0, 0};
+static const GLubyte Helvetica12_Character_250[] = { 7, 0, 0, 0, 0, 52, 76, 68, 68,
68, 68, 68, 0, 16, 8, 0, 0};
+static const GLubyte Helvetica12_Character_251[] = { 7, 0, 0, 0, 0, 52, 76, 68, 68,
68, 68, 68, 0, 40, 16, 0, 0};
+static const GLubyte Helvetica12_Character_252[] = { 7, 0, 0, 0, 0, 52, 76, 68, 68,
68, 68, 68, 0, 40, 0, 0, 0};
+static const GLubyte Helvetica12_Character_253[] = { 7, 0, 64, 32, 16, 16, 40, 40, 72,
68, 68, 68, 0, 16, 8, 0, 0};
+static const GLubyte Helvetica12_Character_254[] = { 7, 0, 64, 64, 64, 88,100, 68, 68,
68,100, 88, 64, 64, 0, 0, 0};
+static const GLubyte Helvetica12_Character_255[] = { 7, 0, 96, 16, 16, 16, 24, 40, 40,
36, 68, 68, 0, 40, 0, 0, 0};
+
+/* The font characters mapping: */
+static const GLubyte* Helvetica12_Character_Map[] =
{Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,
+
Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,
+
Helvetica12_Character_032,Helvetica12_Character_033,Helvetica12_Character_034,Helvetica12_Character_035,Helvetica12_Character_036,Helvetica12_Character_037,Helvetica12_Character_038,Helvetica12_Character_039,Helvetica12_Character_040,Helvetica12_Character_041,Helvetica12_Character_042,Helvetica12_Character_043,Helvetica12_Character_044,Helvetica12_Character_045,Helvetica12_Character_046,Helvetica12_Character_047,
+
Helvetica12_Character_048,Helvetica12_Character_049,Helvetica12_Character_050,Helvetica12_Character_051,Helvetica12_Character_052,Helvetica12_Character_053,Helvetica12_Character_054,Helvetica12_Character_055,Helvetica12_Character_056,Helvetica12_Character_057,Helvetica12_Character_058,Helvetica12_Character_059,Helvetica12_Character_060,Helvetica12_Character_061,Helvetica12_Character_062,Helvetica12_Character_063,
+
Helvetica12_Character_064,Helvetica12_Character_065,Helvetica12_Character_066,Helvetica12_Character_067,Helvetica12_Character_068,Helvetica12_Character_069,Helvetica12_Character_070,Helvetica12_Character_071,Helvetica12_Character_072,Helvetica12_Character_073,Helvetica12_Character_074,Helvetica12_Character_075,Helvetica12_Character_076,Helvetica12_Character_077,Helvetica12_Character_078,Helvetica12_Character_079,
+
Helvetica12_Character_080,Helvetica12_Character_081,Helvetica12_Character_082,Helvetica12_Character_083,Helvetica12_Character_084,Helvetica12_Character_085,Helvetica12_Character_086,Helvetica12_Character_087,Helvetica12_Character_088,Helvetica12_Character_089,Helvetica12_Character_090,Helvetica12_Character_091,Helvetica12_Character_092,Helvetica12_Character_093,Helvetica12_Character_094,Helvetica12_Character_095,
+
Helvetica12_Character_096,Helvetica12_Character_097,Helvetica12_Character_098,Helvetica12_Character_099,Helvetica12_Character_100,Helvetica12_Character_101,Helvetica12_Character_102,Helvetica12_Character_103,Helvetica12_Character_104,Helvetica12_Character_105,Helvetica12_Character_106,Helvetica12_Character_107,Helvetica12_Character_108,Helvetica12_Character_109,Helvetica12_Character_110,Helvetica12_Character_111,
+
Helvetica12_Character_112,Helvetica12_Character_113,Helvetica12_Character_114,Helvetica12_Character_115,Helvetica12_Character_116,Helvetica12_Character_117,Helvetica12_Character_118,Helvetica12_Character_119,Helvetica12_Character_120,Helvetica12_Character_121,Helvetica12_Character_122,Helvetica12_Character_123,Helvetica12_Character_124,Helvetica12_Character_125,Helvetica12_Character_126,Helvetica12_Character_032,
+
Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,
+
Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,
+
Helvetica12_Character_160,Helvetica12_Character_161,Helvetica12_Character_162,Helvetica12_Character_163,Helvetica12_Character_164,Helvetica12_Character_165,Helvetica12_Character_166,Helvetica12_Character_167,Helvetica12_Character_168,Helvetica12_Character_169,Helvetica12_Character_170,Helvetica12_Character_171,Helvetica12_Character_172,Helvetica12_Character_173,Helvetica12_Character_174,Helvetica12_Character_175,
+
Helvetica12_Character_176,Helvetica12_Character_177,Helvetica12_Character_178,Helvetica12_Character_179,Helvetica12_Character_180,Helvetica12_Character_181,Helvetica12_Character_182,Helvetica12_Character_183,Helvetica12_Character_184,Helvetica12_Character_185,Helvetica12_Character_186,Helvetica12_Character_187,Helvetica12_Character_188,Helvetica12_Character_189,Helvetica12_Character_190,Helvetica12_Character_191,
+
Helvetica12_Character_192,Helvetica12_Character_193,Helvetica12_Character_194,Helvetica12_Character_195,Helvetica12_Character_196,Helvetica12_Character_197,Helvetica12_Character_198,Helvetica12_Character_199,Helvetica12_Character_200,Helvetica12_Character_201,Helvetica12_Character_202,Helvetica12_Character_203,Helvetica12_Character_204,Helvetica12_Character_205,Helvetica12_Character_206,Helvetica12_Character_207,
+
Helvetica12_Character_208,Helvetica12_Character_209,Helvetica12_Character_210,Helvetica12_Character_211,Helvetica12_Character_212,Helvetica12_Character_213,Helvetica12_Character_214,Helvetica12_Character_215,Helvetica12_Character_216,Helvetica12_Character_217,Helvetica12_Character_218,Helvetica12_Character_219,Helvetica12_Character_220,Helvetica12_Character_221,Helvetica12_Character_222,Helvetica12_Character_223,
+
Helvetica12_Character_224,Helvetica12_Character_225,Helvetica12_Character_226,Helvetica12_Character_227,Helvetica12_Character_228,Helvetica12_Character_229,Helvetica12_Character_230,Helvetica12_Character_231,Helvetica12_Character_232,Helvetica12_Character_233,Helvetica12_Character_234,Helvetica12_Character_235,Helvetica12_Character_236,Helvetica12_Character_237,Helvetica12_Character_238,Helvetica12_Character_239,
+
Helvetica12_Character_240,Helvetica12_Character_241,Helvetica12_Character_242,Helvetica12_Character_243,Helvetica12_Character_244,Helvetica12_Character_245,Helvetica12_Character_246,Helvetica12_Character_247,Helvetica12_Character_248,Helvetica12_Character_249,Helvetica12_Character_250,Helvetica12_Character_251,Helvetica12_Character_252,Helvetica12_Character_253,Helvetica12_Character_254,Helvetica12_Character_255,NULL};
+
+/* The font structure: */
+const SFG_Font fgFontHelvetica12 = {
"-adobe-helvetica-medium-r-normal--12-120-75-75-p-67-iso8859-1", 256, 16,
Helvetica12_Character_Map, 0, 4 };
+
+static const GLubyte Helvetica18_Character_000[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 85, 80, 0, 0, 64, 16, 0, 0, 64, 16, 0, 0, 64, 16, 0, 0, 64, 16, 0, 0, 64,
16, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_001[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_002[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_003[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_004[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_005[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_006[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_007[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_008[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_009[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_010[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_011[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_012[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_013[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_014[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_015[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_016[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_017[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_018[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_019[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_020[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_021[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_022[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_023[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_024[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_025[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_026[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_027[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_028[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_029[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_030[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_031[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_032[] = { 5, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_033[] = { 6, 0, 0, 0, 0, 0, 48, 48, 0,
0, 32, 32, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_034[] = { 5, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,144,144,216,216,216, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_035[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 36, 0, 36, 0, 36, 0,255,128,255,128, 18, 0, 18, 0, 18, 0,127,192,127,192, 9,
0, 9, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_036[] = { 10, 0, 0, 0, 0, 0, 0, 4, 0,
4, 0, 31, 0, 63,128,117,192,100,192, 4,192, 7,128, 31, 0, 60, 0,116, 0,100,
0,101,128, 63,128, 31, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_037[] = { 16, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 12, 60, 12,126, 6,102, 6,102, 3,126, 3, 60, 1,128, 61,128,126,192,102,192,102,
96,126, 96, 60, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_038[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 30, 56, 63,112,115,224, 97,192, 97,224, 99, 96,119, 96, 62, 0, 30, 0, 51, 0, 51,
0, 63, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_039[] = { 4, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 64, 32, 32, 96, 96, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_040[] = { 6, 0, 8, 24, 48, 48, 96, 96, 96,
96, 96, 96, 96, 96, 96, 96, 48, 48, 24, 8, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_041[] = { 6, 0, 64, 96, 48, 48, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 48, 48, 96, 64, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_042[] = { 7, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 68, 56, 56,124, 16, 16, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_043[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 12, 0, 12, 0, 12, 0, 12, 0,127,128,127,128, 12, 0, 12, 0, 12, 0, 12, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_044[] = { 5, 0, 0, 64, 32, 32, 96, 96, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_045[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127,128,127,128, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_046[] = { 5, 0, 0, 0, 0, 0, 96, 96, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_047[] = { 5, 0, 0, 0, 0, 0,192,192, 64,
64, 96, 96, 32, 32, 48, 48, 16, 16, 24, 24, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_048[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 30, 0, 63, 0, 51, 0, 97,128, 97,128, 97,128, 97,128, 97,128, 97,128, 97,128, 51,
0, 63, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_049[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 62,
0, 62, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_050[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,127,128,127,128, 96, 0,112, 0, 56, 0, 28, 0, 14, 0, 7, 0, 3,128, 1,128,
97,128,127, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_051[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 30, 0, 63, 0, 99,128, 97,128, 1,128, 3,128, 15, 0, 14, 0, 3, 0, 97,128,
97,128, 63, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_052[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1,128, 1,128, 1,128,127,192,127,192, 97,128, 49,128, 25,128, 25,128, 13,128,
7,128, 3,128, 1,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_053[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 62, 0,127, 0, 99,128, 97,128, 1,128, 1,128, 99,128,127, 0,126, 0, 96, 0, 96,
0,127, 0,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_054[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 30, 0, 63, 0,113,128, 97,128, 97,128, 97,128,127, 0,110, 0, 96, 0, 96, 0,
49,128, 63,128, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_055[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 48, 0, 48, 0, 24, 0, 24, 0, 24, 0, 12, 0, 12, 0, 6, 0, 6, 0, 3, 0,
1,128,127,128,127,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_056[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 30, 0, 63, 0,115,128, 97,128, 97,128, 51, 0, 63, 0, 51, 0, 97,128,
97,128,115,128, 63, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_057[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 62, 0,127, 0, 99, 0, 1,128, 1,128, 29,128, 63,128, 97,128, 97,128, 97,128,
99,128, 63, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_058[] = { 5, 0, 0, 0, 0, 0, 96, 96, 0,
0, 0, 0, 0, 0, 96, 96, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_059[] = { 5, 0, 0, 64, 32, 32, 96, 96, 0,
0, 0, 0, 0, 0, 96, 96, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_060[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1,128, 7,128, 30, 0, 56, 0, 96, 0, 56, 0, 30, 0, 7,128, 1,128, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_061[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 63,128, 63,128, 0, 0, 0, 0, 63,128, 63,128, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_062[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 96, 0,120, 0, 30, 0, 7, 0, 1,128, 7, 0, 30, 0,120, 0, 96, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_063[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 24, 0, 24, 0, 0, 0, 0, 0, 24, 0, 24, 0, 24, 0, 28, 0, 14, 0, 7, 0, 99,
0, 99, 0,127, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_064[] = { 18, 0, 0, 0, 0, 0, 0, 3,240,
0, 15,248, 0, 28, 0, 0, 56, 0, 0, 51,184, 0,103,252, 0,102,102, 0,102, 51, 0,102,
51, 0,102, 49,128, 99, 25,128, 51,185,128, 49,217,128, 24, 3, 0, 14, 7, 0, 7,254,
0, 1,248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_065[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,192, 48,192, 48, 96, 96, 96, 96,127,224, 63,192, 48,192, 48,192, 25,128, 25,128, 15,
0, 15, 0, 6, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_066[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,127,192,127,224, 96,112, 96, 48, 96, 48, 96,112,127,224,127,192, 96,192, 96, 96, 96,
96, 96,224,127,192,127,128, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_067[] = { 14, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 7,192, 31,240, 56, 56, 48, 24,112, 0, 96, 0, 96, 0, 96, 0, 96, 0,112, 0, 48,
24, 56, 56, 31,240, 7,192, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_068[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,127,128,127,192, 96,224, 96, 96, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96,
96, 96,224,127,192,127,128, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_069[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,127,192,127,192, 96, 0, 96, 0, 96, 0, 96, 0,127,128,127,128, 96, 0, 96, 0, 96,
0, 96, 0,127,192,127,192, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_070[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 96, 0, 96, 0, 96, 0, 96, 0, 96, 0, 96, 0,127,128,127,128, 96, 0, 96, 0, 96,
0, 96, 0,127,192,127,192, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_071[] = { 14, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 7,216, 31,248, 56, 56, 48, 24,112, 24, 96,248, 96,248, 96, 0, 96, 0,112, 24, 48,
24, 56, 56, 31,240, 7,192, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_072[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48,127,240,127,240, 96, 48, 96, 48, 96,
48, 96, 48, 96, 48, 96, 48, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_073[] = { 6, 0, 0, 0, 0, 0, 48, 48, 48,
48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_074[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 30, 0, 63, 0,115,128, 97,128, 97,128, 1,128, 1,128, 1,128, 1,128, 1,128,
1,128, 1,128, 1,128, 1,128, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_075[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 96, 56, 96,112, 96,224, 97,192, 99,128,103, 0,126, 0,124, 0,110, 0,103, 0,
99,128, 97,192, 96,224, 96,112, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_076[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,127,128,127,128, 96, 0, 96, 0, 96, 0, 96, 0, 96, 0, 96, 0, 96, 0, 96, 0, 96,
0, 96, 0, 96, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_077[] = { 16, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 97,134, 97,134, 99,198, 98, 70,102,102,102,102,108, 54,108, 54,120, 30,120, 30,112,
14,112, 14, 96, 6, 96, 6, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_078[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 96, 48, 96,112, 96,240, 96,240, 97,176, 99, 48, 99, 48,102, 48,102, 48,108, 48,120,
48,120, 48,112, 48, 96, 48, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_079[] = { 15, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 7,192, 31,240, 56, 56, 48, 24,112, 28, 96, 12, 96, 12, 96, 12, 96, 12,112, 28, 48,
24, 56, 56, 31,240, 7,192, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_080[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 96, 0, 96, 0, 96, 0, 96, 0, 96, 0, 96, 0,127,128,127,192, 96,224, 96, 96, 96,
96, 96,224,127,192,127,128, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_081[] = { 15, 0, 0, 0, 0, 0, 0, 0, 0,
0, 24, 7,216, 31,240, 56,120, 48,216,112,220, 96, 12, 96, 12, 96, 12, 96, 12,112, 28, 48,
24, 56, 56, 31,240, 7,192, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_082[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 96, 96, 96, 96, 96, 96, 96, 96, 96,192, 96,192,127,128,127,192, 96,224, 96, 96, 96,
96, 96,224,127,192,127,128, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_083[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 31,128, 63,224,112,112, 96, 48, 0, 48, 0,112, 1,224, 15,128, 62, 0,112, 0, 96,
48,112,112, 63,224, 15,128, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_084[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6,
0, 6, 0,127,224,127,224, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_085[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 15,128, 63,224, 48, 96, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96,
48, 96, 48, 96, 48, 96, 48, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_086[] = { 14, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 3, 0, 7,128, 7,128, 12,192, 12,192, 12,192, 24, 96, 24, 96, 24, 96, 48, 48, 48,
48, 48, 48, 96, 24, 96, 24, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_087[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 12, 12, 0, 12, 12, 0, 14, 28, 0, 26, 22, 0, 27, 54, 0, 27,
54, 0, 51, 51, 0, 51, 51, 0, 49, 35, 0, 49,227, 0, 97,225,128, 96,193,128,
96,193,128, 96,193,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_088[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 96, 48,112,112, 48, 96, 56,224, 24,192, 13,128, 7, 0, 7, 0, 13,128, 24,192,
56,224, 48, 96,112,112, 96, 48, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_089[] = { 14, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 7,128, 12,192, 24, 96, 24, 96, 48,
48, 48, 48, 96, 24, 96, 24, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_090[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,127,224,127,224, 96, 0, 48, 0, 24, 0, 12, 0, 14, 0, 6, 0, 3, 0, 1,128,
0,192, 0, 96,127,224,127,224, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_091[] = { 5, 0,120,120, 96, 96, 96, 96, 96,
96, 96, 96, 96, 96, 96, 96, 96, 96,120,120, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_092[] = { 5, 0, 0, 0, 0, 0, 24, 24, 16,
16, 48, 48, 32, 32, 96, 96, 64, 64,192,192, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_093[] = { 5, 0,240,240, 48, 48, 48, 48, 48,
48, 48, 48, 48, 48, 48, 48, 48, 48,240,240, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_094[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 99, 0, 54,
0, 28, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_095[] = { 10, 0, 0,255,192,255,192, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_096[] = { 4, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 96, 96, 64, 64, 32, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_097[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 59, 0,119, 0, 99, 0, 99, 0,115, 0, 63, 0, 7, 0, 99, 0,119, 0, 62, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_098[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,111, 0,127,128,113,128, 96,192, 96,192, 96,192, 96,192,113,128,127,128,111, 0, 96,
0, 96, 0, 96, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_099[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 31, 0, 63,128, 49,128, 96, 0, 96, 0, 96, 0, 96, 0, 49,128, 63,128, 31, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_100[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 30,192, 63,192, 49,192, 96,192, 96,192, 96,192, 96,192, 49,192, 63,192, 30,192,
0,192, 0,192, 0,192, 0,192, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_101[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 30, 0, 63,128,113,128, 96, 0, 96, 0,127,128, 97,128, 97,128, 63, 0, 30, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_102[] = { 6, 0, 0, 0, 0, 0, 48, 48, 48,
48, 48, 48, 48, 48,252,252, 48, 48, 60, 28, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_103[] = { 11, 0, 0, 14, 0, 63,128, 49,128,
0,192, 30,192, 63,192, 49,192, 96,192, 96,192, 96,192, 96,192, 48,192, 63,192, 30,192, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_104[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 97,128, 97,128, 97,128, 97,128, 97,128, 97,128, 97,128,113,128,111,128,103, 0, 96,
0, 96, 0, 96, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_105[] = { 4, 0, 0, 0, 0, 0, 96, 96, 96,
96, 96, 96, 96, 96, 96, 96, 0, 0, 96, 96, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_106[] = { 4, 0,192,224, 96, 96, 96, 96, 96,
96, 96, 96, 96, 96, 96, 96, 0, 0, 96, 96, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_107[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 99,128, 99, 0,103, 0,102, 0,108, 0,124, 0,120, 0,108, 0,102, 0, 99, 0, 96,
0, 96, 0, 96, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_108[] = { 4, 0, 0, 0, 0, 0, 96, 96, 96,
96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_109[] = { 14, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 99, 24, 99, 24, 99, 24, 99, 24, 99, 24, 99, 24, 99, 24,115,152,111,120,102, 48, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_110[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 97,128, 97,128, 97,128, 97,128, 97,128, 97,128, 97,128,113,128,111,128,103, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_111[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 31, 0, 63,128, 49,128, 96,192, 96,192, 96,192, 96,192, 49,128, 63,128, 31, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_112[] = { 11, 0, 0, 96, 0, 96, 0, 96, 0,
96, 0,111, 0,127,128,113,128, 96,192, 96,192, 96,192, 96,192,113,128,127,128,111, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_113[] = { 11, 0, 0, 0,192, 0,192, 0,192,
0,192, 30,192, 63,192, 49,192, 96,192, 96,192, 96,192, 96,192, 49,192, 63,192, 30,192, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_114[] = { 6, 0, 0, 0, 0, 0, 96, 96, 96,
96, 96, 96, 96,112,108,108, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_115[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 60, 0,126, 0, 99, 0, 3, 0, 31, 0,126, 0, 96, 0, 99, 0, 63, 0, 30, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_116[] = { 6, 0, 0, 0, 0, 0, 24, 56, 48,
48, 48, 48, 48, 48,252,252, 48, 48, 48, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_117[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 57,128,125,128, 99,128, 97,128, 97,128, 97,128, 97,128, 97,128, 97,128, 97,128, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_118[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 12, 0, 12, 0, 30, 0, 18, 0, 51, 0, 51, 0, 51, 0, 97,128, 97,128, 97,128, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_119[] = { 14, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 12,192, 12,192, 28,224, 20,160, 52,176, 51, 48, 51, 48, 99, 24, 99, 24, 99, 24, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_120[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 97,128,115,128, 51, 0, 30, 0, 12, 0, 12, 0, 30, 0, 51, 0,115,128, 97,128, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_121[] = { 10, 0, 0, 56, 0, 56, 0, 12, 0,
12, 0, 12, 0, 12, 0, 30, 0, 18, 0, 51, 0, 51, 0, 51, 0, 97,128, 97,128, 97,128,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_122[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,127, 0,127, 0, 96, 0, 48, 0, 24, 0, 12, 0, 6, 0, 3, 0,127, 0,127, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_123[] = { 6, 0, 12, 24, 48, 48, 48, 48, 48,
48, 96,192, 96, 48, 48, 48, 48, 48, 24, 12, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_124[] = { 4, 0, 96, 96, 96, 96, 96, 96, 96,
96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_125[] = { 6, 0,192, 96, 48, 48, 48, 48, 48,
48, 24, 12, 24, 48, 48, 48, 48, 48, 96,192, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_126[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,102, 0, 63, 0, 25,128, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_127[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_128[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_129[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_130[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_131[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_132[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_133[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_134[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_135[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_136[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_137[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_138[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_139[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_140[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_141[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_142[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_143[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_144[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_145[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_146[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_147[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_148[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_149[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_150[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_151[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_152[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_153[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_154[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_155[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_156[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_157[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_158[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_159[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0,
0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_160[] = { 5, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_161[] = { 6, 0, 48, 48, 48, 48, 48, 48, 48,
48, 16, 16, 0, 0, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_162[] = { 10, 0, 0, 0, 0, 0, 0, 8, 0,
8, 0, 31, 0, 63,128, 53,128,100, 0,100, 0,100, 0,100, 0, 53,128, 63,128, 31, 0, 2,
0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_163[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,223, 0,255,128, 96,128, 48, 0, 24, 0, 24, 0,126, 0, 48, 0, 96, 0, 97,128,
97,128, 63, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_164[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 97,128,127,128, 51, 0, 51, 0, 51, 0,127,128, 97,128, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_165[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 12, 0, 12, 0, 12, 0, 12, 0,127,128, 12, 0,127,128, 30, 0, 51, 0, 51, 0, 51,
0, 97,128, 97,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_166[] = { 4, 0, 0, 96, 96, 96, 96, 96, 96,
0, 0, 0, 0, 96, 96, 96, 96, 96, 96, 96, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_167[] = { 10, 0, 0, 30, 0, 63, 0, 97,128,
97,128, 3,128, 7, 0, 31, 0, 57,128,113,128, 97,128, 99,128, 55, 0, 62, 0,120, 0,
97,128, 97,128, 63, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_168[] = { 6, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,216,216, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_169[] = { 15, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 7,192, 24, 48, 32, 8, 35,136, 68, 68, 72, 4, 72, 4, 72, 4, 68, 68, 35,136, 32,
8, 24, 48, 7,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_170[] = { 7, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0,124, 0, 52,108, 36, 28,100, 56, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_171[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 9, 0, 27, 0, 54, 0,108, 0,108, 0, 54, 0, 27, 0, 9, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_172[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,192, 0,192, 0,192,127,192,127,192, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_173[] = { 7, 0, 0, 0, 0, 0, 0, 0, 0,
0,124,124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_174[] = { 14, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 7,192, 24, 48, 32, 8, 36, 40, 68, 68, 68,132, 71,196, 68, 36, 68, 36, 39,200, 32,
8, 24, 48, 7,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_175[] = { 5, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,248, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_176[] = { 7, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 56,108, 68,108, 56, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_177[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,127,128,127,128, 0, 0, 12, 0, 12, 0, 12, 0,127,128,127,128, 12, 0, 12, 0, 12,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_178[] = { 6, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,248,248, 96, 48, 24,152,248,112, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_179[] = { 6, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,112,248,152, 48, 48,152,248,112, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_180[] = { 4, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,192, 96, 48, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_181[] = { 10, 0, 0, 96, 0, 96, 0, 96, 0,
96, 0,109,128,127,128,115,128, 97,128, 97,128, 97,128, 97,128, 97,128, 97,128, 97,128,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_182[] = { 10, 0, 0, 9, 0, 9, 0, 9, 0,
9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 25, 0, 57, 0,121, 0,121, 0,121,
0,121, 0, 57, 0, 31,128, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_183[] = { 4, 0, 0, 0, 0, 0, 0, 0, 0,
0, 96, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_184[] = { 5, 0,240,216, 24,112, 96, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_185[] = { 6, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 48, 48, 48, 48, 48,112,112, 48, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_186[] = { 7, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0,124, 0, 56,108, 68, 68,108, 56, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_187[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 72, 0,108, 0, 54, 0, 27, 0, 27, 0, 54, 0,108, 0, 72, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_188[] = { 15, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 24, 24, 24, 24, 12,252, 6,216, 6,120, 51, 56, 49, 24, 49,136, 48,192, 48,192,112,
96,112, 48, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_189[] = { 15, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 24,124, 24,124, 12, 48, 6, 24, 6, 12, 51, 76, 49,124, 49,184, 48,192, 48,192,112,
96,112, 48, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_190[] = { 15, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 24, 24, 24, 24, 12,252, 6,216, 6,120,115, 56,249, 24,153,136, 48,192, 48,192,152,
96,248, 48,112, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_191[] = { 10, 0, 0, 62, 0,127, 0, 99, 0,
99, 0,112, 0, 56, 0, 28, 0, 12, 0, 12, 0, 12, 0, 0, 0, 0, 0, 12, 0, 12, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_192[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,192, 48,192, 48, 96, 96, 96, 96,127,224, 63,192, 48,192, 48,192, 25,128, 25,128, 15,
0, 15, 0, 6, 0, 6, 0, 0, 0, 6, 0, 12, 0, 24, 0};
+static const GLubyte Helvetica18_Character_193[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,192, 48,192, 48, 96, 96, 96, 96,127,224, 63,192, 48,192, 48,192, 25,128, 25,128, 15,
0, 15, 0, 6, 0, 6, 0, 0, 0, 6, 0, 3, 0, 1,128};
+static const GLubyte Helvetica18_Character_194[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,192, 48,192, 48, 96, 96, 96, 96,127,224, 63,192, 48,192, 48,192, 25,128, 25,128, 15,
0, 15, 0, 6, 0, 6, 0, 0, 0, 25,128, 15, 0, 6, 0};
+static const GLubyte Helvetica18_Character_195[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,192, 48,192, 48, 96, 96, 96, 96,127,224, 63,192, 48,192, 48,192, 25,128, 25,128, 15,
0, 15, 0, 6, 0, 6, 0, 0, 0, 19, 0, 22,128, 12,128};
+static const GLubyte Helvetica18_Character_196[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,192, 48,192, 48, 96, 96, 96, 96,127,224, 63,192, 48,192, 48,192, 25,128, 25,128, 15,
0, 15, 0, 6, 0, 6, 0, 0, 0, 25,128, 25,128, 0, 0};
+static const GLubyte Helvetica18_Character_197[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,192, 48,192, 48, 96, 96, 96, 96,127,224, 63,192, 48,192, 48,192, 25,128, 25,128, 15,
0, 15, 0, 6, 0, 6, 0, 15, 0, 25,128, 25,128, 15, 0};
+static const GLubyte Helvetica18_Character_198[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 96,255,128, 96,255,128, 48,192, 0, 48,192, 0, 63,192, 0,
31,192, 0, 24,255, 0, 24,255, 0, 12,192, 0, 12,192, 0, 6,192, 0, 6,192, 0,
3,255,128, 3,255,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_199[] = { 14, 0, 0, 15, 0, 13,128, 1,128,
7, 0, 7,192, 31,240, 56, 56, 48, 24,112, 0, 96, 0, 96, 0, 96, 0, 96, 0,112, 0, 48,
24, 56, 56, 31,240, 7,192, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_200[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,127,192,127,192, 96, 0, 96, 0, 96, 0, 96, 0,127,128,127,128, 96, 0, 96, 0, 96,
0, 96, 0,127,192,127,192, 0, 0, 6, 0, 12, 0, 24, 0};
+static const GLubyte Helvetica18_Character_201[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,127,192,127,192, 96, 0, 96, 0, 96, 0, 96, 0,127,128,127,128, 96, 0, 96, 0, 96,
0, 96, 0,127,192,127,192, 0, 0, 6, 0, 3, 0, 1,128};
+static const GLubyte Helvetica18_Character_202[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,127,192,127,192, 96, 0, 96, 0, 96, 0, 96, 0,127,128,127,128, 96, 0, 96, 0, 96,
0, 96, 0,127,192,127,192, 0, 0, 25,128, 15, 0, 6, 0};
+static const GLubyte Helvetica18_Character_203[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,127,192,127,192, 96, 0, 96, 0, 96, 0, 96, 0,127,128,127,128, 96, 0, 96, 0, 96,
0, 96, 0,127,192,127,192, 0, 0, 25,128, 25,128, 0, 0};
+static const GLubyte Helvetica18_Character_204[] = { 6, 0, 0, 0, 0, 0, 48, 48, 48,
48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 48, 96,192};
+static const GLubyte Helvetica18_Character_205[] = { 6, 0, 0, 0, 0, 0, 48, 48, 48,
48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 48, 24, 12};
+static const GLubyte Helvetica18_Character_206[] = { 6, 0, 0, 0, 0, 0, 48, 48, 48,
48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0,204,120, 48};
+static const GLubyte Helvetica18_Character_207[] = { 6, 0, 0, 0, 0, 0, 48, 48, 48,
48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0,204,204, 0};
+static const GLubyte Helvetica18_Character_208[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,127,128,127,192, 96,224, 96, 96, 96, 48, 96, 48,252, 48,252, 48, 96, 48, 96, 48, 96,
96, 96,224,127,192,127,128, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_209[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 96, 48, 96,112, 96,240, 96,240, 97,176, 99, 48, 99, 48,102, 48,102, 48,108, 48,108,
48,120, 48,112, 48,112, 48, 0, 0, 9,128, 11, 64, 6, 64};
+static const GLubyte Helvetica18_Character_210[] = { 15, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 7,192, 31,240, 56, 56, 48, 24,112, 28, 96, 12, 96, 12, 96, 12, 96, 12,112, 28, 48,
24, 56, 56, 31,240, 7,192, 0, 0, 1,128, 3, 0, 6, 0};
+static const GLubyte Helvetica18_Character_211[] = { 15, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 7,192, 31,240, 56, 56, 48, 24,112, 28, 96, 12, 96, 12, 96, 12, 96, 12,112, 28, 48,
24, 56, 56, 31,240, 7,192, 0, 0, 1,128, 0,192, 0, 96};
+static const GLubyte Helvetica18_Character_212[] = { 15, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 7,192, 31,240, 56, 56, 48, 24,112, 28, 96, 12, 96, 12, 96, 12, 96, 12,112, 28, 48,
24, 56, 56, 31,240, 7,192, 0, 0, 6, 96, 3,192, 1,128};
+static const GLubyte Helvetica18_Character_213[] = { 15, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 7,192, 31,240, 56, 56, 48, 24,112, 28, 96, 12, 96, 12, 96, 12, 96, 12,112, 28, 48,
24, 56, 56, 31,240, 7,192, 0, 0, 4,192, 5,160, 3, 32};
+static const GLubyte Helvetica18_Character_214[] = { 15, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 7,192, 31,240, 56, 56, 48, 24,112, 28, 96, 12, 96, 12, 96, 12, 96, 12,112, 28, 48,
24, 56, 56, 31,240, 7,192, 0, 0, 6,192, 6,192, 0, 0};
+static const GLubyte Helvetica18_Character_215[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,192,192, 97,128, 51, 0, 30, 0, 12, 0, 30, 0, 51, 0, 97,128,192,192, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_216[] = { 15, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,199,192,255,240,120, 56, 56, 24,108, 28,110, 12,103, 12, 99,140, 97,204,112,220,
48,120, 56, 56, 31,252, 7,204, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_217[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 15,128, 63,224, 48, 96, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96,
48, 96, 48, 96, 48, 96, 48, 0, 0, 3, 0, 6, 0, 12, 0};
+static const GLubyte Helvetica18_Character_218[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 15,128, 63,224, 48, 96, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96,
48, 96, 48, 96, 48, 96, 48, 0, 0, 6, 0, 3, 0, 1,128};
+static const GLubyte Helvetica18_Character_219[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 15,128, 63,224, 48, 96, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96,
48, 96, 48, 96, 48, 96, 48, 0, 0, 12,192, 7,128, 3, 0};
+static const GLubyte Helvetica18_Character_220[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 15,128, 63,224, 48, 96, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96,
48, 96, 48, 96, 48, 96, 48, 0, 0, 12,192, 12,192, 0, 0};
+static const GLubyte Helvetica18_Character_221[] = { 14, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 7,128, 12,192, 24, 96, 24, 96, 48,
48, 48, 48, 96, 24, 96, 24, 0, 0, 3, 0, 1,128, 0,192};
+static const GLubyte Helvetica18_Character_222[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 96, 0, 96, 0, 96, 0,127,128,127,192, 96,224, 96, 96, 96, 96,
96,224,127,192,127,128, 96, 0, 96, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_223[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,110, 0,111, 0, 99, 0, 99, 0, 99, 0, 99, 0,110, 0,110, 0, 99, 0, 99, 0, 99,
0, 99, 0, 62, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_224[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 59, 0,119, 0, 99, 0, 99, 0,115, 0, 63, 0, 7, 0, 99, 0,119, 0, 62, 0, 0,
0, 12, 0, 24, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_225[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 59, 0,119, 0, 99, 0, 99, 0,115, 0, 63, 0, 7, 0, 99, 0,119, 0, 62, 0, 0,
0, 24, 0, 12, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_226[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 59, 0,119, 0, 99, 0, 99, 0,115, 0, 63, 0, 7, 0, 99, 0,119, 0, 62, 0, 0,
0, 51, 0, 30, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_227[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 59, 0,119, 0, 99, 0, 99, 0,115, 0, 63, 0, 7, 0, 99, 0,119, 0, 62, 0, 0,
0, 38, 0, 45, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_228[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 59, 0,119, 0, 99, 0, 99, 0,115, 0, 63, 0, 7, 0, 99, 0,119, 0, 62, 0, 0,
0, 54, 0, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_229[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 59, 0,119, 0, 99, 0, 99, 0,115, 0, 63, 0, 7, 0, 99, 0,119, 0, 62, 0, 28,
0, 54, 0, 54, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_230[] = { 15, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 58,240,119,252, 99,140, 99, 0,115, 0, 63,252, 7, 12, 99, 12,119,248, 62,240, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_231[] = { 10, 0, 0, 60, 0, 54, 0, 6, 0,
28, 0, 31, 0, 63,128, 49,128, 96, 0, 96, 0, 96, 0, 96, 0, 49,128, 63,128, 31, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_232[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 30, 0, 63,128,113,128, 96, 0, 96, 0,127,128, 97,128, 97,128, 63, 0, 30, 0, 0,
0, 12, 0, 24, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_233[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 30, 0, 63,128,113,128, 96, 0, 96, 0,127,128, 97,128, 97,128, 63, 0, 30, 0, 0,
0, 12, 0, 6, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_234[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 30, 0, 63,128,113,128, 96, 0, 96, 0,127,128, 97,128, 97,128, 63, 0, 30, 0, 0,
0, 51, 0, 30, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_235[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 30, 0, 63,128,113,128, 96, 0, 96, 0,127,128, 97,128, 97,128, 63, 0, 30, 0, 0,
0, 27, 0, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_236[] = { 4, 0, 0, 0, 0, 0, 96, 96, 96,
96, 96, 96, 96, 96, 96, 96, 0, 48, 96,192, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_237[] = { 4, 0, 0, 0, 0, 0, 96, 96, 96,
96, 96, 96, 96, 96, 96, 96, 0,192, 96, 48, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_238[] = { 4, 0, 0, 0, 0, 0, 96, 96, 96,
96, 96, 96, 96, 96, 96, 96, 0,144,240, 96, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_239[] = { 4, 0, 0, 0, 0, 0, 96, 96, 96,
96, 96, 96, 96, 96, 96, 96, 0,216,216, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_240[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 31, 0, 63,128, 49,128, 96,192, 96,192, 96,192, 96,192, 49,128, 63,128, 31, 0, 38,
0, 28, 0, 27, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_241[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 97,128, 97,128, 97,128, 97,128, 97,128, 97,128, 97,128,113,128,111,128,103, 0, 0,
0, 38, 0, 45, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_242[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 31, 0, 63,128, 49,128, 96,192, 96,192, 96,192, 96,192, 49,128, 63,128, 31, 0, 0,
0, 6, 0, 12, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_243[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 31, 0, 63,128, 49,128, 96,192, 96,192, 96,192, 96,192, 49,128, 63,128, 31, 0, 0,
0, 12, 0, 6, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_244[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 31, 0, 63,128, 49,128, 96,192, 96,192, 96,192, 96,192, 49,128, 63,128, 31, 0, 0,
0, 25,128, 15, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_245[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 31, 0, 63,128, 49,128, 96,192, 96,192, 96,192, 96,192, 49,128, 63,128, 31, 0, 0,
0, 19, 0, 22,128, 12,128, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_246[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 31, 0, 63,128, 49,128, 96,192, 96,192, 96,192, 96,192, 49,128, 63,128, 31, 0, 0,
0, 27, 0, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_247[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 12, 0, 12, 0, 0, 0,127,128,127,128, 0, 0, 12, 0, 12, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_248[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,206, 0,127,128, 49,128,120,192,108,192,102,192, 99,192, 49,128, 63,192, 14, 96, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_249[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 57,128,125,128, 99,128, 97,128, 97,128, 97,128, 97,128, 97,128, 97,128, 97,128, 0,
0, 6, 0, 12, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_250[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 57,128,125,128, 99,128, 97,128, 97,128, 97,128, 97,128, 97,128, 97,128, 97,128, 0,
0, 12, 0, 6, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_251[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 57,128,125,128, 99,128, 97,128, 97,128, 97,128, 97,128, 97,128, 97,128, 97,128, 0,
0, 51, 0, 30, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_252[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 57,128,125,128, 99,128, 97,128, 97,128, 97,128, 97,128, 97,128, 97,128, 97,128, 0,
0, 51, 0, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_253[] = { 10, 0, 0, 56, 0, 56, 0, 12, 0,
12, 0, 12, 0, 12, 0, 30, 0, 18, 0, 51, 0, 51, 0, 51, 0, 97,128, 97,128, 97,128,
0, 0, 12, 0, 6, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_254[] = { 11, 0, 0, 96, 0, 96, 0, 96, 0,
96, 0,111, 0,127,128,113,128, 96,192, 96,192, 96,192, 96,192,113,128,127,128,111, 0,
96, 0, 96, 0, 96, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte Helvetica18_Character_255[] = { 10, 0, 0, 56, 0, 56, 0, 12, 0,
12, 0, 12, 0, 12, 0, 30, 0, 18, 0, 51, 0, 51, 0, 51, 0, 97,128, 97,128, 97,128,
0, 0, 51, 0, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+/* The font characters mapping: */
+static const GLubyte* Helvetica18_Character_Map[] =
{Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,
+
Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,
+
Helvetica18_Character_032,Helvetica18_Character_033,Helvetica18_Character_034,Helvetica18_Character_035,Helvetica18_Character_036,Helvetica18_Character_037,Helvetica18_Character_038,Helvetica18_Character_039,Helvetica18_Character_040,Helvetica18_Character_041,Helvetica18_Character_042,Helvetica18_Character_043,Helvetica18_Character_044,Helvetica18_Character_045,Helvetica18_Character_046,Helvetica18_Character_047,
+
Helvetica18_Character_048,Helvetica18_Character_049,Helvetica18_Character_050,Helvetica18_Character_051,Helvetica18_Character_052,Helvetica18_Character_053,Helvetica18_Character_054,Helvetica18_Character_055,Helvetica18_Character_056,Helvetica18_Character_057,Helvetica18_Character_058,Helvetica18_Character_059,Helvetica18_Character_060,Helvetica18_Character_061,Helvetica18_Character_062,Helvetica18_Character_063,
+
Helvetica18_Character_064,Helvetica18_Character_065,Helvetica18_Character_066,Helvetica18_Character_067,Helvetica18_Character_068,Helvetica18_Character_069,Helvetica18_Character_070,Helvetica18_Character_071,Helvetica18_Character_072,Helvetica18_Character_073,Helvetica18_Character_074,Helvetica18_Character_075,Helvetica18_Character_076,Helvetica18_Character_077,Helvetica18_Character_078,Helvetica18_Character_079,
+
Helvetica18_Character_080,Helvetica18_Character_081,Helvetica18_Character_082,Helvetica18_Character_083,Helvetica18_Character_084,Helvetica18_Character_085,Helvetica18_Character_086,Helvetica18_Character_087,Helvetica18_Character_088,Helvetica18_Character_089,Helvetica18_Character_090,Helvetica18_Character_091,Helvetica18_Character_092,Helvetica18_Character_093,Helvetica18_Character_094,Helvetica18_Character_095,
+
Helvetica18_Character_096,Helvetica18_Character_097,Helvetica18_Character_098,Helvetica18_Character_099,Helvetica18_Character_100,Helvetica18_Character_101,Helvetica18_Character_102,Helvetica18_Character_103,Helvetica18_Character_104,Helvetica18_Character_105,Helvetica18_Character_106,Helvetica18_Character_107,Helvetica18_Character_108,Helvetica18_Character_109,Helvetica18_Character_110,Helvetica18_Character_111,
+
Helvetica18_Character_112,Helvetica18_Character_113,Helvetica18_Character_114,Helvetica18_Character_115,Helvetica18_Character_116,Helvetica18_Character_117,Helvetica18_Character_118,Helvetica18_Character_119,Helvetica18_Character_120,Helvetica18_Character_121,Helvetica18_Character_122,Helvetica18_Character_123,Helvetica18_Character_124,Helvetica18_Character_125,Helvetica18_Character_126,Helvetica18_Character_032,
+
Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,
+
Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,
+
Helvetica18_Character_160,Helvetica18_Character_161,Helvetica18_Character_162,Helvetica18_Character_163,Helvetica18_Character_164,Helvetica18_Character_165,Helvetica18_Character_166,Helvetica18_Character_167,Helvetica18_Character_168,Helvetica18_Character_169,Helvetica18_Character_170,Helvetica18_Character_171,Helvetica18_Character_172,Helvetica18_Character_173,Helvetica18_Character_174,Helvetica18_Character_175,
+
Helvetica18_Character_176,Helvetica18_Character_177,Helvetica18_Character_178,Helvetica18_Character_179,Helvetica18_Character_180,Helvetica18_Character_181,Helvetica18_Character_182,Helvetica18_Character_183,Helvetica18_Character_184,Helvetica18_Character_185,Helvetica18_Character_186,Helvetica18_Character_187,Helvetica18_Character_188,Helvetica18_Character_189,Helvetica18_Character_190,Helvetica18_Character_191,
+
Helvetica18_Character_192,Helvetica18_Character_193,Helvetica18_Character_194,Helvetica18_Character_195,Helvetica18_Character_196,Helvetica18_Character_197,Helvetica18_Character_198,Helvetica18_Character_199,Helvetica18_Character_200,Helvetica18_Character_201,Helvetica18_Character_202,Helvetica18_Character_203,Helvetica18_Character_204,Helvetica18_Character_205,Helvetica18_Character_206,Helvetica18_Character_207,
+
Helvetica18_Character_208,Helvetica18_Character_209,Helvetica18_Character_210,Helvetica18_Character_211,Helvetica18_Character_212,Helvetica18_Character_213,Helvetica18_Character_214,Helvetica18_Character_215,Helvetica18_Character_216,Helvetica18_Character_217,Helvetica18_Character_218,Helvetica18_Character_219,Helvetica18_Character_220,Helvetica18_Character_221,Helvetica18_Character_222,Helvetica18_Character_223,
+
Helvetica18_Character_224,Helvetica18_Character_225,Helvetica18_Character_226,Helvetica18_Character_227,Helvetica18_Character_228,Helvetica18_Character_229,Helvetica18_Character_230,Helvetica18_Character_231,Helvetica18_Character_232,Helvetica18_Character_233,Helvetica18_Character_234,Helvetica18_Character_235,Helvetica18_Character_236,Helvetica18_Character_237,Helvetica18_Character_238,Helvetica18_Character_239,
+
Helvetica18_Character_240,Helvetica18_Character_241,Helvetica18_Character_242,Helvetica18_Character_243,Helvetica18_Character_244,Helvetica18_Character_245,Helvetica18_Character_246,Helvetica18_Character_247,Helvetica18_Character_248,Helvetica18_Character_249,Helvetica18_Character_250,Helvetica18_Character_251,Helvetica18_Character_252,Helvetica18_Character_253,Helvetica18_Character_254,Helvetica18_Character_255,NULL};
+
+/* The font structure: */
+const SFG_Font fgFontHelvetica18 = {
"-adobe-helvetica-medium-r-normal--18-180-75-75-p-98-iso8859-1", 256, 23,
Helvetica18_Character_Map, 0, 5 };
+
+static const GLubyte TimesRoman10_Character_000[] = { 8, 0, 0, 0, 0,170, 0,130,
0,130, 0,170, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_001[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_002[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_003[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_004[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_005[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_006[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_007[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_008[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_009[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_010[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_011[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_012[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_013[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_014[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_015[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_016[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_017[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_018[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_019[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_020[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_021[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_022[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_023[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_024[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_025[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_026[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_027[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_028[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_029[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_030[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_031[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_032[] = { 2, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_033[] = { 3, 0, 0, 0, 0, 64, 0, 64, 64,
64, 64, 64, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_034[] = { 4, 0, 0, 0, 0, 0, 0, 0, 0,
0,160,160, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_035[] = { 5, 0, 0, 0, 0, 80, 80,248,
80,248, 80, 80, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_036[] = { 5, 0, 0, 0, 32,224,144, 16,
96,128,144,112, 32, 0, 0};
+static const GLubyte TimesRoman10_Character_037[] = { 8, 0, 0, 0, 0, 68, 42, 42,
86,168,164,126, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_038[] = { 8, 0, 0, 0,
0,118,141,152,116,110, 80, 48, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_039[] = { 3, 0, 0, 0, 0, 0, 0, 0, 0,
0, 64,192, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_040[] = { 4, 0, 0, 32, 64, 64,128,128,128,
64, 64, 32, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_041[] = { 4, 0, 0,128, 64, 64, 32, 32, 32,
64, 64,128, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_042[] = { 5, 0, 0, 0, 0, 0, 0, 0,
0,160, 64,160, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_043[] = { 6, 0, 0, 0, 0, 32, 32,248, 32,
32, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_044[] = { 3, 0, 0, 64, 64, 64, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_045[] = { 7, 0, 0, 0, 0, 0, 0,120, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_046[] = { 3, 0, 0, 0, 0, 64, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_047[] = { 3, 0, 0, 0, 0,128,128, 64, 64,
64, 32, 32, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_048[] = { 5, 0, 0, 0, 0,
96,144,144,144,144,144, 96, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_049[] = { 5, 0, 0, 0, 0,112, 32, 32, 32,
32, 96, 32, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_050[] = { 5, 0, 0, 0, 0,240, 64, 32, 32,
16,144, 96, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_051[] = { 5, 0, 0, 0, 0,224, 16, 16, 96,
16,144, 96, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_052[] = { 5, 0, 0, 0, 0, 16, 16,248,144,
80, 48, 16, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_053[] = { 5, 0, 0, 0, 0,224,144, 16,
16,224, 64,112, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_054[] = { 5, 0, 0, 0, 0,
96,144,144,144,224, 64, 48, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_055[] = { 5, 0, 0, 0, 0, 64, 64, 64, 32,
32,144,240, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_056[] = { 5, 0, 0, 0, 0, 96,144,144,
96,144,144, 96, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_057[] = { 5, 0, 0, 0, 0,192,
32,112,144,144,144, 96, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_058[] = { 3, 0, 0, 0, 0, 64, 0, 0, 0,
64, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_059[] = { 3, 0, 0, 64, 64, 64, 0, 0, 0,
64, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_060[] = { 5, 0, 0, 0, 0, 16, 32, 64, 32,
16, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_061[] = { 6, 0, 0, 0, 0, 0,248, 0,248,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_062[] = { 5, 0, 0, 0, 0,128, 64, 32,
64,128, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_063[] = { 4, 0, 0, 0, 0, 64, 0, 64, 64,
32,160,224, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_064[] = { 9, 0, 0, 0, 0, 62, 0, 64,
0,146, 0,173, 0,165, 0,165, 0,157, 0, 66, 0, 60, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_065[] = { 8, 0, 0, 0, 0,238, 68,124, 40,
40, 56, 16, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_066[] = { 6, 0, 0, 0, 0,240, 72, 72,112,
72, 72,240, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_067[] = { 7, 0, 0, 0,
0,120,196,128,128,128,196,124, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_068[] = { 7, 0, 0, 0, 0,248, 76, 68, 68,
68, 76,248, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_069[] = { 6, 0, 0, 0, 0,248, 72, 64,112,
64, 72,248, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_070[] = { 6, 0, 0, 0, 0,224, 64, 64,112,
64, 72,248, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_071[] = { 7, 0, 0, 0,
0,120,196,132,156,128,196,124, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_072[] = { 8, 0, 0, 0, 0,238, 68, 68,124,
68, 68,238, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_073[] = { 4, 0, 0, 0, 0,224, 64, 64, 64,
64, 64,224, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_074[] = { 4, 0, 0, 0, 0,192,160, 32, 32,
32, 32,112, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_075[] = { 7, 0, 0, 0, 0,236, 72, 80, 96,
80, 72,236, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_076[] = { 6, 0, 0, 0, 0,248, 72, 64, 64,
64, 64,224, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_077[] = { 10, 0, 0, 0, 0, 0, 0, 0,
0,235,128, 73, 0, 85, 0, 85, 0, 99, 0, 99, 0,227,128, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_078[] = { 8, 0, 0, 0, 0,228, 76, 76, 84,
84,100,238, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_079[] = { 7, 0, 0, 0,
0,120,204,132,132,132,204,120, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_080[] = { 6, 0, 0, 0, 0,224, 64, 64,112,
72, 72,240, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_081[] = { 7, 0, 0, 12,
24,112,204,132,132,132,204,120, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_082[] = { 7, 0, 0, 0, 0,236, 72, 80,112,
72, 72,240, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_083[] = { 5, 0, 0, 0, 0,224,144, 16,
96,192,144,112, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_084[] = { 6, 0, 0, 0, 0,112, 32, 32, 32,
32,168,248, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_085[] = { 8, 0, 0, 0, 0, 56,108, 68, 68,
68, 68,238, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_086[] = { 8, 0, 0, 0, 0, 16, 16, 40,
40,108, 68,238, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_087[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
34, 0, 34, 0, 85, 0, 85, 0,201,128,136,128,221,192, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_088[] = { 8, 0, 0, 0, 0,238, 68, 40, 16,
40, 68,238, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_089[] = { 8, 0, 0, 0, 0, 56, 16, 16, 40,
40, 68,238, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_090[] = { 6, 0, 0, 0, 0,248,136, 64, 32,
16,136,248, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_091[] = { 3, 0,
0,192,128,128,128,128,128,128,128,192, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_092[] = { 3, 0, 0, 0, 0, 32, 32, 64, 64,
64,128,128, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_093[] = { 3, 0, 0,192, 64, 64, 64, 64, 64,
64, 64,192, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_094[] = { 5, 0, 0, 0, 0, 0, 0, 0, 0,
80, 80, 32, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_095[] = { 5, 0,248, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_096[] = { 3, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,192,128, 0, 0};
+static const GLubyte TimesRoman10_Character_097[] = { 4, 0, 0, 0, 0,224,160, 96,
32,192, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_098[] = { 5, 0, 0, 0,
0,224,144,144,144,224,128,128, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_099[] = { 4, 0, 0, 0, 0, 96,128,128,128,
96, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_100[] = { 5, 0, 0, 0,
0,104,144,144,144,112, 16, 48, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_101[] = { 4, 0, 0, 0, 0, 96,128,192,160,
96, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_102[] = { 4, 0, 0, 0, 0,224, 64, 64,
64,224, 64, 48, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_103[] = { 5, 0, 0,224,144, 96,
64,160,160,112, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_104[] = { 5, 0, 0, 0,
0,216,144,144,144,224,128,128, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_105[] = { 3, 0, 0, 0, 0, 64, 64, 64,
64,192, 0, 64, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_106[] = { 3, 0, 0,128, 64, 64, 64, 64,
64,192, 0, 64, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_107[] = { 5, 0, 0, 0,
0,152,144,224,160,144,128,128, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_108[] = { 4, 0, 0, 0, 0,224, 64, 64, 64,
64, 64,192, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_109[] = { 8, 0, 0, 0,
0,219,146,146,146,236, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_110[] = { 5, 0, 0, 0,
0,216,144,144,144,224, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_111[] = { 5, 0, 0, 0, 0, 96,144,144,144,
96, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_112[] = { 5, 0,
0,192,128,224,144,144,144,224, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_113[] = { 5, 0, 0, 56,
16,112,144,144,144,112, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_114[] = { 4, 0, 0, 0, 0,224, 64, 64,
96,160, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_115[] = { 4, 0, 0, 0, 0,224, 32,
96,128,224, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_116[] = { 4, 0, 0, 0, 0, 48, 64, 64,
64,224, 64, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_117[] = { 5, 0, 0, 0,
0,104,144,144,144,144, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_118[] = { 5, 0, 0, 0, 0, 32, 96,
80,144,216, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_119[] = { 8, 0, 0, 0, 0, 40,108,
84,146,219, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_120[] = { 6, 0, 0, 0, 0,216, 80, 32,
80,216, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_121[] = { 5, 0, 0,128,128, 64,
96,160,144,184, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_122[] = { 5, 0, 0, 0, 0,240,144, 64,
32,240, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_123[] = { 4, 0, 0, 32, 64, 64, 64,128, 64,
64, 64, 32, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_124[] = { 2, 0,
0,128,128,128,128,128,128,128,128,128, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_125[] = { 4, 0, 0,128, 64, 64, 64, 32, 64,
64, 64,128, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_126[] = { 7, 0, 0, 0, 0, 0, 0,152,100,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_127[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_128[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_129[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_130[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_131[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_132[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_133[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_134[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_135[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_136[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_137[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_138[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_139[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_140[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_141[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_142[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_143[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_144[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_145[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_146[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_147[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_148[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_149[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_150[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_151[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_152[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_153[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_154[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_155[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_156[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_157[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_158[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_159[] = { 13, 0, 0, 0, 0, 0, 0, 0,
0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_160[] = { 2, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_161[] = { 3, 0, 0, 64, 64, 64, 64, 64, 0,
64, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_162[] = { 5, 0, 0,
0,128,224,144,128,144,112, 16, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_163[] = { 5, 0, 0, 0, 0,240,200, 64,224,
64, 80, 48, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_164[] = { 5, 0, 0, 0, 0, 0,136,112, 80,
80,112,136, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_165[] = { 5, 0, 0, 0, 0,112, 32,248,
32,216, 80,136, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_166[] = { 2, 0, 0, 0, 0,128,128,128,
0,128,128,128, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_167[] = { 5, 0, 0, 0,224,144, 32,
80,144,160, 64,144,112, 0, 0};
+static const GLubyte TimesRoman10_Character_168[] = { 5, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 80, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_169[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
28, 0, 34, 0, 77, 0, 81, 0, 77, 0, 34, 0, 28, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_170[] = { 4, 0, 0, 0, 0, 0, 0,224,
0,160, 32,192, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_171[] = { 5, 0, 0, 0, 0, 0, 80,160,160,
80, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_172[] = { 7, 0, 0, 0, 0, 0, 4, 4,124,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_173[] = { 4, 0, 0, 0, 0, 0, 0,224, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_174[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
28, 0, 34, 0, 85, 0, 89, 0, 93, 0, 34, 0, 28, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_175[] = { 4, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,224, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_176[] = { 4, 0, 0, 0, 0, 0, 0, 0,
96,144,144, 96, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_177[] = { 6, 0, 0, 0, 0,248, 0, 32,
32,248, 32, 32, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_178[] = { 3, 0, 0, 0, 0, 0, 0, 0,224,
64,160, 96, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_179[] = { 3, 0, 0, 0, 0, 0, 0, 0,192,
32, 64,224, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_180[] = { 3, 0, 0, 0, 0, 0, 0, 0, 0,
0,128, 64, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_181[] = { 5, 0,
0,128,128,232,144,144,144,144, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_182[] = { 6, 0, 0, 40, 40, 40,
40,104,232,232,232,124, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_183[] = { 2, 0, 0, 0, 0, 0, 0,128, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_184[] = { 4, 0,192, 32, 64, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_185[] = { 3, 0, 0, 0, 0, 0, 0, 0,224,
64,192, 64, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_186[] = { 4, 0, 0, 0, 0, 0, 0,224, 0,
64,160, 64, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_187[] = { 5, 0, 0, 0, 0, 0,160, 80,
80,160, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_188[] = { 8, 0, 0, 0, 0, 68, 62, 44,244,
72,200, 68, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_189[] = { 8, 0, 0, 0, 0, 78, 36, 42,246,
72,200, 68, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_190[] = { 8, 0, 0, 0, 0, 68, 62, 44,212,
40, 72,228, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_191[] = { 4, 0, 0,224,160,128, 64, 64, 0,
64, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_192[] = { 8, 0, 0, 0, 0,238, 68,124, 40,
40, 56, 16, 0, 16, 32};
+static const GLubyte TimesRoman10_Character_193[] = { 8, 0, 0, 0, 0,238, 68,124, 40,
40, 56, 16, 0, 16, 8};
+static const GLubyte TimesRoman10_Character_194[] = { 8, 0, 0, 0, 0,238, 68,124, 40,
40, 56, 16, 0, 40, 16};
+static const GLubyte TimesRoman10_Character_195[] = { 8, 0, 0, 0, 0,238, 68,124, 40,
40, 56, 16, 0, 40, 20};
+static const GLubyte TimesRoman10_Character_196[] = { 8, 0, 0, 0, 0,238, 68,124, 40,
40, 56, 16, 0, 40, 0};
+static const GLubyte TimesRoman10_Character_197[] = { 8, 0, 0, 0, 0,238, 68,124, 40,
40, 56, 16, 16, 40, 16};
+static const GLubyte TimesRoman10_Character_198[] = { 9, 0, 0, 0, 0, 0, 0, 0,
0,239, 0, 73, 0,120, 0, 46, 0, 40, 0, 57, 0, 31, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_199[] = { 7, 0, 96, 16,
32,120,196,128,128,128,196,124, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_200[] = { 6, 0, 0, 0, 0,248, 72, 64,112,
64, 72,248, 0, 32, 64};
+static const GLubyte TimesRoman10_Character_201[] = { 6, 0, 0, 0, 0,248, 72, 64,112,
64, 72,248, 0, 32, 16};
+static const GLubyte TimesRoman10_Character_202[] = { 6, 0, 0, 0, 0,248, 72, 64,112,
64, 72,248, 0, 80, 32};
+static const GLubyte TimesRoman10_Character_203[] = { 6, 0, 0, 0, 0,248, 72, 64,112,
64, 72,248, 0, 80, 0};
+static const GLubyte TimesRoman10_Character_204[] = { 4, 0, 0, 0, 0,224, 64, 64, 64,
64, 64,224, 0, 64,128};
+static const GLubyte TimesRoman10_Character_205[] = { 4, 0, 0, 0, 0,224, 64, 64, 64,
64, 64,224, 0, 64, 32};
+static const GLubyte TimesRoman10_Character_206[] = { 4, 0, 0, 0, 0,224, 64, 64, 64,
64, 64,224, 0,160, 64};
+static const GLubyte TimesRoman10_Character_207[] = { 4, 0, 0, 0, 0,224, 64, 64, 64,
64, 64,224, 0,160, 0};
+static const GLubyte TimesRoman10_Character_208[] = { 7, 0, 0, 0, 0,248, 76, 68,228,
68, 76,248, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_209[] = { 8, 0, 0, 0, 0,228, 76, 76, 84,
84,100,238, 0, 80, 40};
+static const GLubyte TimesRoman10_Character_210[] = { 7, 0, 0, 0,
0,120,204,132,132,132,204,120, 0, 32, 64};
+static const GLubyte TimesRoman10_Character_211[] = { 7, 0, 0, 0,
0,120,204,132,132,132,204,120, 0, 16, 8};
+static const GLubyte TimesRoman10_Character_212[] = { 7, 0, 0, 0,
0,120,204,132,132,132,204,120, 0, 80, 32};
+static const GLubyte TimesRoman10_Character_213[] = { 7, 0, 0, 0,
0,120,204,132,132,132,204,120, 0, 80, 40};
+static const GLubyte TimesRoman10_Character_214[] = { 7, 0, 0, 0,
0,120,204,132,132,132,204,120, 0, 80, 0};
+static const GLubyte TimesRoman10_Character_215[] = { 6, 0, 0, 0, 0,136, 80, 32,
80,136, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_216[] = { 8, 0, 0, 0,128,124,102, 82, 82,
74,102, 62, 1, 0, 0};
+static const GLubyte TimesRoman10_Character_217[] = { 8, 0, 0, 0, 0, 56,108, 68, 68,
68, 68,238, 0, 16, 32};
+static const GLubyte TimesRoman10_Character_218[] = { 8, 0, 0, 0, 0, 56,108, 68, 68,
68, 68,238, 0, 16, 8};
+static const GLubyte TimesRoman10_Character_219[] = { 8, 0, 0, 0, 0, 56,108, 68, 68,
68, 68,238, 0, 40, 16};
+static const GLubyte TimesRoman10_Character_220[] = { 8, 0, 0, 0, 0, 56,108, 68, 68,
68, 68,238, 0, 40, 0};
+static const GLubyte TimesRoman10_Character_221[] = { 8, 0, 0, 0, 0, 56, 16, 16, 40,
40, 68,238, 0, 16, 8};
+static const GLubyte TimesRoman10_Character_222[] = { 6, 0, 0, 0, 0,224, 64,112,
72,112, 64,224, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_223[] = { 5, 0, 0, 0, 0,224, 80, 80, 96,
80, 80, 32, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_224[] = { 4, 0, 0, 0, 0,224,160, 96,
32,192, 0, 64,128, 0, 0};
+static const GLubyte TimesRoman10_Character_225[] = { 4, 0, 0, 0, 0,224,160, 96,
32,192, 0, 64, 32, 0, 0};
+static const GLubyte TimesRoman10_Character_226[] = { 4, 0, 0, 0, 0,224,160, 96,
32,192, 0,160, 64, 0, 0};
+static const GLubyte TimesRoman10_Character_227[] = { 4, 0, 0, 0, 0,224,160, 96,
32,192, 0,160, 80, 0, 0};
+static const GLubyte TimesRoman10_Character_228[] = { 4, 0, 0, 0, 0,224,160, 96,
32,192, 0,160, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_229[] = { 4, 0, 0, 0, 0,224,160, 96,
32,192, 64,160, 64, 0, 0};
+static const GLubyte TimesRoman10_Character_230[] = { 6, 0, 0, 0, 0,216,160,112,
40,216, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_231[] = { 4, 0,192, 32, 64, 96,128,128,128,
96, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_232[] = { 4, 0, 0, 0, 0, 96,128,192,160,
96, 0, 64,128, 0, 0};
+static const GLubyte TimesRoman10_Character_233[] = { 4, 0, 0, 0, 0, 96,128,192,160,
96, 0, 64, 32, 0, 0};
+static const GLubyte TimesRoman10_Character_234[] = { 4, 0, 0, 0, 0, 96,128,192,160,
96, 0,160, 64, 0, 0};
+static const GLubyte TimesRoman10_Character_235[] = { 4, 0, 0, 0, 0, 96,128,192,160,
96, 0,160, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_236[] = { 4, 0, 0, 0, 0,224, 64, 64,
64,192, 0, 64,128, 0, 0};
+static const GLubyte TimesRoman10_Character_237[] = { 4, 0, 0, 0, 0,224, 64, 64,
64,192, 0, 64, 32, 0, 0};
+static const GLubyte TimesRoman10_Character_238[] = { 4, 0, 0, 0, 0,224, 64, 64,
64,192, 0,160, 64, 0, 0};
+static const GLubyte TimesRoman10_Character_239[] = { 4, 0, 0, 0, 0,224, 64, 64,
64,192, 0,160, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_240[] = { 5, 0, 0, 0, 0,
96,144,144,144,112,160,112, 64, 0, 0};
+static const GLubyte TimesRoman10_Character_241[] = { 5, 0, 0, 0,
0,216,144,144,144,224, 0,160, 80, 0, 0};
+static const GLubyte TimesRoman10_Character_242[] = { 5, 0, 0, 0, 0, 96,144,144,144,
96, 0, 32, 64, 0, 0};
+static const GLubyte TimesRoman10_Character_243[] = { 5, 0, 0, 0, 0, 96,144,144,144,
96, 0, 64, 32, 0, 0};
+static const GLubyte TimesRoman10_Character_244[] = { 5, 0, 0, 0, 0, 96,144,144,144,
96, 0,160, 64, 0, 0};
+static const GLubyte TimesRoman10_Character_245[] = { 5, 0, 0, 0, 0, 96,144,144,144,
96, 0,160, 80, 0, 0};
+static const GLubyte TimesRoman10_Character_246[] = { 5, 0, 0, 0, 0, 96,144,144,144,
96, 0,160, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_247[] = { 6, 0, 0, 0, 0, 32, 0,248, 0,
32, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_248[] = { 5, 0, 0, 0,
0,224,144,144,144,112, 8, 0, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_249[] = { 5, 0, 0, 0,
0,104,144,144,144,144, 0, 32, 64, 0, 0};
+static const GLubyte TimesRoman10_Character_250[] = { 5, 0, 0, 0,
0,104,144,144,144,144, 0, 64, 32, 0, 0};
+static const GLubyte TimesRoman10_Character_251[] = { 5, 0, 0, 0,
0,104,144,144,144,144, 0, 80, 32, 0, 0};
+static const GLubyte TimesRoman10_Character_252[] = { 5, 0, 0, 0,
0,104,144,144,144,144, 0, 80, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_253[] = { 5, 0, 0,128,192, 64,
96,160,144,184, 0, 32, 16, 0, 0};
+static const GLubyte TimesRoman10_Character_254[] = { 5, 0,
0,192,128,224,144,144,144,224,128,128, 0, 0, 0};
+static const GLubyte TimesRoman10_Character_255[] = { 5, 0, 0,128,192, 64,
96,160,144,184, 0,160, 0, 0, 0};
+
+/* The font characters mapping: */
+static const GLubyte* TimesRoman10_Character_Map[] =
{TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,
+
TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,
+
TimesRoman10_Character_032,TimesRoman10_Character_033,TimesRoman10_Character_034,TimesRoman10_Character_035,TimesRoman10_Character_036,TimesRoman10_Character_037,TimesRoman10_Character_038,TimesRoman10_Character_039,TimesRoman10_Character_040,TimesRoman10_Character_041,TimesRoman10_Character_042,TimesRoman10_Character_043,TimesRoman10_Character_044,TimesRoman10_Character_045,TimesRoman10_Character_046,TimesRoman10_Character_047,
+
TimesRoman10_Character_048,TimesRoman10_Character_049,TimesRoman10_Character_050,TimesRoman10_Character_051,TimesRoman10_Character_052,TimesRoman10_Character_053,TimesRoman10_Character_054,TimesRoman10_Character_055,TimesRoman10_Character_056,TimesRoman10_Character_057,TimesRoman10_Character_058,TimesRoman10_Character_059,TimesRoman10_Character_060,TimesRoman10_Character_061,TimesRoman10_Character_062,TimesRoman10_Character_063,
+
TimesRoman10_Character_064,TimesRoman10_Character_065,TimesRoman10_Character_066,TimesRoman10_Character_067,TimesRoman10_Character_068,TimesRoman10_Character_069,TimesRoman10_Character_070,TimesRoman10_Character_071,TimesRoman10_Character_072,TimesRoman10_Character_073,TimesRoman10_Character_074,TimesRoman10_Character_075,TimesRoman10_Character_076,TimesRoman10_Character_077,TimesRoman10_Character_078,TimesRoman10_Character_079,
+
TimesRoman10_Character_080,TimesRoman10_Character_081,TimesRoman10_Character_082,TimesRoman10_Character_083,TimesRoman10_Character_084,TimesRoman10_Character_085,TimesRoman10_Character_086,TimesRoman10_Character_087,TimesRoman10_Character_088,TimesRoman10_Character_089,TimesRoman10_Character_090,TimesRoman10_Character_091,TimesRoman10_Character_092,TimesRoman10_Character_093,TimesRoman10_Character_094,TimesRoman10_Character_095,
+
TimesRoman10_Character_096,TimesRoman10_Character_097,TimesRoman10_Character_098,TimesRoman10_Character_099,TimesRoman10_Character_100,TimesRoman10_Character_101,TimesRoman10_Character_102,TimesRoman10_Character_103,TimesRoman10_Character_104,TimesRoman10_Character_105,TimesRoman10_Character_106,TimesRoman10_Character_107,TimesRoman10_Character_108,TimesRoman10_Character_109,TimesRoman10_Character_110,TimesRoman10_Character_111,
+
TimesRoman10_Character_112,TimesRoman10_Character_113,TimesRoman10_Character_114,TimesRoman10_Character_115,TimesRoman10_Character_116,TimesRoman10_Character_117,TimesRoman10_Character_118,TimesRoman10_Character_119,TimesRoman10_Character_120,TimesRoman10_Character_121,TimesRoman10_Character_122,TimesRoman10_Character_123,TimesRoman10_Character_124,TimesRoman10_Character_125,TimesRoman10_Character_126,TimesRoman10_Character_032,
+
TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,
+
TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,
+
TimesRoman10_Character_160,TimesRoman10_Character_161,TimesRoman10_Character_162,TimesRoman10_Character_163,TimesRoman10_Character_164,TimesRoman10_Character_165,TimesRoman10_Character_166,TimesRoman10_Character_167,TimesRoman10_Character_168,TimesRoman10_Character_169,TimesRoman10_Character_170,TimesRoman10_Character_171,TimesRoman10_Character_172,TimesRoman10_Character_173,TimesRoman10_Character_174,TimesRoman10_Character_175,
+
TimesRoman10_Character_176,TimesRoman10_Character_177,TimesRoman10_Character_178,TimesRoman10_Character_179,TimesRoman10_Character_180,TimesRoman10_Character_181,TimesRoman10_Character_182,TimesRoman10_Character_183,TimesRoman10_Character_184,TimesRoman10_Character_185,TimesRoman10_Character_186,TimesRoman10_Character_187,TimesRoman10_Character_188,TimesRoman10_Character_189,TimesRoman10_Character_190,TimesRoman10_Character_191,
+
TimesRoman10_Character_192,TimesRoman10_Character_193,TimesRoman10_Character_194,TimesRoman10_Character_195,TimesRoman10_Character_196,TimesRoman10_Character_197,TimesRoman10_Character_198,TimesRoman10_Character_199,TimesRoman10_Character_200,TimesRoman10_Character_201,TimesRoman10_Character_202,TimesRoman10_Character_203,TimesRoman10_Character_204,TimesRoman10_Character_205,TimesRoman10_Character_206,TimesRoman10_Character_207,
+
TimesRoman10_Character_208,TimesRoman10_Character_209,TimesRoman10_Character_210,TimesRoman10_Character_211,TimesRoman10_Character_212,TimesRoman10_Character_213,TimesRoman10_Character_214,TimesRoman10_Character_215,TimesRoman10_Character_216,TimesRoman10_Character_217,TimesRoman10_Character_218,TimesRoman10_Character_219,TimesRoman10_Character_220,TimesRoman10_Character_221,TimesRoman10_Character_222,TimesRoman10_Character_223,
+
TimesRoman10_Character_224,TimesRoman10_Character_225,TimesRoman10_Character_226,TimesRoman10_Character_227,TimesRoman10_Character_228,TimesRoman10_Character_229,TimesRoman10_Character_230,TimesRoman10_Character_231,TimesRoman10_Character_232,TimesRoman10_Character_233,TimesRoman10_Character_234,TimesRoman10_Character_235,TimesRoman10_Character_236,TimesRoman10_Character_237,TimesRoman10_Character_238,TimesRoman10_Character_239,
+
TimesRoman10_Character_240,TimesRoman10_Character_241,TimesRoman10_Character_242,TimesRoman10_Character_243,TimesRoman10_Character_244,TimesRoman10_Character_245,TimesRoman10_Character_246,TimesRoman10_Character_247,TimesRoman10_Character_248,TimesRoman10_Character_249,TimesRoman10_Character_250,TimesRoman10_Character_251,TimesRoman10_Character_252,TimesRoman10_Character_253,TimesRoman10_Character_254,TimesRoman10_Character_255,NULL};
+
+/* The font structure: */
+const SFG_Font fgFontTimesRoman10 = {
"-adobe-times-medium-r-normal--10-100-75-75-p-54-iso8859-1", 256, 14,
TimesRoman10_Character_Map, 0, 4 };
+
+static const GLubyte TimesRoman24_Character_000[] = { 19, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 64, 0, 64,
0, 0, 0, 64, 0, 64, 0, 0, 0, 64, 0, 64, 0, 0, 0, 64, 0, 64, 0, 0, 0, 64, 0,
64, 0, 0, 0, 64, 0, 64, 0, 0, 0, 64, 0, 64, 0, 0, 0, 85, 85, 64, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_001[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_002[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_003[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_004[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_005[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_006[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_007[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_008[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_009[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_010[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_011[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_012[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_013[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_014[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_015[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_016[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_017[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_018[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_019[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_020[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_021[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_022[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_023[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_024[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_025[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_026[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_027[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_028[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_029[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_030[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_031[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_032[] = { 6, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_033[] = { 8, 0, 0, 0, 0, 0, 0, 0, 24,
24, 0, 0, 0, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_034[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 68, 0,102, 0,102, 0,102, 0,102, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_035[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 17, 0, 17, 0, 17, 0, 17, 0, 17, 0,127,224,127,224, 8,128,
8,128, 8,128, 63,240, 63,240, 4, 64, 4, 64, 4, 64, 4, 64, 4, 64, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_036[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 4, 0, 4, 0, 63, 0,229,192,196,192,132, 96,132, 96, 4, 96, 4,224, 7,192,
7,128, 30, 0, 60, 0,116, 0,100, 0,100, 32,100, 96, 52,224, 31,128, 4, 0, 4, 0, 0,
0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_037[] = { 19, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 30, 0, 12, 57, 0, 6, 48,128,
2, 48, 64, 3, 48, 64, 1,152, 64, 0,140,192, 0,199,128, 60, 96, 0,114, 32, 0, 97, 48,
0, 96,152, 0, 96,136, 0, 48,140, 0, 25,254, 0, 15, 6, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_038[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 0, 63,191, 0,112,240,128,
96, 96, 0, 96,224, 0, 96,208, 0, 49,144, 0, 27,136, 0, 15, 12, 0, 7, 31, 0,
7,128, 0, 14,192, 0, 12, 96, 0, 12, 32, 0, 12, 32, 0, 6, 96, 0, 3,192, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_039[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 12, 4, 28, 24, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_040[] = { 8, 0, 0, 2, 4, 8, 24, 16, 48,
48, 96, 96, 96, 96, 96, 96, 96, 96, 48, 48, 16, 24, 8, 4, 2, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_041[] = { 8, 0, 0, 64, 32, 16, 24, 8, 12,
12, 6, 6, 6, 6, 6, 6, 6, 6, 12, 12, 8, 24, 16, 32, 64, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_042[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2, 0, 7, 0, 50, 96, 58,224, 7, 0, 58,224, 50, 96, 7, 0, 2, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_043[] = { 14, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0,127,248,127,248,
3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_044[] = { 7, 0, 0, 0, 0, 48, 24, 8, 56,
48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_045[] = { 14, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127,248,127,248,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_046[] = { 6, 0, 0, 0, 0, 0, 0, 0, 48,
48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_047[] = { 7, 0, 0, 0, 0,192,192,192, 64,
96, 96, 32, 48, 48, 16, 24, 24, 8, 12, 12, 4, 6, 6, 6, 6, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_048[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 15, 0, 25,128, 48,192, 48,192,112,224, 96, 96, 96, 96, 96, 96,
96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 48,192, 48,192, 25,128, 15, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_049[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 63,192, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0,
6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 30, 0, 6, 0, 2, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_050[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,127,192,127,224, 48, 32, 24, 0, 12, 0, 6, 0, 2, 0, 3, 0,
1,128, 1,128, 0,192, 0,192, 64,192, 64,192, 33,192, 63,128, 14, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_051[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 60, 0,115, 0, 97,128, 0,128, 0,192, 0,192, 0,192, 1,192,
3,128, 15, 0, 6, 0, 3, 0, 65,128, 65,128, 35,128, 63, 0, 14, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_052[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1,128, 1,128, 1,128, 1,128,127,224,127,224, 97,128, 33,128,
49,128, 17,128, 25,128, 9,128, 13,128, 5,128, 3,128, 3,128, 1,128, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_053[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 63, 0,113,192, 96,192, 0, 96, 0, 96, 0, 96, 0, 96, 0,224,
1,192, 7,192, 63, 0, 60, 0, 48, 0, 16, 0, 16, 0, 15,192, 15,224, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_054[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 15, 0, 61,192, 48,192,112, 96, 96, 96, 96, 96, 96, 96, 96, 96,
96,192,121,192,119, 0, 48, 0, 56, 0, 24, 0, 12, 0, 7, 0, 1,224, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_055[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 12, 0, 12, 0, 6, 0, 6, 0, 6, 0, 2, 0, 3, 0, 3, 0,
1, 0, 1,128, 1,128, 0,128, 0,192, 64,192, 96, 96,127,224, 63,224, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_056[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 15, 0, 57,192,112,192, 96, 96, 96, 96, 96, 96, 32,224, 48,192,
27,128, 15, 0, 15, 0, 25,128, 48,192, 48,192, 48,192, 25,128, 15, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_057[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,120, 0, 14, 0, 3, 0, 1,128, 1,192, 0,192, 14,192, 57,224,
48,224, 96, 96, 96, 96, 96, 96, 96, 96, 96,224, 48,192, 59,192, 15, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_058[] = { 6, 0, 0, 0, 0, 0, 0, 0, 48,
48, 0, 0, 0, 0, 0, 0, 0, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_059[] = { 7, 0, 0, 0, 0, 48, 24, 8, 56,
48, 0, 0, 0, 0, 0, 0, 0, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_060[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 0,224, 3,128, 14, 0, 56, 0, 96, 0, 56, 0,
14, 0, 3,128, 0,224, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_061[] = { 14, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127,248,127,248, 0, 0, 0,
0,127,248,127,248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_062[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 56, 0, 14, 0, 3,128, 0,224, 0, 48, 0,224,
3,128, 14, 0, 56, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_063[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 12, 0, 12, 0, 0, 0, 0, 0, 4, 0, 4, 0, 4, 0, 6, 0,
6, 0, 3, 0, 3,128, 1,192, 48,192, 48,192, 32,192, 49,128, 31, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_064[] = { 22, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0,252, 0, 3,131, 0, 6, 0, 0, 12, 0, 0, 24,119,128, 24,222,192,
49,142, 96, 49,134, 32, 49,134, 48, 49,134, 16, 49,131, 16, 48,195, 16, 48,227, 16,
56,127, 16, 24, 59, 48, 28, 0, 32, 14, 0, 96, 7, 0,192, 3,195,128, 0,254, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_065[] = { 17, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,252, 31,128, 48, 6, 0, 16, 6, 0,
16, 12, 0, 24, 12, 0, 8, 12, 0, 15,248, 0, 12, 24, 0, 4, 24, 0, 4, 48, 0, 6,
48, 0, 2, 48, 0, 2, 96, 0, 1, 96, 0, 1,192, 0, 1,192, 0, 0,128, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_066[] = { 16, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,127,240, 24, 60, 24, 12, 24, 6, 24, 6, 24, 6, 24, 12, 24, 28,
31,240, 24, 32, 24, 24, 24, 12, 24, 12, 24, 12, 24, 24, 24, 56,127,224, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_067[] = { 16, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 3,240, 15, 28, 28, 4, 48, 2, 48, 0, 96, 0, 96, 0, 96, 0,
96, 0, 96, 0, 96, 0, 96, 0, 48, 2, 48, 2, 28, 6, 14, 30, 3,242, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_068[] = { 17, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127,224, 0, 24, 56, 0, 24, 28, 0,
24, 6, 0, 24, 6, 0, 24, 3, 0, 24, 3, 0, 24, 3, 0, 24, 3, 0, 24, 3, 0, 24,
3, 0, 24, 3, 0, 24, 6, 0, 24, 6, 0, 24, 28, 0, 24, 56, 0,127,224, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_069[] = { 15, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,127,252, 24, 12, 24, 4, 24, 4, 24, 0, 24, 0, 24, 32, 24, 32,
31,224, 24, 32, 24, 32, 24, 0, 24, 0, 24, 8, 24, 8, 24, 24,127,248, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_070[] = { 14, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,126, 0, 24, 0, 24, 0, 24, 0, 24, 0, 24, 0, 24, 16, 24, 16,
31,240, 24, 16, 24, 16, 24, 0, 24, 0, 24, 8, 24, 8, 24, 24,127,248, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_071[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,240, 0, 15, 28, 0, 28, 14, 0,
48, 6, 0, 48, 6, 0, 96, 6, 0, 96, 6, 0, 96, 31,128, 96, 0, 0, 96, 0, 0, 96,
0, 0, 96, 0, 0, 48, 2, 0, 48, 2, 0, 28, 6, 0, 14, 30, 0, 3,242, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_072[] = { 19, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 15,192, 24, 3, 0, 24, 3, 0,
24, 3, 0, 24, 3, 0, 24, 3, 0, 24, 3, 0, 24, 3, 0, 31,255, 0, 24, 3, 0, 24,
3, 0, 24, 3, 0, 24, 3, 0, 24, 3, 0, 24, 3, 0, 24, 3, 0,126, 15,192, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_073[] = { 8, 0, 0, 0, 0, 0, 0, 0,126,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,126, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_074[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 60, 0,102, 0, 99, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0,
3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 15,192, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_075[] = { 17, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 15,128, 24, 7, 0, 24, 14, 0,
24, 28, 0, 24, 56, 0, 24,112, 0, 24,224, 0, 25,192, 0, 31,128, 0, 31, 0, 0,
25,128, 0, 24,192, 0, 24, 96, 0, 24, 48, 0, 24, 24, 0, 24, 12, 0,126, 63, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_076[] = { 14, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,127,252, 24, 12, 24, 4, 24, 4, 24, 0, 24, 0, 24, 0, 24, 0,
24, 0, 24, 0, 24, 0, 24, 0, 24, 0, 24, 0, 24, 0, 24, 0,126, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_077[] = { 22, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,124, 16,252, 16, 48, 48, 16, 48, 48,
16,104, 48, 16,104, 48, 16,196, 48, 16,196, 48, 17,132, 48, 17,130, 48, 19, 2, 48, 19,
1, 48, 22, 1, 48, 22, 1, 48, 28, 0,176, 28, 0,176, 24, 0,112,120, 0,124, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_078[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,124, 6, 0, 16, 14, 0, 16, 14, 0,
16, 26, 0, 16, 50, 0, 16, 50, 0, 16, 98, 0, 16,194, 0, 16,194, 0, 17,130, 0, 19,
2, 0, 19, 2, 0, 22, 2, 0, 28, 2, 0, 28, 2, 0, 24, 2, 0,120, 15,128, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_079[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,240, 0, 14, 28, 0, 28, 14, 0,
48, 3, 0, 48, 3, 0, 96, 1,128, 96, 1,128, 96, 1,128, 96, 1,128, 96, 1,128, 96,
1,128, 96, 1,128, 48, 3, 0, 48, 3, 0, 28, 14, 0, 14, 28, 0, 3,240, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_080[] = { 15, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,126, 0, 24, 0, 24, 0, 24, 0, 24, 0, 24, 0, 24, 0, 24, 0,
31,224, 24, 56, 24, 24, 24, 12, 24, 12, 24, 12, 24, 24, 24, 56,127,224, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_081[] = { 18, 0, 0, 0, 0, 0, 0, 0,
7,128, 0, 28, 0, 0, 56, 0, 0,112, 0, 0,224, 0, 3,240, 0, 14, 28, 0, 28, 14, 0,
48, 3, 0, 48, 3, 0, 96, 1,128, 96, 1,128, 96, 1,128, 96, 1,128, 96, 1,128, 96,
1,128, 96, 1,128, 48, 3, 0, 48, 3, 0, 28, 14, 0, 14, 28, 0, 3,240, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_082[] = { 16, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,126, 15, 24, 14, 24, 28, 24, 56, 24, 48, 24, 96, 24,224, 25,192,
31,224, 24, 56, 24, 24, 24, 28, 24, 12, 24, 28, 24, 24, 24, 56,127,224, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_083[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 79, 0,120,192, 96, 96, 64, 48, 64, 48, 0, 48, 0,112, 1,224,
7,192, 15, 0, 60, 0,112, 0, 96, 32, 96, 32, 96, 96, 49,224, 15, 32, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_084[] = { 16, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 7,224, 1,128, 1,128, 1,128, 1,128, 1,128, 1,128, 1,128,
1,128, 1,128, 1,128, 1,128, 1,128, 65,130, 65,130, 97,134,127,254, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_085[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,240, 0, 14, 24, 0, 12, 4, 0,
24, 4, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24,
2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0,126, 15,128, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_086[] = { 17, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,128, 0, 1,128, 0, 1,128, 0,
3,192, 0, 3, 64, 0, 3, 96, 0, 6, 32, 0, 6, 32, 0, 6, 48, 0, 12, 16, 0, 12, 24,
0, 24, 8, 0, 24, 8, 0, 24, 12, 0, 48, 4, 0, 48, 6, 0,252, 31,128, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_087[] = { 23, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,131, 0, 1,131, 0, 1,131,128,
3,135,128, 3, 70,128, 3, 70,192, 6, 70, 64, 6, 76, 64, 6, 76, 96, 12, 44, 96, 12, 44,
32, 24, 44, 32, 24, 24, 48, 24, 24, 16, 48, 24, 16, 48, 24, 24,252,126,126, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_088[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,252, 15,192, 48, 3,128, 24, 7, 0,
8, 14, 0, 4, 12, 0, 6, 24, 0, 2, 56, 0, 1,112, 0, 0,224, 0, 0,192, 0, 1,192,
0, 3,160, 0, 3, 16, 0, 6, 8, 0, 14, 12, 0, 28, 6, 0,126, 15,128, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_089[] = { 16, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 7,224, 1,128, 1,128, 1,128, 1,128, 1,128, 1,128, 3,192,
3, 64, 6, 96, 6, 32, 12, 48, 28, 16, 24, 24, 56, 8, 48, 12,252, 63, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_090[] = { 15, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,127,252,112, 12, 56, 4, 24, 4, 28, 0, 12, 0, 14, 0, 7, 0,
3, 0, 3,128, 1,128, 1,192, 0,224, 64, 96, 64,112, 96, 56,127,248, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_091[] = { 8, 0, 0, 0, 62, 48, 48, 48, 48,
48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 62, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_092[] = { 7, 0, 0, 0, 0, 0, 0, 0, 6,
6, 4, 12, 12, 8, 24, 24, 16, 48, 48, 32, 96, 96, 64,192,192, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_093[] = { 8, 0, 0, 0,124, 12, 12, 12, 12,
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,124, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_094[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
64, 64, 96,192, 32,128, 49,128, 17, 0, 27, 0, 10, 0, 14, 0, 4, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_095[] = { 13, 0, 0, 0, 0,255,248,255,248,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_096[] = { 7, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48,112, 64, 96, 48, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_097[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 56,192,125,128, 99,128, 97,128, 97,128, 49,128, 29,128, 7,128,
1,128, 49,128, 51,128, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_098[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 47, 0, 57,192, 48,192, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96,
48, 96, 48,192, 57,192, 55, 0, 48, 0, 48, 0, 48, 0, 48, 0,112, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_099[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 15, 0, 63,128, 56, 64,112, 0, 96, 0, 96, 0, 96, 0, 96, 0,
96, 0, 32,192, 49,192, 15,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_100[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 15, 96, 57,192, 48,192, 96,192, 96,192, 96,192, 96,192, 96,192,
96,192, 48,192, 57,192, 14,192, 0,192, 0,192, 0,192, 0,192, 1,192, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_101[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 15, 0, 63,128, 56, 64,112, 0, 96, 0, 96, 0, 96, 0,127,192,
96,192, 32,192, 49,128, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_102[] = { 7, 0, 0, 0, 0, 0, 0, 0,120,
48, 48, 48, 48, 48, 48, 48, 48, 48, 48,254, 48, 48, 48, 22, 14, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_103[] = { 12, 0, 0, 0, 0, 31,128,120,224,
96, 48, 96, 16, 48, 48, 31,224, 63,128, 48, 0, 24, 0, 31, 0, 25,128, 48,192, 48,192,
48,192, 48,192, 25,128, 15,224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_104[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,120,240, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96,
48, 96, 56,224, 55,192, 51,128, 48, 0, 48, 0, 48, 0, 48, 0,112, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_105[] = { 6, 0, 0, 0, 0, 0, 0, 0,120,
48, 48, 48, 48, 48, 48, 48, 48, 48, 48,112, 0, 0, 0, 48, 48, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_106[] = { 6, 0, 0,192,224, 48, 48, 48, 48,
48, 48, 48, 48, 48, 48, 48, 48, 48, 48,112, 0, 0, 0, 48, 48, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_107[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,121,240, 48,224, 49,192, 51,128, 55, 0, 54, 0, 60, 0, 52, 0,
50, 0, 51, 0, 49,128, 51,224, 48, 0, 48, 0, 48, 0, 48, 0,112, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_108[] = { 6, 0, 0, 0, 0, 0, 0, 0,120,
48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,112, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_109[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,120,241,224, 48, 96,192, 48, 96,192,
48, 96,192, 48, 96,192, 48, 96,192, 48, 96,192, 48, 96,192, 48, 96,192, 56,241,192,
55,207,128,115,135, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_110[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,120,240, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96,
48, 96, 56,224, 55,192,115,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_111[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 15, 0, 57,192, 48,192, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
96, 96, 48,192, 57,192, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_112[] = { 12, 0, 0, 0, 0,120, 0, 48, 0,
48, 0, 48, 0, 48, 0, 55, 0, 57,192, 48,192, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96,
48, 96, 48,192, 57,192,119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_113[] = { 12, 0, 0, 0, 0, 1,224, 0,192,
0,192, 0,192, 0,192, 14,192, 57,192, 48,192, 96,192, 96,192, 96,192, 96,192, 96,192,
96,192, 48,192, 57,192, 14,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_114[] = { 8, 0, 0, 0, 0, 0, 0, 0,120,
48, 48, 48, 48, 48, 48, 48, 48, 59, 55,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_115[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,124, 0, 99, 0, 65,128, 1,128, 3,128, 15, 0, 62, 0, 56,
0,112, 0, 97, 0, 51, 0, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_116[] = { 7, 0, 0, 0, 0, 0, 0, 0, 28,
50, 48, 48, 48, 48, 48, 48, 48, 48, 48,254,112, 48, 16, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_117[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 14,112, 31, 96, 56,224, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96,
48, 96, 48, 96, 48, 96,112,224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_118[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 4, 0, 14, 0, 14, 0, 26, 0, 25, 0, 25, 0, 49, 0, 48,128,
48,128, 96,128, 96,192,241,224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_119[] = { 17, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 16, 0, 14, 56, 0, 14, 56, 0,
26, 40, 0, 26,100, 0, 25,100, 0, 49,100, 0, 48,194, 0, 48,194, 0, 96,194, 0,
96,195, 0,241,231,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_120[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,120,240, 48, 96, 16,192, 25,192, 13,128, 7, 0, 6, 0, 13, 0,
28,128, 24,192, 48, 96,120,240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_121[] = { 11, 0, 0, 0, 0,224, 0,240, 0,
24, 0, 8, 0, 12, 0, 4, 0, 14, 0, 14, 0, 26, 0, 25, 0, 25, 0, 49, 0, 48,128,
48,128, 96,128, 96,192,241,224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_122[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,127,128, 97,128, 48,128, 56, 0, 24, 0, 28, 0, 12, 0, 14, 0,
7, 0, 67, 0, 97,128,127,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_123[] = { 10, 0, 0, 0, 0, 3,128, 6, 0,
12, 0, 12, 0, 12, 0, 12, 0, 12, 0, 12, 0, 8, 0, 24, 0, 16, 0, 96, 0, 16, 0,
24, 0, 8, 0, 12, 0, 12, 0, 12, 0, 12, 0, 12, 0, 6, 0, 3,128, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_124[] = { 6, 0, 0, 0, 0, 0, 0, 0, 48,
48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_125[] = { 10, 0, 0, 0, 0,112, 0, 24, 0,
12, 0, 12, 0, 12, 0, 12, 0, 12, 0, 12, 0, 4, 0, 6, 0, 2, 0, 1,128, 2, 0,
6, 0, 4, 0, 12, 0, 12, 0, 12, 0, 12, 0, 12, 0, 24, 0,112, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_126[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65,192, 99,224, 62, 48,
28, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_127[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_128[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_129[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_130[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_131[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_132[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_133[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_134[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_135[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_136[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_137[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_138[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_139[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_140[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_141[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_142[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_143[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_144[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_145[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_146[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_147[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_148[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_149[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_150[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_151[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_152[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_153[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_154[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_155[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_156[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_157[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_158[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_159[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85,
64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0,
64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0,
0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_160[] = { 6, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_161[] = { 8, 0, 0, 12, 12, 12, 12, 12, 12,
12, 12, 12, 12, 12, 12, 0, 0, 0, 12, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_162[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 32, 0, 32, 0, 31, 0, 63,128, 56, 64,104, 0,100, 0,100, 0,100, 0, 98, 0,
98, 0, 33,192, 49,192, 15,128, 0,128, 0,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_163[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,115,192, 95, 96, 60, 32, 24, 0, 24, 0, 24, 0, 24, 0, 24, 0,
24, 0,126, 0, 24, 0, 24, 0, 24, 0, 24, 0, 24,192, 12,192, 7,128, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_164[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 48,119,112, 63,224, 24,192, 48, 96,
48, 96, 48, 96, 48, 96, 24,192, 63,224,119,112, 96, 48, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_165[] = { 14, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 15,192, 3, 0, 3, 0, 3, 0, 3, 0, 31,224, 3, 0, 31,224,
3, 0, 7,128, 12,128, 12,192, 24, 64, 24, 96, 48, 32,112, 48,248,124, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_166[] = { 6, 0, 0, 0, 0, 0, 0, 0, 48,
48, 48, 48, 48, 48, 48, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_167[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 14, 0, 25, 0, 24,128, 1,128, 3,128, 7, 0, 14, 0, 29, 0, 56,128, 48,192,
32,192, 33,192, 19,128, 15, 0, 14, 0, 28, 0, 24, 0, 17,128, 9,128, 7, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_168[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,102,102, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_169[] = { 19, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,248, 0, 14, 14, 0, 24, 3, 0,
48,225,128, 35,184,128, 98, 12,192, 70, 0, 64, 68, 0, 64, 68, 0, 64, 68, 0, 64, 70,
0, 64, 98, 12,192, 35,152,128, 48,241,128, 24, 3, 0, 14, 14, 0, 3,248, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_170[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,126, 0,118,204,204,124, 12,204,120, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_171[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 2, 32, 6, 96, 12,192, 25,128, 51, 0, 51, 0, 25,128,
12,192, 6, 96, 2, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_172[] = { 14, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 24, 0, 24, 0, 24, 0,
24,127,248,127,248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_173[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127, 0,127, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_174[] = { 19, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,248, 0, 14, 14, 0, 24, 3, 0,
48, 1,128, 35,140,128, 97, 24,192, 65, 16, 64, 65, 32, 64, 65,240, 64, 65, 24, 64, 65,
8, 64, 97, 8,192, 33, 24,128, 51,241,128, 24, 3, 0, 14, 14, 0, 3,248, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_175[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126,126, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_176[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 28, 0, 34, 0, 65, 0, 65, 0, 65, 0, 34, 0, 28, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_177[] = { 14, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,127,248,127,248, 0, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3,
0,127,248,127,248, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_178[] = { 7, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,252, 68, 32, 48, 16, 8, 12,140, 76, 56, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_179[] = { 7, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,112,136,140, 12, 8, 48, 8,140, 76, 56, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_180[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 24, 14, 6, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_181[] = { 13, 0, 0, 0, 0, 32, 0,112, 0,
96, 0, 32, 0, 32, 0, 46,112, 63, 96, 56,224, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96,
48, 96, 48, 96, 48, 96,112,224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_182[] = { 11, 0, 0, 0, 0, 4,128, 4,128,
4,128, 4,128, 4,128, 4,128, 4,128, 4,128, 4,128, 4,128, 4,128, 12,128, 28,128,
60,128, 60,128,124,128,124,128,124,128, 60,128, 60,128, 28,128, 15,192, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_183[] = { 6, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_184[] = { 8, 0, 60,102, 6, 30, 24, 8, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_185[] = { 7, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,124, 16, 16, 16, 16, 16, 16, 80, 48, 16, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_186[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,126, 0, 60,102,102,102,102,102, 60, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_187[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 51, 0, 25,128, 12,192, 6, 96, 6, 96, 12,192,
25,128, 51, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_188[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 2, 0, 8, 2, 0, 12,127,128,
4, 34, 0, 6, 50, 0, 3, 18, 0, 1, 10, 0,125,142, 0, 16,134, 0, 16,194, 0, 16, 96,
0, 16, 32, 0, 16, 48, 0, 16, 16, 0, 80, 24, 0, 48, 12, 0, 16, 4, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_189[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 63, 0, 8, 17, 0, 12, 8, 0,
4, 12, 0, 6, 4, 0, 3, 2, 0, 1, 3, 0,125,163, 0, 16,147, 0, 16,206, 0, 16, 96,
0, 16, 32, 0, 16, 48, 0, 16, 16, 0, 80, 24, 0, 48, 12, 0, 16, 4, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_190[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 2, 0, 8, 2, 0, 12,127,128,
4, 34, 0, 6, 50, 0, 3, 18, 0, 1, 10, 0,113,142, 0,136,134, 0,140,194, 0, 12, 96,
0, 8, 32, 0, 48, 48, 0, 8, 16, 0,140, 24, 0, 76, 12, 0, 56, 4, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_191[] = { 11, 0, 0, 0, 0, 31, 0, 49,128,
96,128, 97,128, 97,128,112, 0, 56, 0, 24, 0, 28, 0, 12, 0, 12, 0, 4, 0, 4, 0,
0, 0, 0, 0, 6, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_192[] = { 17, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,252, 31,128, 48, 6, 0, 16, 6, 0,
16, 12, 0, 24, 12, 0, 8, 12, 0, 15,248, 0, 12, 24, 0, 4, 24, 0, 4, 48, 0, 6,
48, 0, 2, 48, 0, 2, 96, 0, 1, 96, 0, 1,192, 0, 1,192, 0, 0,128, 0, 0, 0,
0, 0, 32, 0, 0,192, 0, 3,128, 0, 3, 0, 0};
+static const GLubyte TimesRoman24_Character_193[] = { 17, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,252, 31,128, 48, 6, 0, 16, 6, 0,
16, 12, 0, 24, 12, 0, 8, 12, 0, 15,248, 0, 12, 24, 0, 4, 24, 0, 4, 48, 0, 6,
48, 0, 2, 48, 0, 2, 96, 0, 1, 96, 0, 1,192, 0, 1,192, 0, 0,128, 0, 0, 0,
0, 1, 0, 0, 0,192, 0, 0,112, 0, 0, 48, 0};
+static const GLubyte TimesRoman24_Character_194[] = { 17, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,252, 31,128, 48, 6, 0, 16, 6, 0,
16, 12, 0, 24, 12, 0, 8, 12, 0, 15,248, 0, 12, 24, 0, 4, 24, 0, 4, 48, 0, 6,
48, 0, 2, 48, 0, 2, 96, 0, 1, 96, 0, 1,192, 0, 1,192, 0, 0,128, 0, 0, 0,
0, 8, 16, 0, 6, 96, 0, 3,192, 0, 1,128, 0};
+static const GLubyte TimesRoman24_Character_195[] = { 17, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,252, 31,128, 48, 7, 0, 16, 6, 0,
16, 12, 0, 24, 12, 0, 8, 12, 0, 15,248, 0, 12, 24, 0, 4, 24, 0, 4, 48, 0, 6,
48, 0, 2, 48, 0, 2, 96, 0, 1, 96, 0, 1,192, 0, 1,192, 0, 0,128, 0, 0, 0,
0, 0, 0, 0, 4,224, 0, 3,144, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_196[] = { 17, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,252, 31,128, 48, 6, 0, 16, 6, 0,
16, 12, 0, 24, 12, 0, 8, 12, 0, 15,248, 0, 12, 24, 0, 4, 24, 0, 4, 48, 0, 6,
48, 0, 2, 48, 0, 2, 96, 0, 1, 96, 0, 1,192, 0, 1,192, 0, 0,128, 0, 0, 0,
0, 0, 0, 0, 6, 48, 0, 6, 48, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_197[] = { 17, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,252, 31,128, 48, 6, 0, 16, 6, 0,
16, 12, 0, 24, 12, 0, 8, 12, 0, 15,248, 0, 12, 24, 0, 4, 24, 0, 4, 48, 0, 6,
48, 0, 2, 48, 0, 2, 96, 0, 1, 96, 0, 1,192, 0, 1,192, 0, 0,128, 0, 1,192,
0, 2, 32, 0, 2, 32, 0, 1,192, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_198[] = { 21, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,249,255,240, 48, 96, 48, 16, 96, 16,
16, 96, 16, 24, 96, 0, 8, 96, 0, 15,224,128, 12, 96,128, 4,127,128, 4, 96,128, 6,
96,128, 2, 96, 0, 2, 96, 0, 1, 96, 32, 1, 96, 32, 1,224, 96, 3,255,224, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_199[] = { 16, 0, 0, 3,192, 6, 96, 0, 96,
1,224, 1,128, 0,128, 3,240, 15, 28, 28, 4, 48, 2, 48, 0, 96, 0, 96, 0, 96, 0,
96, 0, 96, 0, 96, 0, 96, 0, 48, 2, 48, 2, 28, 6, 14, 30, 3,242, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_200[] = { 15, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,127,252, 24, 12, 24, 4, 24, 4, 24, 0, 24, 0, 24, 32, 24, 32,
31,224, 24, 32, 24, 32, 24, 0, 24, 0, 24, 8, 24, 8, 24, 24,127,248, 0, 0, 0,128,
3, 0, 14, 0, 12, 0};
+static const GLubyte TimesRoman24_Character_201[] = { 15, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,127,252, 24, 12, 24, 4, 24, 4, 24, 0, 24, 0, 24, 32, 24, 32,
31,224, 24, 32, 24, 32, 24, 0, 24, 0, 24, 8, 24, 8, 24, 24,127,248, 0, 0, 2, 0,
1,128, 0,224, 0, 96};
+static const GLubyte TimesRoman24_Character_202[] = { 15, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,127,252, 24, 12, 24, 4, 24, 4, 24, 0, 24, 0, 24, 32, 24, 32,
31,224, 24, 32, 24, 32, 24, 0, 24, 0, 24, 8, 24, 8, 24, 24,127,248, 0, 0, 8, 16,
6, 96, 3,192, 1,128};
+static const GLubyte TimesRoman24_Character_203[] = { 15, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,127,252, 24, 12, 24, 4, 24, 4, 24, 0, 24, 0, 24, 32, 24, 32,
31,224, 24, 32, 24, 32, 24, 0, 24, 0, 24, 8, 24, 8, 24, 24,127,248, 0, 0, 0, 0,
12,192, 12,192, 0, 0};
+static const GLubyte TimesRoman24_Character_204[] = { 8, 0, 0, 0, 0, 0, 0, 0,126,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,126, 0, 4, 24,112, 96};
+static const GLubyte TimesRoman24_Character_205[] = { 8, 0, 0, 0, 0, 0, 0, 0,126,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,126, 0, 32, 24, 14, 6};
+static const GLubyte TimesRoman24_Character_206[] = { 8, 0, 0, 0, 0, 0, 0, 0, 63,
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 63, 0, 64, 51, 30, 12};
+static const GLubyte TimesRoman24_Character_207[] = { 8, 0, 0, 0, 0, 0, 0, 0,126,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,126, 0, 0,102,102, 0};
+static const GLubyte TimesRoman24_Character_208[] = { 17, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127,224, 0, 24, 56, 0, 24, 28, 0,
24, 6, 0, 24, 6, 0, 24, 3, 0, 24, 3, 0, 24, 3, 0,255, 3, 0, 24, 3, 0, 24,
3, 0, 24, 3, 0, 24, 6, 0, 24, 6, 0, 24, 28, 0, 24, 56, 0,127,224, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_209[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,124, 6, 0, 16, 14, 0, 16, 14, 0,
16, 26, 0, 16, 50, 0, 16, 50, 0, 16, 98, 0, 16,194, 0, 16,194, 0, 17,130, 0, 19,
2, 0, 19, 2, 0, 22, 2, 0, 28, 2, 0, 28, 2, 0, 24, 2, 0,120, 15,128, 0, 0, 0,
0, 0, 0, 2,112, 0, 1,200, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_210[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,240, 0, 14, 28, 0, 28, 14, 0,
48, 3, 0, 48, 3, 0, 96, 1,128, 96, 1,128, 96, 1,128, 96, 1,128, 96, 1,128, 96,
1,128, 96, 1,128, 48, 3, 0, 48, 3, 0, 28, 14, 0, 14, 28, 0, 3,240, 0, 0, 0, 0,
0, 32, 0, 0,192, 0, 3,128, 0, 3, 0, 0};
+static const GLubyte TimesRoman24_Character_211[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,240, 0, 14, 28, 0, 28, 14, 0,
48, 3, 0, 48, 3, 0, 96, 1,128, 96, 1,128, 96, 1,128, 96, 1,128, 96, 1,128, 96,
1,128, 96, 1,128, 48, 3, 0, 48, 3, 0, 28, 14, 0, 14, 28, 0, 3,240, 0, 0, 0, 0,
0,128, 0, 0, 96, 0, 0, 56, 0, 0, 24, 0};
+static const GLubyte TimesRoman24_Character_212[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,240, 0, 14, 28, 0, 28, 14, 0,
48, 3, 0, 48, 3, 0, 96, 1,128, 96, 1,128, 96, 1,128, 96, 1,128, 96, 1,128, 96,
1,128, 96, 1,128, 48, 3, 0, 48, 3, 0, 28, 14, 0, 14, 28, 0, 3,240, 0, 0, 0, 0,
4, 8, 0, 3, 48, 0, 1,224, 0, 0,192, 0};
+static const GLubyte TimesRoman24_Character_213[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,240, 0, 14, 28, 0, 28, 14, 0,
48, 3, 0, 48, 3, 0, 96, 1,128, 96, 1,128, 96, 1,128, 96, 1,128, 96, 1,128, 96,
1,128, 96, 1,128, 48, 3, 0, 48, 3, 0, 28, 14, 0, 14, 28, 0, 3,240, 0, 0, 0, 0,
0, 0, 0, 2,112, 0, 1,200, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_214[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,240, 0, 14, 28, 0, 28, 14, 0,
48, 3, 0, 48, 3, 0, 96, 1,128, 96, 1,128, 96, 1,128, 96, 1,128, 96, 1,128, 96,
1,128, 96, 1,128, 48, 3, 0, 48, 3, 0, 28, 14, 0, 14, 28, 0, 3,240, 0, 0, 0, 0,
0, 0, 0, 3, 48, 0, 3, 48, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_215[] = { 14, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 32, 16, 48, 48, 24, 96, 12,192, 7,128, 3, 0, 7,128,
12,192, 24, 96, 48, 48, 32, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_216[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 19,240, 0, 14, 28, 0, 28, 14, 0,
52, 3, 0, 50, 3, 0, 97, 1,128, 97, 1,128, 96,129,128, 96,129,128, 96, 65,128, 96,
65,128, 96, 33,128, 48, 35, 0, 48, 19, 0, 28, 14, 0, 14, 28, 0, 3,242, 0, 0, 2,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_217[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,240, 0, 14, 24, 0, 12, 4, 0,
24, 4, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24,
2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0,126, 15,128, 0, 0, 0,
0, 32, 0, 0,192, 0, 3,128, 0, 3, 0, 0};
+static const GLubyte TimesRoman24_Character_218[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,240, 0, 14, 24, 0, 12, 4, 0,
24, 4, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24,
2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0,126, 15,128, 0, 0, 0,
0,128, 0, 0, 96, 0, 0, 56, 0, 0, 24, 0};
+static const GLubyte TimesRoman24_Character_219[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,240, 0, 14, 24, 0, 12, 4, 0,
24, 4, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24,
2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0,126, 15,128, 0, 0, 0,
4, 8, 0, 3, 48, 0, 1,224, 0, 0,192, 0};
+static const GLubyte TimesRoman24_Character_220[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,240, 0, 14, 24, 0, 12, 4, 0,
24, 4, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24,
2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0,126, 15,128, 0, 0, 0,
0, 0, 0, 3, 24, 0, 3, 24, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_221[] = { 16, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 7,224, 1,128, 1,128, 1,128, 1,128, 1,128, 1,128, 3,192,
3, 64, 6, 96, 6, 32, 12, 48, 28, 16, 24, 24, 56, 8, 48, 12,252, 63, 0, 0, 1, 0,
0,192, 0,112, 0, 48};
+static const GLubyte TimesRoman24_Character_222[] = { 15, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,126, 0, 24, 0, 24, 0, 24, 0, 31,224, 24, 56, 24, 24, 24, 12,
24, 12, 24, 12, 24, 24, 24, 56, 31,224, 24, 0, 24, 0, 24, 0,126, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_223[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,115,128, 54, 64, 54, 96, 48, 96, 48, 96, 48,224, 48,192, 49,192,
51,128, 54, 0, 49,128, 48,192, 48,192, 48,192, 48,192, 25,128, 15, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_224[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 56,192,125,128, 99,128, 97,128, 97,128, 49,128, 29,128, 7,128,
1,128, 49,128, 51,128, 31, 0, 0, 0, 2, 0, 12, 0, 56, 0, 48, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_225[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 56,192,125,128, 99,128, 97,128, 97,128, 49,128, 29,128, 7,128,
1,128, 49,128, 51,128, 31, 0, 0, 0, 8, 0, 6, 0, 3,128, 1,128, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_226[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 56,192,125,128, 99,128, 97,128, 97,128, 49,128, 29,128, 7,128,
1,128, 49,128, 51,128, 31, 0, 0, 0, 33, 0, 18, 0, 30, 0, 12, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_227[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 56,192,125,128, 99,128, 97,128, 97,128, 49,128, 29,128, 7,128,
1,128, 49,128, 51,128, 31, 0, 0, 0, 0, 0, 46, 0, 29, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_228[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 56,192,125,128, 99,128, 97,128, 97,128, 49,128, 29,128, 7,128,
1,128, 49,128, 51,128, 31, 0, 0, 0, 0, 0, 51, 0, 51, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_229[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 56,192,125,128, 99,128, 97,128, 97,128, 49,128, 29,128, 7,128,
1,128, 49,128, 51,128, 31, 0, 0, 0, 14, 0, 17, 0, 17, 0, 14, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_230[] = { 16, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 56,120,125,252, 99,194, 97,128, 97,128, 49,128, 29,128, 7,254,
1,134, 49,134, 51,204, 30,120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_231[] = { 11, 0, 0, 30, 0, 51, 0, 3, 0,
15, 0, 12, 0, 4, 0, 15, 0, 63,128, 56, 64,112, 0, 96, 0, 96, 0, 96, 0, 96, 0,
96, 0, 32,192, 49,192, 15,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_232[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 15, 0, 63,128, 56, 64,112, 0, 96, 0, 96, 0, 96, 0,127,192,
96,192, 32,192, 49,128, 15, 0, 0, 0, 2, 0, 12, 0, 56, 0, 48, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_233[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 15, 0, 63,128, 56, 64,112, 0, 96, 0, 96, 0, 96, 0,127,192,
96,192, 32,192, 49,128, 15, 0, 0, 0, 8, 0, 6, 0, 3,128, 1,128, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_234[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 15, 0, 63,128, 56, 64,112, 0, 96, 0, 96, 0, 96, 0,127,192,
96,192, 32,192, 49,128, 15, 0, 0, 0, 16,128, 9, 0, 15, 0, 6, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_235[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 15, 0, 63,128, 56, 64,112, 0, 96, 0, 96, 0, 96, 0,127,192,
96,192, 32,192, 49,128, 15, 0, 0, 0, 0, 0, 25,128, 25,128, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_236[] = { 6, 0, 0, 0, 0, 0, 0, 0,120,
48, 48, 48, 48, 48, 48, 48, 48, 48, 48,112, 0, 8, 48,224,192, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_237[] = { 6, 0, 0, 0, 0, 0, 0, 0,120,
48, 48, 48, 48, 48, 48, 48, 48, 48, 48,112, 0, 64, 48, 28, 12, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_238[] = { 6, 0, 0, 0, 0, 0, 0, 0,120,
48, 48, 48, 48, 48, 48, 48, 48, 48, 48,112, 0,132, 72,120, 48, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_239[] = { 6, 0, 0, 0, 0, 0, 0, 0,120,
48, 48, 48, 48, 48, 48, 48, 48, 48, 48,112, 0, 0,204,204, 0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_240[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 15, 0, 57,192, 48,192, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
96, 96, 48,192, 57,192, 15,128, 99, 0, 30, 0, 15, 0, 56,192, 96, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_241[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,120,240, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96,
48, 96, 56,224, 55,192,115,128, 0, 0, 0, 0, 19,128, 14, 64, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_242[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 15, 0, 57,192, 48,192, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
96, 96, 48,192, 57,192, 15, 0, 0, 0, 1, 0, 6, 0, 28, 0, 24, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_243[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 15, 0, 57,192, 48,192, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
96, 96, 48,192, 57,192, 15, 0, 0, 0, 4, 0, 3, 0, 1,192, 0,192, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_244[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 15, 0, 57,192, 48,192, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
96, 96, 48,192, 57,192, 15, 0, 0, 0, 16,128, 9, 0, 15, 0, 6, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_245[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 15, 0, 57,192, 48,192, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
96, 96, 48,192, 57,192, 15, 0, 0, 0, 0, 0, 19,128, 14, 64, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_246[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 15, 0, 57,192, 48,192, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
96, 96, 48,192, 57,192, 15, 0, 0, 0, 0, 0, 25,128, 25,128, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_247[] = { 14, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 0, 0, 0, 0, 0,127,248,127,248,
0, 0, 0, 0, 3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_248[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 96, 0,111, 0, 57,192, 56,192,104, 96,108, 96,100, 96,102, 96, 98, 96,
99, 96, 49,192, 57,192, 15, 96, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_249[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 14,112, 31, 96, 56,224, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96,
48, 96, 48, 96, 48, 96,112,224, 0, 0, 1, 0, 6, 0, 28, 0, 24, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_250[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 14,112, 31, 96, 56,224, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96,
48, 96, 48, 96, 48, 96,112,224, 0, 0, 4, 0, 3, 0, 1,192, 0,192, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_251[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 14,112, 31, 96, 56,224, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96,
48, 96, 48, 96, 48, 96,112,224, 0, 0, 16,128, 9, 0, 15, 0, 6, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_252[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 14,112, 31, 96, 56,224, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96,
48, 96, 48, 96, 48, 96,112,224, 0, 0, 0, 0, 25,128, 25,128, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_253[] = { 11, 0, 0, 0, 0,224, 0,240, 0,
24, 0, 8, 0, 12, 0, 4, 0, 14, 0, 14, 0, 26, 0, 25, 0, 25, 0, 49, 0, 48,128,
48,128, 96,128, 96,192,241,224, 0, 0, 8, 0, 6, 0, 3,128, 1,128, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_254[] = { 12, 0, 0, 0, 0,120, 0, 48, 0,
48, 0, 48, 0, 48, 0, 55, 0, 57,192, 48,192, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96,
48, 96, 48,192, 57,192, 55, 0, 48, 0, 48, 0, 48, 0, 48, 0,112, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+static const GLubyte TimesRoman24_Character_255[] = { 11, 0, 0, 0, 0,224, 0,240, 0,
24, 0, 8, 0, 12, 0, 4, 0, 14, 0, 14, 0, 26, 0, 25, 0, 25, 0, 49, 0, 48,128,
48,128, 96,128, 96,192,241,224, 0, 0, 0, 0, 51, 0, 51, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
+
+/* The font characters mapping: */
+static const GLubyte* TimesRoman24_Character_Map[] =
{TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,
+
TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,
+
TimesRoman24_Character_032,TimesRoman24_Character_033,TimesRoman24_Character_034,TimesRoman24_Character_035,TimesRoman24_Character_036,TimesRoman24_Character_037,TimesRoman24_Character_038,TimesRoman24_Character_039,TimesRoman24_Character_040,TimesRoman24_Character_041,TimesRoman24_Character_042,TimesRoman24_Character_043,TimesRoman24_Character_044,TimesRoman24_Character_045,TimesRoman24_Character_046,TimesRoman24_Character_047,
+
TimesRoman24_Character_048,TimesRoman24_Character_049,TimesRoman24_Character_050,TimesRoman24_Character_051,TimesRoman24_Character_052,TimesRoman24_Character_053,TimesRoman24_Character_054,TimesRoman24_Character_055,TimesRoman24_Character_056,TimesRoman24_Character_057,TimesRoman24_Character_058,TimesRoman24_Character_059,TimesRoman24_Character_060,TimesRoman24_Character_061,TimesRoman24_Character_062,TimesRoman24_Character_063,
+
TimesRoman24_Character_064,TimesRoman24_Character_065,TimesRoman24_Character_066,TimesRoman24_Character_067,TimesRoman24_Character_068,TimesRoman24_Character_069,TimesRoman24_Character_070,TimesRoman24_Character_071,TimesRoman24_Character_072,TimesRoman24_Character_073,TimesRoman24_Character_074,TimesRoman24_Character_075,TimesRoman24_Character_076,TimesRoman24_Character_077,TimesRoman24_Character_078,TimesRoman24_Character_079,
+
TimesRoman24_Character_080,TimesRoman24_Character_081,TimesRoman24_Character_082,TimesRoman24_Character_083,TimesRoman24_Character_084,TimesRoman24_Character_085,TimesRoman24_Character_086,TimesRoman24_Character_087,TimesRoman24_Character_088,TimesRoman24_Character_089,TimesRoman24_Character_090,TimesRoman24_Character_091,TimesRoman24_Character_092,TimesRoman24_Character_093,TimesRoman24_Character_094,TimesRoman24_Character_095,
+
TimesRoman24_Character_096,TimesRoman24_Character_097,TimesRoman24_Character_098,TimesRoman24_Character_099,TimesRoman24_Character_100,TimesRoman24_Character_101,TimesRoman24_Character_102,TimesRoman24_Character_103,TimesRoman24_Character_104,TimesRoman24_Character_105,TimesRoman24_Character_106,TimesRoman24_Character_107,TimesRoman24_Character_108,TimesRoman24_Character_109,TimesRoman24_Character_110,TimesRoman24_Character_111,
+
TimesRoman24_Character_112,TimesRoman24_Character_113,TimesRoman24_Character_114,TimesRoman24_Character_115,TimesRoman24_Character_116,TimesRoman24_Character_117,TimesRoman24_Character_118,TimesRoman24_Character_119,TimesRoman24_Character_120,TimesRoman24_Character_121,TimesRoman24_Character_122,TimesRoman24_Character_123,TimesRoman24_Character_124,TimesRoman24_Character_125,TimesRoman24_Character_126,TimesRoman24_Character_032,
+
TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,
+
TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,
+
TimesRoman24_Character_160,TimesRoman24_Character_161,TimesRoman24_Character_162,TimesRoman24_Character_163,TimesRoman24_Character_164,TimesRoman24_Character_165,TimesRoman24_Character_166,TimesRoman24_Character_167,TimesRoman24_Character_168,TimesRoman24_Character_169,TimesRoman24_Character_170,TimesRoman24_Character_171,TimesRoman24_Character_172,TimesRoman24_Character_173,TimesRoman24_Character_174,TimesRoman24_Character_175,
+
TimesRoman24_Character_176,TimesRoman24_Character_177,TimesRoman24_Character_178,TimesRoman24_Character_179,TimesRoman24_Character_180,TimesRoman24_Character_181,TimesRoman24_Character_182,TimesRoman24_Character_183,TimesRoman24_Character_184,TimesRoman24_Character_185,TimesRoman24_Character_186,TimesRoman24_Character_187,TimesRoman24_Character_188,TimesRoman24_Character_189,TimesRoman24_Character_190,TimesRoman24_Character_191,
+
TimesRoman24_Character_192,TimesRoman24_Character_193,TimesRoman24_Character_194,TimesRoman24_Character_195,TimesRoman24_Character_196,TimesRoman24_Character_197,TimesRoman24_Character_198,TimesRoman24_Character_199,TimesRoman24_Character_200,TimesRoman24_Character_201,TimesRoman24_Character_202,TimesRoman24_Character_203,TimesRoman24_Character_204,TimesRoman24_Character_205,TimesRoman24_Character_206,TimesRoman24_Character_207,
+
TimesRoman24_Character_208,TimesRoman24_Character_209,TimesRoman24_Character_210,TimesRoman24_Character_211,TimesRoman24_Character_212,TimesRoman24_Character_213,TimesRoman24_Character_214,TimesRoman24_Character_215,TimesRoman24_Character_216,TimesRoman24_Character_217,TimesRoman24_Character_218,TimesRoman24_Character_219,TimesRoman24_Character_220,TimesRoman24_Character_221,TimesRoman24_Character_222,TimesRoman24_Character_223,
+
TimesRoman24_Character_224,TimesRoman24_Character_225,TimesRoman24_Character_226,TimesRoman24_Character_227,TimesRoman24_Character_228,TimesRoman24_Character_229,TimesRoman24_Character_230,TimesRoman24_Character_231,TimesRoman24_Character_232,TimesRoman24_Character_233,TimesRoman24_Character_234,TimesRoman24_Character_235,TimesRoman24_Character_236,TimesRoman24_Character_237,TimesRoman24_Character_238,TimesRoman24_Character_239,
+
TimesRoman24_Character_240,TimesRoman24_Character_241,TimesRoman24_Character_242,TimesRoman24_Character_243,TimesRoman24_Character_244,TimesRoman24_Character_245,TimesRoman24_Character_246,TimesRoman24_Character_247,TimesRoman24_Character_248,TimesRoman24_Character_249,TimesRoman24_Character_250,TimesRoman24_Character_251,TimesRoman24_Character_252,TimesRoman24_Character_253,TimesRoman24_Character_254,TimesRoman24_Character_255,NULL};
+
+/* The font structure: */
+const SFG_Font fgFontTimesRoman24 = {
"-adobe-times-medium-r-normal--24-240-75-75-p-124-iso8859-1", 256, 29,
TimesRoman24_Character_Map, 0, 7 };
+
Index: external/trimesh/gluit/glui_img_spindown_0.c
--- external/trimesh/gluit/glui_img_spindown_0.c (revision 0)
+++ external/trimesh/gluit/glui_img_spindown_0.c (revision 0)
@@ -0,0 +1,24 @@
+
+
+int glui_img_spindown_0[] = { 12, 8, /* width, height */
+ 255,255,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 255,255,255, 127,127,127, 127,127,127,
+ 127,127,127, 127,127,127, 127,127,127, 127,127,127, 127,127,127,
+ 127,127,127, 127,127,127, 127,127,127, 0, 0, 0, 255,255,255,
+ 191,191,191, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 191,191,191, 127,127,127,
+ 0, 0, 0, 255,255,255, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 0, 0, 0, 127,127,127, 191,191,191, 191,191,191,
+ 191,191,191, 127,127,127, 0, 0, 0, 255,255,255, 191,191,191,
+ 191,191,191, 191,191,191, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 127,127,127, 191,191,191, 191,191,191, 127,127,127, 0, 0, 0,
+ 255,255,255, 191,191,191, 191,191,191, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 127,127,127, 191,191,191,
+ 127,127,127, 0, 0, 0, 255,255,255, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 191,191,191, 191,191,191, 191,191,191,
+ 191,191,191, 191,191,191, 127,127,127, 0, 0, 0, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 0, 0, 0,
+};
Index: external/trimesh/gluit/freeglut_ext.c
--- external/trimesh/gluit/freeglut_ext.c (revision 0)
+++ external/trimesh/gluit/freeglut_ext.c (revision 0)
@@ -0,0 +1,205 @@
+/*
+ * freeglut_ext.c
+ *
+ * Functions related to OpenGL extensions.
+ *
+ * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
+ * Written by Pawel W. Olszta, <olszta(a)sourceforge.net>
+ * Creation date: Thu Dec 9 1999
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define GLX_GLXEXT_PROTOTYPES
+
+#include <GL/freeglut.h>
+#include "freeglut_internal.h"
+
+
+struct name_address_pair
+{
+ const char *name;
+ void *address;
+};
+
+static struct name_address_pair glut_functions[] =
+{
+ { "glutInit", (void *) glutInit },
+ { "glutInitDisplayMode", (void *) glutInitDisplayMode },
+ { "glutInitDisplayString", (void *) glutInitDisplayString },
+ { "glutInitWindowPosition", (void *) glutInitWindowPosition },
+ { "glutInitWindowSize", (void *) glutInitWindowSize },
+ { "glutMainLoop", (void *) glutMainLoop },
+ { "glutCreateWindow", (void *) glutCreateWindow },
+ { "glutCreateSubWindow", (void *) glutCreateSubWindow },
+ { "glutDestroyWindow", (void *) glutDestroyWindow },
+ { "glutPostRedisplay", (void *) glutPostRedisplay },
+ { "glutPostWindowRedisplay", (void *) glutPostWindowRedisplay },
+ { "glutSwapBuffers", (void *) glutSwapBuffers },
+ { "glutGetWindow", (void *) glutGetWindow },
+ { "glutSetWindow", (void *) glutSetWindow },
+ { "glutSetWindowTitle", (void *) glutSetWindowTitle },
+ { "glutSetIconTitle", (void *) glutSetIconTitle },
+ { "glutPositionWindow", (void *) glutPositionWindow },
+ { "glutReshapeWindow", (void *) glutReshapeWindow },
+ { "glutPopWindow", (void *) glutPopWindow },
+ { "glutPushWindow", (void *) glutPushWindow },
+ { "glutIconifyWindow", (void *) glutIconifyWindow },
+ { "glutShowWindow", (void *) glutShowWindow },
+ { "glutHideWindow", (void *) glutHideWindow },
+ { "glutFullScreen", (void *) glutFullScreen },
+ { "glutSetCursor", (void *) glutSetCursor },
+ { "glutWarpPointer", (void *) glutWarpPointer },
+ { "glutEstablishOverlay", (void *) glutEstablishOverlay },
+ { "glutRemoveOverlay", (void *) glutRemoveOverlay },
+ { "glutUseLayer", (void *) glutUseLayer },
+ { "glutPostOverlayRedisplay", (void *) glutPostOverlayRedisplay },
+ { "glutPostWindowOverlayRedisplay", (void *) glutPostWindowOverlayRedisplay
},
+ { "glutShowOverlay", (void *) glutShowOverlay },
+ { "glutHideOverlay", (void *) glutHideOverlay },
+ { "glutCreateMenu", (void *) glutCreateMenu },
+ { "glutDestroyMenu", (void *) glutDestroyMenu },
+ { "glutGetMenu", (void *) glutGetMenu },
+ { "glutSetMenu", (void *) glutSetMenu },
+ { "glutAddMenuEntry", (void *) glutAddMenuEntry },
+ { "glutAddSubMenu", (void *) glutAddSubMenu },
+ { "glutChangeToMenuEntry", (void *) glutChangeToMenuEntry },
+ { "glutChangeToSubMenu", (void *) glutChangeToSubMenu },
+ { "glutRemoveMenuItem", (void *) glutRemoveMenuItem },
+ { "glutAttachMenu", (void *) glutAttachMenu },
+ { "glutDetachMenu", (void *) glutDetachMenu },
+ { "glutDisplayFunc", (void *) glutDisplayFunc },
+ { "glutReshapeFunc", (void *) glutReshapeFunc },
+ { "glutKeyboardFunc", (void *) glutKeyboardFunc },
+ { "glutMouseFunc", (void *) glutMouseFunc },
+ { "glutMotionFunc", (void *) glutMotionFunc },
+ { "glutPassiveMotionFunc", (void *) glutPassiveMotionFunc },
+ { "glutEntryFunc", (void *) glutEntryFunc },
+ { "glutVisibilityFunc", (void *) glutVisibilityFunc },
+ { "glutIdleFunc", (void *) glutIdleFunc },
+ { "glutTimerFunc", (void *) glutTimerFunc },
+ { "glutMenuStateFunc", (void *) glutMenuStateFunc },
+ { "glutSpecialFunc", (void *) glutSpecialFunc },
+ { "glutSpaceballMotionFunc", (void *) glutSpaceballMotionFunc },
+ { "glutSpaceballRotateFunc", (void *) glutSpaceballRotateFunc },
+ { "glutSpaceballButtonFunc", (void *) glutSpaceballButtonFunc },
+ { "glutButtonBoxFunc", (void *) glutButtonBoxFunc },
+ { "glutDialsFunc", (void *) glutDialsFunc },
+ { "glutTabletMotionFunc", (void *) glutTabletMotionFunc },
+ { "glutTabletButtonFunc", (void *) glutTabletButtonFunc },
+ { "glutMenuStatusFunc", (void *) glutMenuStatusFunc },
+ { "glutOverlayDisplayFunc", (void *) glutOverlayDisplayFunc },
+ { "glutWindowStatusFunc", (void *) glutWindowStatusFunc },
+ { "glutKeyboardUpFunc", (void *) glutKeyboardUpFunc },
+ { "glutSpecialUpFunc", (void *) glutSpecialUpFunc },
+#if !TARGET_HOST_WINCE
+ { "glutJoystickFunc", (void *) glutJoystickFunc },
+#endif /* !TARGET_HOST_WINCE */
+ { "glutSetColor", (void *) glutSetColor },
+ { "glutGetColor", (void *) glutGetColor },
+ { "glutCopyColormap", (void *) glutCopyColormap },
+ { "glutGet", (void *) glutGet },
+ { "glutDeviceGet", (void *) glutDeviceGet },
+ { "glutExtensionSupported", (void *) glutExtensionSupported },
+ { "glutGetModifiers", (void *) glutGetModifiers },
+ { "glutLayerGet", (void *) glutLayerGet },
+ { "glutBitmapCharacter", (void *) glutBitmapCharacter },
+ { "glutBitmapWidth", (void *) glutBitmapWidth },
+ { "glutStrokeCharacter", (void *) glutStrokeCharacter },
+ { "glutStrokeWidth", (void *) glutStrokeWidth },
+ { "glutBitmapLength", (void *) glutBitmapLength },
+ { "glutStrokeLength", (void *) glutStrokeLength },
+ { "glutWireSphere", (void *) glutWireSphere },
+ { "glutSolidSphere", (void *) glutSolidSphere },
+ { "glutWireCone", (void *) glutWireCone },
+ { "glutSolidCone", (void *) glutSolidCone },
+ { "glutWireCube", (void *) glutWireCube },
+ { "glutSolidCube", (void *) glutSolidCube },
+ { "glutWireTorus", (void *) glutWireTorus },
+ { "glutSolidTorus", (void *) glutSolidTorus },
+ { "glutWireDodecahedron", (void *) glutWireDodecahedron },
+ { "glutSolidDodecahedron", (void *) glutSolidDodecahedron },
+ { "glutWireTeapot", (void *) glutWireTeapot },
+ { "glutSolidTeapot", (void *) glutSolidTeapot },
+ { "glutWireOctahedron", (void *) glutWireOctahedron },
+ { "glutSolidOctahedron", (void *) glutSolidOctahedron },
+ { "glutWireTetrahedron", (void *) glutWireTetrahedron },
+ { "glutSolidTetrahedron", (void *) glutSolidTetrahedron },
+ { "glutWireIcosahedron", (void *) glutWireIcosahedron },
+ { "glutSolidIcosahedron", (void *) glutSolidIcosahedron },
+ { "glutVideoResizeGet", (void *) glutVideoResizeGet },
+ { "glutSetupVideoResizing", (void *) glutSetupVideoResizing },
+ { "glutStopVideoResizing", (void *) glutStopVideoResizing },
+ { "glutVideoResize", (void *) glutVideoResize },
+ { "glutVideoPan", (void *) glutVideoPan },
+ { "glutReportErrors", (void *) glutReportErrors },
+ { "glutIgnoreKeyRepeat", (void *) glutIgnoreKeyRepeat },
+ { "glutSetKeyRepeat", (void *) glutSetKeyRepeat },
+#if !TARGET_HOST_WINCE
+ { "glutForceJoystickFunc", (void *) glutForceJoystickFunc },
+ { "glutGameModeString", (void *) glutGameModeString },
+ { "glutEnterGameMode", (void *) glutEnterGameMode },
+ { "glutLeaveGameMode", (void *) glutLeaveGameMode },
+ { "glutGameModeGet", (void *) glutGameModeGet },
+#endif /* !TARGET_HOST_WINCE */
+ /* freeglut extensions */
+ { "glutMainLoopEvent", (void *) glutMainLoopEvent },
+ { "glutLeaveMainLoop", (void *) glutLeaveMainLoop },
+ { "glutCloseFunc", (void *) glutCloseFunc },
+ { "glutWMCloseFunc", (void *) glutWMCloseFunc },
+ { "glutMenuDestroyFunc", (void *) glutMenuDestroyFunc },
+ { "glutSetOption", (void *) glutSetOption },
+ { "glutSetWindowData", (void *) glutSetWindowData },
+ { "glutGetWindowData", (void *) glutGetWindowData },
+ { "glutSetMenuData", (void *) glutSetMenuData },
+ { "glutGetMenuData", (void *) glutGetMenuData },
+ { "glutBitmapHeight", (void *) glutBitmapHeight },
+ { "glutStrokeHeight", (void *) glutStrokeHeight },
+ { "glutBitmapString", (void *) glutBitmapString },
+ { "glutStrokeString", (void *) glutStrokeString },
+ { "glutWireRhombicDodecahedron", (void *) glutWireRhombicDodecahedron },
+ { "glutSolidRhombicDodecahedron", (void *) glutSolidRhombicDodecahedron },
+ { "glutWireSierpinskiSponge ", (void *) glutWireSierpinskiSponge },
+ { "glutSolidSierpinskiSponge ", (void *) glutSolidSierpinskiSponge },
+ { "glutGetProcAddress", (void *) glutGetProcAddress },
+ { "glutMouseWheelFunc", (void *) glutMouseWheelFunc },
+ { NULL, NULL }
+};
+
+
+void *FGAPIENTRY glutGetProcAddress( const char *procName )
+{
+ /* Try GLUT functions first */
+ int i;
+ for( i = 0; glut_functions[ i ].name; i++ )
+ if( strcmp( glut_functions[ i ].name, procName ) == 0)
+ return glut_functions[ i ].address;
+
+ /* Try core GL functions */
+#if TARGET_HOST_WIN32 || TARGET_HOST_WINCE
+ return( void * )wglGetProcAddress( ( LPCSTR )procName );
+#elif TARGET_HOST_UNIX_X11 && defined( GLX_ARB_get_proc_address )
+ return(void * )glXGetProcAddressARB( ( const GLubyte * )procName );
+#else
+ return NULL;
+#endif
+}
Index: external/trimesh/gluit/freeglut_init.c
--- external/trimesh/gluit/freeglut_init.c (revision 0)
+++ external/trimesh/gluit/freeglut_init.c (revision 0)
@@ -0,0 +1,899 @@
+/*
+ * freeglut_init.c
+ *
+ * Various freeglut initialization functions.
+ *
+ * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
+ * Written by Pawel W. Olszta, <olszta(a)sourceforge.net>
+ * Creation date: Thu Dec 2 1999
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <GL/freeglut.h>
+#include "freeglut_internal.h"
+
+/*
+ * TODO BEFORE THE STABLE RELEASE:
+ *
+ * fgDeinitialize() -- Win32's OK, X11 needs the OS-specific
+ * deinitialization done
+ * glutInitDisplayString() -- display mode string parsing
+ *
+ * Wouldn't it be cool to use gettext() for error messages? I just love
+ * bash saying "nie znaleziono pliku" instead of "file not found"
:)
+ * Is gettext easily portable?
+ */
+
+/* -- GLOBAL VARIABLES ----------------------------------------------------- */
+
+/*
+ * A structure pointed by g_pDisplay holds all information
+ * regarding the display, screen, root window etc.
+ */
+SFG_Display fgDisplay;
+
+/*
+ * The settings for the current freeglut session
+ */
+SFG_State fgState = { { -1, -1, GL_FALSE }, /* Position */
+ { 300, 300, GL_TRUE }, /* Size */
+ GLUT_RGBA | GLUT_SINGLE | GLUT_DEPTH, /* DisplayMode */
+ GL_FALSE, /* Initialised */
+ GLUT_TRY_DIRECT_CONTEXT, /* DirectContext */
+ GL_FALSE, /* ForceIconic */
+ GL_FALSE, /* UseCurrentContext */
+ GL_FALSE, /* GLDebugSwitch */
+ GL_FALSE, /* XSyncSwitch */
+ GL_TRUE, /* KeyRepeat */
+ 0xffffffff, /* Modifiers */
+ 0, /* FPSInterval */
+ 0, /* SwapCount */
+ 0, /* SwapTime */
+#if TARGET_HOST_WIN32 || TARGET_HOST_WINCE
+ { 0, GL_FALSE }, /* Time */
+#else
+ { { 0, 0 }, GL_FALSE },
+#endif
+ { NULL, NULL }, /* Timers */
+ { NULL, NULL }, /* FreeTimers */
+ NULL, /* IdleCallback */
+ 0, /* ActiveMenus */
+ NULL, /* MenuStateCallback */
+ NULL, /* MenuStatusCallback */
+ { 640, 480, GL_TRUE }, /* GameModeSize */
+ 16, /* GameModeDepth */
+ 72, /* GameModeRefresh */
+ GLUT_ACTION_EXIT, /* ActionOnWindowClose */
+ GLUT_EXEC_STATE_INIT, /* ExecState */
+ NULL /* ProgramName */
+};
+
+
+/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
+
+/*
+ * A call to this function should initialize all the display stuff...
+ */
+void fgInitialize( const char* displayName )
+{
+#if TARGET_HOST_UNIX_X11
+ fgDisplay.Display = XOpenDisplay( displayName );
+
+ if( fgDisplay.Display == NULL )
+ fgError( "failed to open display '%s'", XDisplayName(
displayName ) );
+
+ if( !glXQueryExtension( fgDisplay.Display, NULL, NULL ) )
+ fgError( "OpenGL GLX extension not supported by display '%s'",
+ XDisplayName( displayName ) );
+
+ fgDisplay.Screen = DefaultScreen( fgDisplay.Display );
+ fgDisplay.RootWindow = RootWindow(
+ fgDisplay.Display,
+ fgDisplay.Screen
+ );
+
+ fgDisplay.ScreenWidth = DisplayWidth(
+ fgDisplay.Display,
+ fgDisplay.Screen
+ );
+ fgDisplay.ScreenHeight = DisplayHeight(
+ fgDisplay.Display,
+ fgDisplay.Screen
+ );
+
+ fgDisplay.ScreenWidthMM = DisplayWidthMM(
+ fgDisplay.Display,
+ fgDisplay.Screen
+ );
+ fgDisplay.ScreenHeightMM = DisplayHeightMM(
+ fgDisplay.Display,
+ fgDisplay.Screen
+ );
+
+ fgDisplay.Connection = ConnectionNumber( fgDisplay.Display );
+
+ /*
+ * Create the window deletion atom
+ */
+ fgDisplay.DeleteWindow = XInternAtom(
+ fgDisplay.Display,
+ "WM_DELETE_WINDOW",
+ FALSE
+ );
+
+#elif TARGET_HOST_WIN32 || TARGET_HOST_WINCE
+
+ WNDCLASS wc;
+ ATOM atom;
+
+ /*
+ * What we need to do is to initialize the fgDisplay global structure here.
+ */
+ fgDisplay.Instance = GetModuleHandle( NULL );
+
+ atom = GetClassInfo( fgDisplay.Instance, _T("FREEGLUT"), &wc );
+
+ if( atom == 0 )
+ {
+ ZeroMemory( &wc, sizeof(WNDCLASS) );
+
+ /*
+ * Each of the windows should have its own device context, and we
+ * want redraw events during Vertical and Horizontal Resizes by
+ * the user.
+ *
+ * XXX Old code had "| CS_DBCLCKS" commented out. Plans for the
+ * XXX future? Dead-end idea?
+ */
+ wc.lpfnWndProc = fgWindowProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = fgDisplay.Instance;
+ wc.hIcon = LoadIcon( fgDisplay.Instance, _T("GLUT_ICON") );
+
+#if TARGET_HOST_WIN32
+ wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
+ if (!wc.hIcon)
+ wc.hIcon = LoadIcon( NULL, IDI_WINLOGO );
+#else /* TARGET_HOST_WINCE */
+ wc.style = CS_HREDRAW | CS_VREDRAW;
+#endif
+
+ wc.hCursor = LoadCursor( NULL, IDC_ARROW );
+ wc.hbrBackground = NULL;
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = _T("FREEGLUT");
+
+ /*
+ * Register the window class
+ */
+ atom = RegisterClass( &wc );
+ assert( atom );
+ }
+
+ /*
+ * The screen dimensions can be obtained via GetSystemMetrics() calls
+ */
+ fgDisplay.ScreenWidth = GetSystemMetrics( SM_CXSCREEN );
+ fgDisplay.ScreenHeight = GetSystemMetrics( SM_CYSCREEN );
+
+ {
+ HWND desktop = GetDesktopWindow( );
+ HDC context = GetDC( desktop );
+
+ fgDisplay.ScreenWidthMM = GetDeviceCaps( context, HORZSIZE );
+ fgDisplay.ScreenHeightMM = GetDeviceCaps( context, VERTSIZE );
+
+ ReleaseDC( desktop, context );
+ }
+
+#endif
+
+#if !TARGET_HOST_WINCE
+ fgJoystickInit( 0 );
+ fgJoystickInit( 1 );
+#endif /* !TARGET_HOST_WINCE */
+
+ fgState.Initialised = GL_TRUE;
+}
+
+/*
+ * Perform the freeglut deinitialization...
+ */
+void fgDeinitialize( void )
+{
+ SFG_Timer *timer;
+
+ if( !fgState.Initialised )
+ {
+ fgWarning( "fgDeinitialize(): "
+ "no valid initialization has been performed" );
+ return;
+ }
+
+ /* fgState.Initialised = GL_FALSE; */
+
+ /*
+ * If there was a menu created, destroy the rendering context
+ */
+ if( fgStructure.MenuContext )
+ {
+ free( fgStructure.MenuContext );
+ fgStructure.MenuContext = NULL;
+ }
+
+ fgDestroyStructure( );
+
+ while( (timer = fgState.Timers.First) )
+ {
+ fgListRemove( &fgState.Timers, &timer->Node );
+ free( timer );
+ }
+
+ while( (timer = fgState.FreeTimers.First) )
+ {
+ fgListRemove( &fgState.FreeTimers, &timer->Node );
+ free( timer );
+ }
+
+#if !TARGET_HOST_WINCE
+ fgJoystickClose( );
+#endif /* !TARGET_HOST_WINCE */
+
+ fgState.Initialised = GL_FALSE;
+
+ fgState.Position.X = -1;
+ fgState.Position.Y = -1;
+ fgState.Position.Use = GL_FALSE;
+
+ fgState.Size.X = 300;
+ fgState.Size.Y = 300;
+ fgState.Size.Use = GL_TRUE;
+
+ fgState.DisplayMode = GLUT_RGBA | GLUT_SINGLE | GLUT_DEPTH;
+
+ fgState.DirectContext = GLUT_TRY_DIRECT_CONTEXT;
+ fgState.ForceIconic = GL_FALSE;
+ fgState.UseCurrentContext = GL_FALSE;
+ fgState.GLDebugSwitch = GL_FALSE;
+ fgState.XSyncSwitch = GL_FALSE;
+ fgState.ActionOnWindowClose = GLUT_ACTION_EXIT;
+ fgState.ExecState = GLUT_EXEC_STATE_INIT;
+
+ fgState.KeyRepeat = GL_FALSE;
+ fgState.Modifiers = 0xffffffff;
+
+ fgState.GameModeSize.X = 640;
+ fgState.GameModeSize.Y = 480;
+ fgState.GameModeDepth = 16;
+ fgState.GameModeRefresh = 72;
+
+ fgState.Time.Set = GL_FALSE;
+
+ fgListInit( &fgState.Timers );
+ fgListInit( &fgState.FreeTimers );
+
+ fgState.IdleCallback = NULL;
+ fgState.MenuStateCallback = ( FGCBMenuState )NULL;
+ fgState.MenuStatusCallback = ( FGCBMenuStatus )NULL;
+
+ fgState.SwapCount = 0;
+ fgState.SwapTime = 0;
+ fgState.FPSInterval = 0;
+
+ if( fgState.ProgramName )
+ {
+ free( fgState.ProgramName );
+ fgState.ProgramName = NULL;
+ }
+
+
+#if TARGET_HOST_UNIX_X11
+
+ /*
+ * Make sure all X-client data we have created will be destroyed on
+ * display closing
+ */
+ XSetCloseDownMode( fgDisplay.Display, DestroyAll );
+
+ /*
+ * Close the display connection, destroying all windows we have
+ * created so far
+ */
+ XCloseDisplay( fgDisplay.Display );
+
+#endif
+}
+
+/*
+ * Everything inside the following #ifndef is copied from the X sources.
+ */
+
+#if TARGET_HOST_WIN32 || TARGET_HOST_WINCE
+
+/*
+
+Copyright 1985, 1986, 1987,1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+*/
+
+#define NoValue 0x0000
+#define XValue 0x0001
+#define YValue 0x0002
+#define WidthValue 0x0004
+#define HeightValue 0x0008
+#define AllValues 0x000F
+#define XNegative 0x0010
+#define YNegative 0x0020
+
+/*
+ * XParseGeometry parses strings of the form
+ * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>",
where
+ * width, height, xoffset, and yoffset are unsigned integers.
+ * Example: "=80x24+300-49"
+ * The equal sign is optional.
+ * It returns a bitmask that indicates which of the four values
+ * were actually found in the string. For each value found,
+ * the corresponding argument is updated; for each value
+ * not found, the corresponding argument is left unchanged.
+ */
+
+static int
+ReadInteger(char *string, char **NextString)
+{
+ register int Result = 0;
+ int Sign = 1;
+
+ if (*string == '+')
+ string++;
+ else if (*string == '-')
+ {
+ string++;
+ Sign = -1;
+ }
+ for (; (*string >= '0') && (*string <= '9'); string++)
+ {
+ Result = (Result * 10) + (*string - '0');
+ }
+ *NextString = string;
+ if (Sign >= 0)
+ return Result;
+ else
+ return -Result;
+}
+
+static int XParseGeometry (
+ const char *string,
+ int *x,
+ int *y,
+ unsigned int *width, /* RETURN */
+ unsigned int *height) /* RETURN */
+{
+ int mask = NoValue;
+ register char *strind;
+ unsigned int tempWidth = 0, tempHeight = 0;
+ int tempX = 0, tempY = 0;
+ char *nextCharacter;
+
+ if ( (string == NULL) || (*string == '\0'))
+ return mask;
+ if (*string == '=')
+ string++; /* ignore possible '=' at beg of geometry spec */
+
+ strind = (char *)string;
+ if (*strind != '+' && *strind != '-' && *strind !=
'x') {
+ tempWidth = ReadInteger(strind, &nextCharacter);
+ if (strind == nextCharacter)
+ return 0;
+ strind = nextCharacter;
+ mask |= WidthValue;
+ }
+
+ if (*strind == 'x' || *strind == 'X') {
+ strind++;
+ tempHeight = ReadInteger(strind, &nextCharacter);
+ if (strind == nextCharacter)
+ return 0;
+ strind = nextCharacter;
+ mask |= HeightValue;
+ }
+
+ if ((*strind == '+') || (*strind == '-')) {
+ if (*strind == '-') {
+ strind++;
+ tempX = -ReadInteger(strind, &nextCharacter);
+ if (strind == nextCharacter)
+ return 0;
+ strind = nextCharacter;
+ mask |= XNegative;
+ }
+ else
+ {
+ strind++;
+ tempX = ReadInteger(strind, &nextCharacter);
+ if (strind == nextCharacter)
+ return 0;
+ strind = nextCharacter;
+ }
+ mask |= XValue;
+ if ((*strind == '+') || (*strind == '-')) {
+ if (*strind == '-') {
+ strind++;
+ tempY = -ReadInteger(strind, &nextCharacter);
+ if (strind == nextCharacter)
+ return 0;
+ strind = nextCharacter;
+ mask |= YNegative;
+ }
+ else
+ {
+ strind++;
+ tempY = ReadInteger(strind, &nextCharacter);
+ if (strind == nextCharacter)
+ return 0;
+ strind = nextCharacter;
+ }
+ mask |= YValue;
+ }
+ }
+
+ /* If strind isn't at the end of the string the it's an invalid
+ geometry specification. */
+
+ if (*strind != '\0') return 0;
+
+ if (mask & XValue)
+ *x = tempX;
+ if (mask & YValue)
+ *y = tempY;
+ if (mask & WidthValue)
+ *width = tempWidth;
+ if (mask & HeightValue)
+ *height = tempHeight;
+ return mask;
+}
+#endif
+
+/* -- INTERFACE FUNCTIONS -------------------------------------------------- */
+
+/*
+ * Perform initialization. This usually happens on the program startup
+ * and restarting after glutMainLoop termination...
+ */
+void FGAPIENTRY glutInit( int* pargc, char** argv )
+{
+ char* displayName = NULL;
+ char* geometry = NULL;
+ int i, j, argc = *pargc;
+
+ if( fgState.Initialised )
+ fgError( "illegal glutInit() reinitialization attempt" );
+
+ if (pargc && *pargc && argv && *argv && **argv)
+ {
+ fgState.ProgramName = strdup (*argv);
+
+ if( !fgState.ProgramName )
+ fgError ("Could not allocate space for the program's name.");
+ }
+
+ fgCreateStructure( );
+
+ fgElapsedTime( );
+
+ /* check if GLUT_FPS env var is set */
+#if !TARGET_HOST_WINCE
+ {
+ const char *fps = getenv( "GLUT_FPS" );
+ if( fps )
+ {
+ int interval;
+ sscanf( fps, "%d", &interval );
+
+ if( interval <= 0 )
+ fgState.FPSInterval = 5000; /* 5000 millisecond default */
+ else
+ fgState.FPSInterval = interval;
+ }
+ }
+
+ displayName = getenv( "DISPLAY");
+
+ for( i = 1; i < argc; i++ )
+ {
+ if( strcmp( argv[ i ], "-display" ) == 0 )
+ {
+ if( ++i >= argc )
+ fgError( "-display parameter must be followed by display name"
);
+
+ displayName = argv[ i ];
+
+ argv[ i - 1 ] = NULL;
+ argv[ i ] = NULL;
+ ( *pargc ) -= 2;
+ }
+ else if( strcmp( argv[ i ], "-geometry" ) == 0 )
+ {
+ if( ++i >= argc )
+ fgError( "-geometry parameter must be followed by window "
+ "geometry settings" );
+
+ geometry = argv[ i ];
+
+ argv[ i - 1 ] = NULL;
+ argv[ i ] = NULL;
+ ( *pargc ) -= 2;
+ }
+ else if( strcmp( argv[ i ], "-direct" ) == 0)
+ {
+ if( fgState.DirectContext == GLUT_FORCE_INDIRECT_CONTEXT )
+ fgError( "parameters ambiguity, -direct and -indirect "
+ "cannot be both specified" );
+
+ fgState.DirectContext = GLUT_FORCE_DIRECT_CONTEXT;
+ argv[ i ] = NULL;
+ ( *pargc )--;
+ }
+ else if( strcmp( argv[ i ], "-indirect" ) == 0 )
+ {
+ if( fgState.DirectContext == GLUT_FORCE_DIRECT_CONTEXT )
+ fgError( "parameters ambiguity, -direct and -indirect "
+ "cannot be both specified" );
+
+ fgState.DirectContext = GLUT_FORCE_INDIRECT_CONTEXT;
+ argv[ i ] = NULL;
+ (*pargc)--;
+ }
+ else if( strcmp( argv[ i ], "-iconic" ) == 0 )
+ {
+ fgState.ForceIconic = GL_TRUE;
+ argv[ i ] = NULL;
+ ( *pargc )--;
+ }
+ else if( strcmp( argv[ i ], "-gldebug" ) == 0 )
+ {
+ fgState.GLDebugSwitch = GL_TRUE;
+ argv[ i ] = NULL;
+ ( *pargc )--;
+ }
+ else if( strcmp( argv[ i ], "-sync" ) == 0 )
+ {
+ fgState.XSyncSwitch = GL_TRUE;
+ argv[ i ] = NULL;
+ ( *pargc )--;
+ }
+ }
+
+ /*
+ * Compact {argv}.
+ */
+ j = 2;
+ for( i = 1; i < *pargc; i++, j++ )
+ {
+ if( argv[ i ] == NULL )
+ {
+ /* Guaranteed to end because there are "*pargc" arguments left */
+ while ( argv[ j ] == NULL )
+ j++;
+ argv[ i ] = argv[ j ];
+ }
+ }
+
+#endif /* TARGET_HOST_WINCE */
+
+ /*
+ * Have the display created now. If there wasn't a "-display"
+ * in the program arguments, we will use the DISPLAY environment
+ * variable for opening the X display (see code above):
+ */
+ fgInitialize( displayName );
+
+ /*
+ * Geometry parsing deffered until here because we may need the screen
+ * size.
+ */
+
+ if (geometry )
+ {
+ int mask = XParseGeometry( geometry,
+ &fgState.Position.X, &fgState.Position.Y,
+ &fgState.Size.X, &fgState.Size.Y );
+
+ if( (mask & (WidthValue|HeightValue)) == (WidthValue|HeightValue) )
+ fgState.Size.Use = GL_TRUE;
+
+ if( mask & XNegative )
+ fgState.Position.X += fgDisplay.ScreenWidth - fgState.Size.X;
+
+ if( mask & YNegative )
+ fgState.Position.Y += fgDisplay.ScreenHeight - fgState.Size.Y;
+
+ if( (mask & (XValue|YValue)) == (XValue|YValue) )
+ fgState.Position.Use = GL_TRUE;
+ }
+}
+
+/*
+ * Sets the default initial window position for new windows
+ */
+void FGAPIENTRY glutInitWindowPosition( int x, int y )
+{
+ fgState.Position.X = x;
+ fgState.Position.Y = y;
+
+ if( ( x >= 0 ) && ( y >= 0 ) )
+ fgState.Position.Use = GL_TRUE;
+ else
+ fgState.Position.Use = GL_FALSE;
+}
+
+/*
+ * Sets the default initial window size for new windows
+ */
+void FGAPIENTRY glutInitWindowSize( int width, int height )
+{
+ fgState.Size.X = width;
+ fgState.Size.Y = height;
+
+ if( ( width > 0 ) && ( height > 0 ) )
+ fgState.Size.Use = GL_TRUE;
+ else
+ fgState.Size.Use = GL_FALSE;
+}
+
+/*
+ * Sets the default display mode for all new windows
+ */
+void FGAPIENTRY glutInitDisplayMode( unsigned int displayMode )
+{
+ /*
+ * We will make use of this value when creating a new OpenGL context...
+ */
+ fgState.DisplayMode = displayMode;
+}
+
+
+/* -- INIT DISPLAY STRING PARSING ------------------------------------------ */
+
+#define NUM_TOKENS 28
+static char* Tokens[] =
+{
+ "alpha", "acca", "acc", "blue",
"buffer", "conformant", "depth", "double",
+ "green", "index", "num", "red",
"rgba", "rgb", "luminance", "stencil",
+ "single", "stereo", "samples", "slow",
"win32pdf", "xvisual",
+ "xstaticgray", "xgrayscale", "xstaticcolor",
"xpseudocolor",
+ "xtruecolor", "xdirectcolor"
+};
+
+static int TokenLengths[] =
+{
+ 5, 4, 3, 4, 6, 10, 5, 6,
+ 5, 5, 3, 3, 4, 3, 9, 7,
+ 6, 6, 7, 4, 8, 7,
+ 11, 10, 12, 12,
+ 10, 12
+};
+
+void FGAPIENTRY glutInitDisplayString( const char* displayMode )
+{
+ int glut_state_flag = 0 ;
+ /*
+ * Unpack a lot of options from a character string. The options are
+ * delimited by blanks or tabs.
+ */
+ char *token ;
+ int len = strlen ( displayMode );
+ char *buffer = (char *)malloc ( (len+1) * sizeof(char) );
+ memcpy ( buffer, displayMode, len );
+ buffer[len] = '\0';
+
+ token = strtok ( buffer, " \t" );
+ while ( token )
+ {
+ /*
+ * Process this token
+ */
+ int i ;
+ for ( i = 0; i < NUM_TOKENS; i++ )
+ {
+ if ( strncmp ( token, Tokens[i], TokenLengths[i] ) == 0 ) break ;
+ }
+
+ switch ( i )
+ {
+ case 0 : /* "alpha": Alpha color buffer precision in bits */
+ glut_state_flag |= GLUT_ALPHA ; /* Somebody fix this for me! */
+ break ;
+
+ case 1 : /* "acca": Red, green, blue, and alpha accumulation buffer
+ precision in bits */
+ break ;
+
+ case 2 : /* "acc": Red, green, and blue accumulation buffer
precision
+ in bits with zero bits alpha */
+ glut_state_flag |= GLUT_ACCUM ; /* Somebody fix this for me! */
+ break ;
+
+ case 3 : /* "blue": Blue color buffer precision in bits */
+ break ;
+
+ case 4 : /* "buffer": Number of bits in the color index color buffer
+ */
+ break ;
+
+ case 5 : /* "conformant": Boolean indicating if the frame buffer
+ configuration is conformant or not */
+ break ;
+
+ case 6 : /* "depth": Number of bits of precsion in the depth buffer
*/
+ glut_state_flag |= GLUT_DEPTH ; /* Somebody fix this for me! */
+ break ;
+
+ case 7 : /* "double": Boolean indicating if the color buffer is
+ double buffered */
+ glut_state_flag |= GLUT_DOUBLE ;
+ break ;
+
+ case 8 : /* "green": Green color buffer precision in bits */
+ break ;
+
+ case 9 : /* "index": Boolean if the color model is color index or
not
+ */
+ glut_state_flag |= GLUT_INDEX ;
+ break ;
+
+ case 10 : /* "num": A special capability name indicating where the
+ value represents the Nth frame buffer configuration
+ matching the description string */
+ break ;
+
+ case 11 : /* "red": Red color buffer precision in bits */
+ break ;
+
+ case 12 : /* "rgba": Number of bits of red, green, blue, and alpha
in
+ the RGBA color buffer */
+ glut_state_flag |= GLUT_RGBA ; /* Somebody fix this for me! */
+ break ;
+
+ case 13 : /* "rgb": Number of bits of red, green, and blue in the
+ RGBA color buffer with zero bits alpha */
+ glut_state_flag |= GLUT_RGB ; /* Somebody fix this for me! */
+ break ;
+
+ case 14 : /* "luminance": Number of bits of red in the RGBA and zero
+ bits of green, blue (alpha not specified) of color buffer
+ precision */
+ glut_state_flag |= GLUT_LUMINANCE ; /* Somebody fix this for me! */
+ break ;
+
+ case 15 : /* "stencil": Number of bits in the stencil buffer */
+ glut_state_flag |= GLUT_STENCIL; /* Somebody fix this for me! */
+ break ;
+
+ case 16 : /* "single": Boolean indicate the color buffer is single
+ buffered */
+ glut_state_flag |= GLUT_SINGLE ;
+ break ;
+
+ case 17 : /* "stereo": Boolean indicating the color buffer supports
+ OpenGL-style stereo */
+ glut_state_flag |= GLUT_STEREO ;
+ break ;
+
+ case 18 : /* "samples": Indicates the number of multisamples to use
+ based on GLX's SGIS_multisample extension (for
+ antialiasing) */
+ glut_state_flag |= GLUT_MULTISAMPLE ; /*Somebody fix this for me!*/
+ break ;
+
+ case 19 : /* "slow": Boolean indicating if the frame buffer
+ configuration is slow or not */
+ break ;
+
+ case 20 : /* "win32pdf": matches the Win32 Pixel Format Descriptor
by
+ number */
+#if TARGET_HOST_WIN32
+#endif
+ break ;
+
+ case 21 : /* "xvisual": matches the X visual ID by number */
+#if TARGET_HOST_UNIX_X11
+#endif
+ break ;
+
+ case 22 : /* "xstaticgray": boolean indicating if the frame buffer
+ configuration's X visual is of type StaticGray */
+#if TARGET_HOST_UNIX_X11
+#endif
+ break ;
+
+ case 23 : /* "xgrayscale": boolean indicating if the frame buffer
+ configuration's X visual is of type GrayScale */
+#if TARGET_HOST_UNIX_X11
+#endif
+ break ;
+
+ case 24 : /* "xstaticcolor": boolean indicating if the frame buffer
+ configuration's X visual is of type StaticColor */
+#if TARGET_HOST_UNIX_X11
+#endif
+ break ;
+
+ case 25 : /* "xpseudocolor": boolean indicating if the frame buffer
+ configuration's X visual is of type PseudoColor */
+#if TARGET_HOST_UNIX_X11
+#endif
+ break ;
+
+ case 26 : /* "xtruecolor": boolean indicating if the frame buffer
+ configuration's X visual is of type TrueColor */
+#if TARGET_HOST_UNIX_X11
+#endif
+ break ;
+
+ case 27 : /* "xdirectcolor": boolean indicating if the frame buffer
+ configuration's X visual is of type DirectColor */
+#if TARGET_HOST_UNIX_X11
+#endif
+ break ;
+
+ case 28 : /* Unrecognized */
+ printf ( "WARNING - Display string token not recognized: %s\n",
+ token );
+ break ;
+ }
+
+ token = strtok ( NULL, " \t" );
+ }
+
+ free ( buffer );
+
+ /*
+ * We will make use of this value when creating a new OpenGL context...
+ */
+ fgState.DisplayMode = glut_state_flag;
+}
+
+/*** END OF FILE ***/
Index: external/trimesh/gluit/freeglut_stroke_roman.c
--- external/trimesh/gluit/freeglut_stroke_roman.c (revision 0)
+++ external/trimesh/gluit/freeglut_stroke_roman.c (revision 0)
@@ -0,0 +1,2821 @@
+
+/* This file has been automatically generated by the genstroke utility. */
+
+#include "freeglut_internal.h"
+
+/* char: 0x20 */
+
+static const SFG_StrokeStrip ch32st[] =
+{
+ { 0, NULL }
+};
+
+static const SFG_StrokeChar ch32 = {104.762f,0,ch32st};
+
+/* char: 0x21 */
+
+static const SFG_StrokeVertex ch33st0[] =
+{
+ {13.3819f,100.0f},
+ {13.3819f,33.3333f}
+};
+
+static const SFG_StrokeVertex ch33st1[] =
+{
+ {13.3819f,9.5238f},
+ {8.62f,4.7619f},
+ {13.3819f,0.0f},
+ {18.1438f,4.7619f},
+ {13.3819f,9.5238f}
+};
+
+static const SFG_StrokeStrip ch33st[] =
+{
+ {2,ch33st0},
+ {5,ch33st1}
+};
+
+static const SFG_StrokeChar ch33 = {26.6238f,2,ch33st};
+
+/* char: 0x22 */
+
+static const SFG_StrokeVertex ch34st0[] =
+{
+ {4.02f,100.0f},
+ {4.02f,66.6667f}
+};
+
+static const SFG_StrokeVertex ch34st1[] =
+{
+ {42.1152f,100.0f},
+ {42.1152f,66.6667f}
+};
+
+static const SFG_StrokeStrip ch34st[] =
+{
+ {2,ch34st0},
+ {2,ch34st1}
+};
+
+static const SFG_StrokeChar ch34 = {51.4352f,2,ch34st};
+
+/* char: 0x23 */
+
+static const SFG_StrokeVertex ch35st0[] =
+{
+ {41.2952f,119.048f},
+ {7.9619f,-33.3333f}
+};
+
+static const SFG_StrokeVertex ch35st1[] =
+{
+ {69.8667f,119.048f},
+ {36.5333f,-33.3333f}
+};
+
+static const SFG_StrokeVertex ch35st2[] =
+{
+ {7.9619f,57.1429f},
+ {74.6286f,57.1429f}
+};
+
+static const SFG_StrokeVertex ch35st3[] =
+{
+ {3.2f,28.5714f},
+ {69.8667f,28.5714f}
+};
+
+static const SFG_StrokeStrip ch35st[] =
+{
+ {2,ch35st0},
+ {2,ch35st1},
+ {2,ch35st2},
+ {2,ch35st3}
+};
+
+static const SFG_StrokeChar ch35 = {79.4886f,4,ch35st};
+
+/* char: 0x24 */
+
+static const SFG_StrokeVertex ch36st0[] =
+{
+ {28.6295f,119.048f},
+ {28.6295f,-19.0476f}
+};
+
+static const SFG_StrokeVertex ch36st1[] =
+{
+ {47.6771f,119.048f},
+ {47.6771f,-19.0476f}
+};
+
+static const SFG_StrokeVertex ch36st2[] =
+{
+ {71.4867f,85.7143f},
+ {61.9629f,95.2381f},
+ {47.6771f,100.0f},
+ {28.6295f,100.0f},
+ {14.3438f,95.2381f},
+ {4.82f,85.7143f},
+ {4.82f,76.1905f},
+ {9.5819f,66.6667f},
+ {14.3438f,61.9048f},
+ {23.8676f,57.1429f},
+ {52.439f,47.619f},
+ {61.9629f,42.8571f},
+ {66.7248f,38.0952f},
+ {71.4867f,28.5714f},
+ {71.4867f,14.2857f},
+ {61.9629f,4.7619f},
+ {47.6771f,0.0f},
+ {28.6295f,0.0f},
+ {14.3438f,4.7619f},
+ {4.82f,14.2857f}
+};
+
+static const SFG_StrokeStrip ch36st[] =
+{
+ {2,ch36st0},
+ {2,ch36st1},
+ {20,ch36st2}
+};
+
+static const SFG_StrokeChar ch36 = {76.2067f,3,ch36st};
+
+/* char: 0x25 */
+
+static const SFG_StrokeVertex ch37st0[] =
+{
+ {92.0743f,100.0f},
+ {6.36f,0.0f}
+};
+
+static const SFG_StrokeVertex ch37st1[] =
+{
+ {30.1695f,100.0f},
+ {39.6933f,90.4762f},
+ {39.6933f,80.9524f},
+ {34.9314f,71.4286f},
+ {25.4076f,66.6667f},
+ {15.8838f,66.6667f},
+ {6.36f,76.1905f},
+ {6.36f,85.7143f},
+ {11.1219f,95.2381f},
+ {20.6457f,100.0f},
+ {30.1695f,100.0f},
+ {39.6933f,95.2381f},
+ {53.979f,90.4762f},
+ {68.2648f,90.4762f},
+ {82.5505f,95.2381f},
+ {92.0743f,100.0f}
+};
+
+static const SFG_StrokeVertex ch37st2[] =
+{
+ {73.0267f,33.3333f},
+ {63.5029f,28.5714f},
+ {58.741f,19.0476f},
+ {58.741f,9.5238f},
+ {68.2648f,0.0f},
+ {77.7886f,0.0f},
+ {87.3124f,4.7619f},
+ {92.0743f,14.2857f},
+ {92.0743f,23.8095f},
+ {82.5505f,33.3333f},
+ {73.0267f,33.3333f}
+};
+
+static const SFG_StrokeStrip ch37st[] =
+{
+ {2,ch37st0},
+ {16,ch37st1},
+ {11,ch37st2}
+};
+
+static const SFG_StrokeChar ch37 = {96.5743f,3,ch37st};
+
+/* char: 0x26 */
+
+static const SFG_StrokeVertex ch38st0[] =
+{
+ {101.218f,57.1429f},
+ {101.218f,61.9048f},
+ {96.4562f,66.6667f},
+ {91.6943f,66.6667f},
+ {86.9324f,61.9048f},
+ {82.1705f,52.381f},
+ {72.6467f,28.5714f},
+ {63.1229f,14.2857f},
+ {53.599f,4.7619f},
+ {44.0752f,0.0f},
+ {25.0276f,0.0f},
+ {15.5038f,4.7619f},
+ {10.7419f,9.5238f},
+ {5.98f,19.0476f},
+ {5.98f,28.5714f},
+ {10.7419f,38.0952f},
+ {15.5038f,42.8571f},
+ {48.8371f,61.9048f},
+ {53.599f,66.6667f},
+ {58.361f,76.1905f},
+ {58.361f,85.7143f},
+ {53.599f,95.2381f},
+ {44.0752f,100.0f},
+ {34.5514f,95.2381f},
+ {29.7895f,85.7143f},
+ {29.7895f,76.1905f},
+ {34.5514f,61.9048f},
+ {44.0752f,47.619f},
+ {67.8848f,14.2857f},
+ {77.4086f,4.7619f},
+ {86.9324f,0.0f},
+ {96.4562f,0.0f},
+ {101.218f,4.7619f},
+ {101.218f,9.5238f}
+};
+
+static const SFG_StrokeStrip ch38st[] =
+{
+ {34,ch38st0}
+};
+
+static const SFG_StrokeChar ch38 = {101.758f,1,ch38st};
+
+/* char: 0x27 */
+
+static const SFG_StrokeVertex ch39st0[] =
+{
+ {4.44f,100.0f},
+ {4.44f,66.6667f}
+};
+
+static const SFG_StrokeStrip ch39st[] =
+{
+ {2,ch39st0}
+};
+
+static const SFG_StrokeChar ch39 = {13.62f,1,ch39st};
+
+/* char: 0x28 */
+
+static const SFG_StrokeVertex ch40st0[] =
+{
+ {40.9133f,119.048f},
+ {31.3895f,109.524f},
+ {21.8657f,95.2381f},
+ {12.3419f,76.1905f},
+ {7.58f,52.381f},
+ {7.58f,33.3333f},
+ {12.3419f,9.5238f},
+ {21.8657f,-9.5238f},
+ {31.3895f,-23.8095f},
+ {40.9133f,-33.3333f}
+};
+
+static const SFG_StrokeStrip ch40st[] =
+{
+ {10,ch40st0}
+};
+
+static const SFG_StrokeChar ch40 = {47.1733f,1,ch40st};
+
+/* char: 0x29 */
+
+static const SFG_StrokeVertex ch41st0[] =
+{
+ {5.28f,119.048f},
+ {14.8038f,109.524f},
+ {24.3276f,95.2381f},
+ {33.8514f,76.1905f},
+ {38.6133f,52.381f},
+ {38.6133f,33.3333f},
+ {33.8514f,9.5238f},
+ {24.3276f,-9.5238f},
+ {14.8038f,-23.8095f},
+ {5.28f,-33.3333f}
+};
+
+static const SFG_StrokeStrip ch41st[] =
+{
+ {10,ch41st0}
+};
+
+static const SFG_StrokeChar ch41 = {47.5333f,1,ch41st};
+
+/* char: 0x2a */
+
+static const SFG_StrokeVertex ch42st0[] =
+{
+ {30.7695f,71.4286f},
+ {30.7695f,14.2857f}
+};
+
+static const SFG_StrokeVertex ch42st1[] =
+{
+ {6.96f,57.1429f},
+ {54.579f,28.5714f}
+};
+
+static const SFG_StrokeVertex ch42st2[] =
+{
+ {54.579f,57.1429f},
+ {6.96f,28.5714f}
+};
+
+static const SFG_StrokeStrip ch42st[] =
+{
+ {2,ch42st0},
+ {2,ch42st1},
+ {2,ch42st2}
+};
+
+static const SFG_StrokeChar ch42 = {59.439f,3,ch42st};
+
+/* char: 0x2b */
+
+static const SFG_StrokeVertex ch43st0[] =
+{
+ {48.8371f,85.7143f},
+ {48.8371f,0.0f}
+};
+
+static const SFG_StrokeVertex ch43st1[] =
+{
+ {5.98f,42.8571f},
+ {91.6943f,42.8571f}
+};
+
+static const SFG_StrokeStrip ch43st[] =
+{
+ {2,ch43st0},
+ {2,ch43st1}
+};
+
+static const SFG_StrokeChar ch43 = {97.2543f,2,ch43st};
+
+/* char: 0x2c */
+
+static const SFG_StrokeVertex ch44st0[] =
+{
+ {18.2838f,4.7619f},
+ {13.5219f,0.0f},
+ {8.76f,4.7619f},
+ {13.5219f,9.5238f},
+ {18.2838f,4.7619f},
+ {18.2838f,-4.7619f},
+ {13.5219f,-14.2857f},
+ {8.76f,-19.0476f}
+};
+
+static const SFG_StrokeStrip ch44st[] =
+{
+ {8,ch44st0}
+};
+
+static const SFG_StrokeChar ch44 = {26.0638f,1,ch44st};
+
+/* char: 0x2d */
+
+static const SFG_StrokeVertex ch45st0[] =
+{
+ {7.38f,42.8571f},
+ {93.0943f,42.8571f}
+};
+
+static const SFG_StrokeStrip ch45st[] =
+{
+ {2,ch45st0}
+};
+
+static const SFG_StrokeChar ch45 = {100.754f,1,ch45st};
+
+/* char: 0x2e */
+
+static const SFG_StrokeVertex ch46st0[] =
+{
+ {13.1019f,9.5238f},
+ {8.34f,4.7619f},
+ {13.1019f,0.0f},
+ {17.8638f,4.7619f},
+ {13.1019f,9.5238f}
+};
+
+static const SFG_StrokeStrip ch46st[] =
+{
+ {5,ch46st0}
+};
+
+static const SFG_StrokeChar ch46 = {26.4838f,1,ch46st};
+
+/* char: 0x2f */
+
+static const SFG_StrokeVertex ch47st0[] =
+{
+ {7.24f,-14.2857f},
+ {73.9067f,100.0f}
+};
+
+static const SFG_StrokeStrip ch47st[] =
+{
+ {2,ch47st0}
+};
+
+static const SFG_StrokeChar ch47 = {82.1067f,1,ch47st};
+
+/* char: 0x30 */
+
+static const SFG_StrokeVertex ch48st0[] =
+{
+ {33.5514f,100.0f},
+ {19.2657f,95.2381f},
+ {9.7419f,80.9524f},
+ {4.98f,57.1429f},
+ {4.98f,42.8571f},
+ {9.7419f,19.0476f},
+ {19.2657f,4.7619f},
+ {33.5514f,0.0f},
+ {43.0752f,0.0f},
+ {57.361f,4.7619f},
+ {66.8848f,19.0476f},
+ {71.6467f,42.8571f},
+ {71.6467f,57.1429f},
+ {66.8848f,80.9524f},
+ {57.361f,95.2381f},
+ {43.0752f,100.0f},
+ {33.5514f,100.0f}
+};
+
+static const SFG_StrokeStrip ch48st[] =
+{
+ {17,ch48st0}
+};
+
+static const SFG_StrokeChar ch48 = {77.0667f,1,ch48st};
+
+/* char: 0x31 */
+
+static const SFG_StrokeVertex ch49st0[] =
+{
+ {11.82f,80.9524f},
+ {21.3438f,85.7143f},
+ {35.6295f,100.0f},
+ {35.6295f,0.0f}
+};
+
+static const SFG_StrokeStrip ch49st[] =
+{
+ {4,ch49st0}
+};
+
+static const SFG_StrokeChar ch49 = {66.5295f,1,ch49st};
+
+/* char: 0x32 */
+
+static const SFG_StrokeVertex ch50st0[] =
+{
+ {10.1819f,76.1905f},
+ {10.1819f,80.9524f},
+ {14.9438f,90.4762f},
+ {19.7057f,95.2381f},
+ {29.2295f,100.0f},
+ {48.2771f,100.0f},
+ {57.801f,95.2381f},
+ {62.5629f,90.4762f},
+ {67.3248f,80.9524f},
+ {67.3248f,71.4286f},
+ {62.5629f,61.9048f},
+ {53.039f,47.619f},
+ {5.42f,0.0f},
+ {72.0867f,0.0f}
+};
+
+static const SFG_StrokeStrip ch50st[] =
+{
+ {14,ch50st0}
+};
+
+static const SFG_StrokeChar ch50 = {77.6467f,1,ch50st};
+
+/* char: 0x33 */
+
+static const SFG_StrokeVertex ch51st0[] =
+{
+ {14.5238f,100.0f},
+ {66.9048f,100.0f},
+ {38.3333f,61.9048f},
+ {52.619f,61.9048f},
+ {62.1429f,57.1429f},
+ {66.9048f,52.381f},
+ {71.6667f,38.0952f},
+ {71.6667f,28.5714f},
+ {66.9048f,14.2857f},
+ {57.381f,4.7619f},
+ {43.0952f,0.0f},
+ {28.8095f,0.0f},
+ {14.5238f,4.7619f},
+ {9.7619f,9.5238f},
+ {5.0f,19.0476f}
+};
+
+static const SFG_StrokeStrip ch51st[] =
+{
+ {15,ch51st0}
+};
+
+static const SFG_StrokeChar ch51 = {77.0467f,1,ch51st};
+
+/* char: 0x34 */
+
+static const SFG_StrokeVertex ch52st0[] =
+{
+ {51.499f,100.0f},
+ {3.88f,33.3333f},
+ {75.3086f,33.3333f}
+};
+
+static const SFG_StrokeVertex ch52st1[] =
+{
+ {51.499f,100.0f},
+ {51.499f,0.0f}
+};
+
+static const SFG_StrokeStrip ch52st[] =
+{
+ {3,ch52st0},
+ {2,ch52st1}
+};
+
+static const SFG_StrokeChar ch52 = {80.1686f,2,ch52st};
+
+/* char: 0x35 */
+
+static const SFG_StrokeVertex ch53st0[] =
+{
+ {62.0029f,100.0f},
+ {14.3838f,100.0f},
+ {9.6219f,57.1429f},
+ {14.3838f,61.9048f},
+ {28.6695f,66.6667f},
+ {42.9552f,66.6667f},
+ {57.241f,61.9048f},
+ {66.7648f,52.381f},
+ {71.5267f,38.0952f},
+ {71.5267f,28.5714f},
+ {66.7648f,14.2857f},
+ {57.241f,4.7619f},
+ {42.9552f,0.0f},
+ {28.6695f,0.0f},
+ {14.3838f,4.7619f},
+ {9.6219f,9.5238f},
+ {4.86f,19.0476f}
+};
+
+static const SFG_StrokeStrip ch53st[] =
+{
+ {17,ch53st0}
+};
+
+static const SFG_StrokeChar ch53 = {77.6867f,1,ch53st};
+
+/* char: 0x36 */
+
+static const SFG_StrokeVertex ch54st0[] =
+{
+ {62.7229f,85.7143f},
+ {57.961f,95.2381f},
+ {43.6752f,100.0f},
+ {34.1514f,100.0f},
+ {19.8657f,95.2381f},
+ {10.3419f,80.9524f},
+ {5.58f,57.1429f},
+ {5.58f,33.3333f},
+ {10.3419f,14.2857f},
+ {19.8657f,4.7619f},
+ {34.1514f,0.0f},
+ {38.9133f,0.0f},
+ {53.199f,4.7619f},
+ {62.7229f,14.2857f},
+ {67.4848f,28.5714f},
+ {67.4848f,33.3333f},
+ {62.7229f,47.619f},
+ {53.199f,57.1429f},
+ {38.9133f,61.9048f},
+ {34.1514f,61.9048f},
+ {19.8657f,57.1429f},
+ {10.3419f,47.619f},
+ {5.58f,33.3333f}
+};
+
+static const SFG_StrokeStrip ch54st[] =
+{
+ {23,ch54st0}
+};
+
+static const SFG_StrokeChar ch54 = {73.8048f,1,ch54st};
+
+/* char: 0x37 */
+
+static const SFG_StrokeVertex ch55st0[] =
+{
+ {72.2267f,100.0f},
+ {24.6076f,0.0f}
+};
+
+static const SFG_StrokeVertex ch55st1[] =
+{
+ {5.56f,100.0f},
+ {72.2267f,100.0f}
+};
+
+static const SFG_StrokeStrip ch55st[] =
+{
+ {2,ch55st0},
+ {2,ch55st1}
+};
+
+static const SFG_StrokeChar ch55 = {77.2267f,2,ch55st};
+
+/* char: 0x38 */
+
+static const SFG_StrokeVertex ch56st0[] =
+{
+ {29.4095f,100.0f},
+ {15.1238f,95.2381f},
+ {10.3619f,85.7143f},
+ {10.3619f,76.1905f},
+ {15.1238f,66.6667f},
+ {24.6476f,61.9048f},
+ {43.6952f,57.1429f},
+ {57.981f,52.381f},
+ {67.5048f,42.8571f},
+ {72.2667f,33.3333f},
+ {72.2667f,19.0476f},
+ {67.5048f,9.5238f},
+ {62.7429f,4.7619f},
+ {48.4571f,0.0f},
+ {29.4095f,0.0f},
+ {15.1238f,4.7619f},
+ {10.3619f,9.5238f},
+ {5.6f,19.0476f},
+ {5.6f,33.3333f},
+ {10.3619f,42.8571f},
+ {19.8857f,52.381f},
+ {34.1714f,57.1429f},
+ {53.219f,61.9048f},
+ {62.7429f,66.6667f},
+ {67.5048f,76.1905f},
+ {67.5048f,85.7143f},
+ {62.7429f,95.2381f},
+ {48.4571f,100.0f},
+ {29.4095f,100.0f}
+};
+
+static const SFG_StrokeStrip ch56st[] =
+{
+ {29,ch56st0}
+};
+
+static const SFG_StrokeChar ch56 = {77.6667f,1,ch56st};
+
+/* char: 0x39 */
+
+static const SFG_StrokeVertex ch57st0[] =
+{
+ {68.5048f,66.6667f},
+ {63.7429f,52.381f},
+ {54.219f,42.8571f},
+ {39.9333f,38.0952f},
+ {35.1714f,38.0952f},
+ {20.8857f,42.8571f},
+ {11.3619f,52.381f},
+ {6.6f,66.6667f},
+ {6.6f,71.4286f},
+ {11.3619f,85.7143f},
+ {20.8857f,95.2381f},
+ {35.1714f,100.0f},
+ {39.9333f,100.0f},
+ {54.219f,95.2381f},
+ {63.7429f,85.7143f},
+ {68.5048f,66.6667f},
+ {68.5048f,42.8571f},
+ {63.7429f,19.0476f},
+ {54.219f,4.7619f},
+ {39.9333f,0.0f},
+ {30.4095f,0.0f},
+ {16.1238f,4.7619f},
+ {11.3619f,14.2857f}
+};
+
+static const SFG_StrokeStrip ch57st[] =
+{
+ {23,ch57st0}
+};
+
+static const SFG_StrokeChar ch57 = {74.0648f,1,ch57st};
+
+/* char: 0x3a */
+
+static const SFG_StrokeVertex ch58st0[] =
+{
+ {14.0819f,66.6667f},
+ {9.32f,61.9048f},
+ {14.0819f,57.1429f},
+ {18.8438f,61.9048f},
+ {14.0819f,66.6667f}
+};
+
+static const SFG_StrokeVertex ch58st1[] =
+{
+ {14.0819f,9.5238f},
+ {9.32f,4.7619f},
+ {14.0819f,0.0f},
+ {18.8438f,4.7619f},
+ {14.0819f,9.5238f}
+};
+
+static const SFG_StrokeStrip ch58st[] =
+{
+ {5,ch58st0},
+ {5,ch58st1}
+};
+
+static const SFG_StrokeChar ch58 = {26.2238f,2,ch58st};
+
+/* char: 0x3b */
+
+static const SFG_StrokeVertex ch59st0[] =
+{
+ {12.9619f,66.6667f},
+ {8.2f,61.9048f},
+ {12.9619f,57.1429f},
+ {17.7238f,61.9048f},
+ {12.9619f,66.6667f}
+};
+
+static const SFG_StrokeVertex ch59st1[] =
+{
+ {17.7238f,4.7619f},
+ {12.9619f,0.0f},
+ {8.2f,4.7619f},
+ {12.9619f,9.5238f},
+ {17.7238f,4.7619f},
+ {17.7238f,-4.7619f},
+ {12.9619f,-14.2857f},
+ {8.2f,-19.0476f}
+};
+
+static const SFG_StrokeStrip ch59st[] =
+{
+ {5,ch59st0},
+ {8,ch59st1}
+};
+
+static const SFG_StrokeChar ch59 = {26.3038f,2,ch59st};
+
+/* char: 0x3c */
+
+static const SFG_StrokeVertex ch60st0[] =
+{
+ {79.2505f,85.7143f},
+ {3.06f,42.8571f},
+ {79.2505f,0.0f}
+};
+
+static const SFG_StrokeStrip ch60st[] =
+{
+ {3,ch60st0}
+};
+
+static const SFG_StrokeChar ch60 = {81.6105f,1,ch60st};
+
+/* char: 0x3d */
+
+static const SFG_StrokeVertex ch61st0[] =
+{
+ {5.7f,57.1429f},
+ {91.4143f,57.1429f}
+};
+
+static const SFG_StrokeVertex ch61st1[] =
+{
+ {5.7f,28.5714f},
+ {91.4143f,28.5714f}
+};
+
+static const SFG_StrokeStrip ch61st[] =
+{
+ {2,ch61st0},
+ {2,ch61st1}
+};
+
+static const SFG_StrokeChar ch61 = {97.2543f,2,ch61st};
+
+/* char: 0x3e */
+
+static const SFG_StrokeVertex ch62st0[] =
+{
+ {2.78f,85.7143f},
+ {78.9705f,42.8571f},
+ {2.78f,0.0f}
+};
+
+static const SFG_StrokeStrip ch62st[] =
+{
+ {3,ch62st0}
+};
+
+static const SFG_StrokeChar ch62 = {81.6105f,1,ch62st};
+
+/* char: 0x3f */
+
+static const SFG_StrokeVertex ch63st0[] =
+{
+ {8.42f,76.1905f},
+ {8.42f,80.9524f},
+ {13.1819f,90.4762f},
+ {17.9438f,95.2381f},
+ {27.4676f,100.0f},
+ {46.5152f,100.0f},
+ {56.039f,95.2381f},
+ {60.801f,90.4762f},
+ {65.5629f,80.9524f},
+ {65.5629f,71.4286f},
+ {60.801f,61.9048f},
+ {56.039f,57.1429f},
+ {36.9914f,47.619f},
+ {36.9914f,33.3333f}
+};
+
+static const SFG_StrokeVertex ch63st1[] =
+{
+ {36.9914f,9.5238f},
+ {32.2295f,4.7619f},
+ {36.9914f,0.0f},
+ {41.7533f,4.7619f},
+ {36.9914f,9.5238f}
+};
+
+static const SFG_StrokeStrip ch63st[] =
+{
+ {14,ch63st0},
+ {5,ch63st1}
+};
+
+static const SFG_StrokeChar ch63 = {73.9029f,2,ch63st};
+
+/* char: 0x40 */
+
+static const SFG_StrokeVertex ch64st0[] =
+{
+ {49.2171f,52.381f},
+ {39.6933f,57.1429f},
+ {30.1695f,57.1429f},
+ {25.4076f,47.619f},
+ {25.4076f,42.8571f},
+ {30.1695f,33.3333f},
+ {39.6933f,33.3333f},
+ {49.2171f,38.0952f}
+};
+
+static const SFG_StrokeVertex ch64st1[] =
+{
+ {49.2171f,57.1429f},
+ {49.2171f,38.0952f},
+ {53.979f,33.3333f},
+ {63.5029f,33.3333f},
+ {68.2648f,42.8571f},
+ {68.2648f,47.619f},
+ {63.5029f,61.9048f},
+ {53.979f,71.4286f},
+ {39.6933f,76.1905f},
+ {34.9314f,76.1905f},
+ {20.6457f,71.4286f},
+ {11.1219f,61.9048f},
+ {6.36f,47.619f},
+ {6.36f,42.8571f},
+ {11.1219f,28.5714f},
+ {20.6457f,19.0476f},
+ {34.9314f,14.2857f},
+ {39.6933f,14.2857f},
+ {53.979f,19.0476f}
+};
+
+static const SFG_StrokeStrip ch64st[] =
+{
+ {8,ch64st0},
+ {19,ch64st1}
+};
+
+static const SFG_StrokeChar ch64 = {74.3648f,2,ch64st};
+
+/* char: 0x41 */
+
+static const SFG_StrokeVertex ch65st0[] =
+{
+ {40.5952f,100.0f},
+ {2.5f,0.0f}
+};
+
+static const SFG_StrokeVertex ch65st1[] =
+{
+ {40.5952f,100.0f},
+ {78.6905f,0.0f}
+};
+
+static const SFG_StrokeVertex ch65st2[] =
+{
+ {16.7857f,33.3333f},
+ {64.4048f,33.3333f}
+};
+
+static const SFG_StrokeStrip ch65st[] =
+{
+ {2,ch65st0},
+ {2,ch65st1},
+ {2,ch65st2}
+};
+
+static const SFG_StrokeChar ch65 = {80.4905f,3,ch65st};
+
+/* char: 0x42 */
+
+static const SFG_StrokeVertex ch66st0[] =
+{
+ {11.42f,100.0f},
+ {11.42f,0.0f}
+};
+
+static const SFG_StrokeVertex ch66st1[] =
+{
+ {11.42f,100.0f},
+ {54.2771f,100.0f},
+ {68.5629f,95.2381f},
+ {73.3248f,90.4762f},
+ {78.0867f,80.9524f},
+ {78.0867f,71.4286f},
+ {73.3248f,61.9048f},
+ {68.5629f,57.1429f},
+ {54.2771f,52.381f}
+};
+
+static const SFG_StrokeVertex ch66st2[] =
+{
+ {11.42f,52.381f},
+ {54.2771f,52.381f},
+ {68.5629f,47.619f},
+ {73.3248f,42.8571f},
+ {78.0867f,33.3333f},
+ {78.0867f,19.0476f},
+ {73.3248f,9.5238f},
+ {68.5629f,4.7619f},
+ {54.2771f,0.0f},
+ {11.42f,0.0f}
+};
+
+static const SFG_StrokeStrip ch66st[] =
+{
+ {2,ch66st0},
+ {9,ch66st1},
+ {10,ch66st2}
+};
+
+static const SFG_StrokeChar ch66 = {83.6267f,3,ch66st};
+
+/* char: 0x43 */
+
+static const SFG_StrokeVertex ch67st0[] =
+{
+ {78.0886f,76.1905f},
+ {73.3267f,85.7143f},
+ {63.8029f,95.2381f},
+ {54.279f,100.0f},
+ {35.2314f,100.0f},
+ {25.7076f,95.2381f},
+ {16.1838f,85.7143f},
+ {11.4219f,76.1905f},
+ {6.66f,61.9048f},
+ {6.66f,38.0952f},
+ {11.4219f,23.8095f},
+ {16.1838f,14.2857f},
+ {25.7076f,4.7619f},
+ {35.2314f,0.0f},
+ {54.279f,0.0f},
+ {63.8029f,4.7619f},
+ {73.3267f,14.2857f},
+ {78.0886f,23.8095f}
+};
+
+static const SFG_StrokeStrip ch67st[] =
+{
+ {18,ch67st0}
+};
+
+static const SFG_StrokeChar ch67 = {84.4886f,1,ch67st};
+
+/* char: 0x44 */
+
+static const SFG_StrokeVertex ch68st0[] =
+{
+ {11.96f,100.0f},
+ {11.96f,0.0f}
+};
+
+static const SFG_StrokeVertex ch68st1[] =
+{
+ {11.96f,100.0f},
+ {45.2933f,100.0f},
+ {59.579f,95.2381f},
+ {69.1029f,85.7143f},
+ {73.8648f,76.1905f},
+ {78.6267f,61.9048f},
+ {78.6267f,38.0952f},
+ {73.8648f,23.8095f},
+ {69.1029f,14.2857f},
+ {59.579f,4.7619f},
+ {45.2933f,0.0f},
+ {11.96f,0.0f}
+};
+
+static const SFG_StrokeStrip ch68st[] =
+{
+ {2,ch68st0},
+ {12,ch68st1}
+};
+
+static const SFG_StrokeChar ch68 = {85.2867f,2,ch68st};
+
+/* char: 0x45 */
+
+static const SFG_StrokeVertex ch69st0[] =
+{
+ {11.42f,100.0f},
+ {11.42f,0.0f}
+};
+
+static const SFG_StrokeVertex ch69st1[] =
+{
+ {11.42f,100.0f},
+ {73.3248f,100.0f}
+};
+
+static const SFG_StrokeVertex ch69st2[] =
+{
+ {11.42f,52.381f},
+ {49.5152f,52.381f}
+};
+
+static const SFG_StrokeVertex ch69st3[] =
+{
+ {11.42f,0.0f},
+ {73.3248f,0.0f}
+};
+
+static const SFG_StrokeStrip ch69st[] =
+{
+ {2,ch69st0},
+ {2,ch69st1},
+ {2,ch69st2},
+ {2,ch69st3}
+};
+
+static const SFG_StrokeChar ch69 = {78.1848f,4,ch69st};
+
+/* char: 0x46 */
+
+static const SFG_StrokeVertex ch70st0[] =
+{
+ {11.42f,100.0f},
+ {11.42f,0.0f}
+};
+
+static const SFG_StrokeVertex ch70st1[] =
+{
+ {11.42f,100.0f},
+ {73.3248f,100.0f}
+};
+
+static const SFG_StrokeVertex ch70st2[] =
+{
+ {11.42f,52.381f},
+ {49.5152f,52.381f}
+};
+
+static const SFG_StrokeStrip ch70st[] =
+{
+ {2,ch70st0},
+ {2,ch70st1},
+ {2,ch70st2}
+};
+
+static const SFG_StrokeChar ch70 = {78.7448f,3,ch70st};
+
+/* char: 0x47 */
+
+static const SFG_StrokeVertex ch71st0[] =
+{
+ {78.4886f,76.1905f},
+ {73.7267f,85.7143f},
+ {64.2029f,95.2381f},
+ {54.679f,100.0f},
+ {35.6314f,100.0f},
+ {26.1076f,95.2381f},
+ {16.5838f,85.7143f},
+ {11.8219f,76.1905f},
+ {7.06f,61.9048f},
+ {7.06f,38.0952f},
+ {11.8219f,23.8095f},
+ {16.5838f,14.2857f},
+ {26.1076f,4.7619f},
+ {35.6314f,0.0f},
+ {54.679f,0.0f},
+ {64.2029f,4.7619f},
+ {73.7267f,14.2857f},
+ {78.4886f,23.8095f},
+ {78.4886f,38.0952f}
+};
+
+static const SFG_StrokeVertex ch71st1[] =
+{
+ {54.679f,38.0952f},
+ {78.4886f,38.0952f}
+};
+
+static const SFG_StrokeStrip ch71st[] =
+{
+ {19,ch71st0},
+ {2,ch71st1}
+};
+
+static const SFG_StrokeChar ch71 = {89.7686f,2,ch71st};
+
+/* char: 0x48 */
+
+static const SFG_StrokeVertex ch72st0[] =
+{
+ {11.42f,100.0f},
+ {11.42f,0.0f}
+};
+
+static const SFG_StrokeVertex ch72st1[] =
+{
+ {78.0867f,100.0f},
+ {78.0867f,0.0f}
+};
+
+static const SFG_StrokeVertex ch72st2[] =
+{
+ {11.42f,52.381f},
+ {78.0867f,52.381f}
+};
+
+static const SFG_StrokeStrip ch72st[] =
+{
+ {2,ch72st0},
+ {2,ch72st1},
+ {2,ch72st2}
+};
+
+static const SFG_StrokeChar ch72 = {89.0867f,3,ch72st};
+
+/* char: 0x49 */
+
+static const SFG_StrokeVertex ch73st0[] =
+{
+ {10.86f,100.0f},
+ {10.86f,0.0f}
+};
+
+static const SFG_StrokeStrip ch73st[] =
+{
+ {2,ch73st0}
+};
+
+static const SFG_StrokeChar ch73 = {21.3f,1,ch73st};
+
+/* char: 0x4a */
+
+static const SFG_StrokeVertex ch74st0[] =
+{
+ {50.119f,100.0f},
+ {50.119f,23.8095f},
+ {45.3571f,9.5238f},
+ {40.5952f,4.7619f},
+ {31.0714f,0.0f},
+ {21.5476f,0.0f},
+ {12.0238f,4.7619f},
+ {7.2619f,9.5238f},
+ {2.5f,23.8095f},
+ {2.5f,33.3333f}
+};
+
+static const SFG_StrokeStrip ch74st[] =
+{
+ {10,ch74st0}
+};
+
+static const SFG_StrokeChar ch74 = {59.999f,1,ch74st};
+
+/* char: 0x4b */
+
+static const SFG_StrokeVertex ch75st0[] =
+{
+ {11.28f,100.0f},
+ {11.28f,0.0f}
+};
+
+static const SFG_StrokeVertex ch75st1[] =
+{
+ {77.9467f,100.0f},
+ {11.28f,33.3333f}
+};
+
+static const SFG_StrokeVertex ch75st2[] =
+{
+ {35.0895f,57.1429f},
+ {77.9467f,0.0f}
+};
+
+static const SFG_StrokeStrip ch75st[] =
+{
+ {2,ch75st0},
+ {2,ch75st1},
+ {2,ch75st2}
+};
+
+static const SFG_StrokeChar ch75 = {79.3267f,3,ch75st};
+
+/* char: 0x4c */
+
+static const SFG_StrokeVertex ch76st0[] =
+{
+ {11.68f,100.0f},
+ {11.68f,0.0f}
+};
+
+static const SFG_StrokeVertex ch76st1[] =
+{
+ {11.68f,0.0f},
+ {68.8229f,0.0f}
+};
+
+static const SFG_StrokeStrip ch76st[] =
+{
+ {2,ch76st0},
+ {2,ch76st1}
+};
+
+static const SFG_StrokeChar ch76 = {71.3229f,2,ch76st};
+
+/* char: 0x4d */
+
+static const SFG_StrokeVertex ch77st0[] =
+{
+ {10.86f,100.0f},
+ {10.86f,0.0f}
+};
+
+static const SFG_StrokeVertex ch77st1[] =
+{
+ {10.86f,100.0f},
+ {48.9552f,0.0f}
+};
+
+static const SFG_StrokeVertex ch77st2[] =
+{
+ {87.0505f,100.0f},
+ {48.9552f,0.0f}
+};
+
+static const SFG_StrokeVertex ch77st3[] =
+{
+ {87.0505f,100.0f},
+ {87.0505f,0.0f}
+};
+
+static const SFG_StrokeStrip ch77st[] =
+{
+ {2,ch77st0},
+ {2,ch77st1},
+ {2,ch77st2},
+ {2,ch77st3}
+};
+
+static const SFG_StrokeChar ch77 = {97.2105f,4,ch77st};
+
+/* char: 0x4e */
+
+static const SFG_StrokeVertex ch78st0[] =
+{
+ {11.14f,100.0f},
+ {11.14f,0.0f}
+};
+
+static const SFG_StrokeVertex ch78st1[] =
+{
+ {11.14f,100.0f},
+ {77.8067f,0.0f}
+};
+
+static const SFG_StrokeVertex ch78st2[] =
+{
+ {77.8067f,100.0f},
+ {77.8067f,0.0f}
+};
+
+static const SFG_StrokeStrip ch78st[] =
+{
+ {2,ch78st0},
+ {2,ch78st1},
+ {2,ch78st2}
+};
+
+static const SFG_StrokeChar ch78 = {88.8067f,3,ch78st};
+
+/* char: 0x4f */
+
+static const SFG_StrokeVertex ch79st0[] =
+{
+ {34.8114f,100.0f},
+ {25.2876f,95.2381f},
+ {15.7638f,85.7143f},
+ {11.0019f,76.1905f},
+ {6.24f,61.9048f},
+ {6.24f,38.0952f},
+ {11.0019f,23.8095f},
+ {15.7638f,14.2857f},
+ {25.2876f,4.7619f},
+ {34.8114f,0.0f},
+ {53.859f,0.0f},
+ {63.3829f,4.7619f},
+ {72.9067f,14.2857f},
+ {77.6686f,23.8095f},
+ {82.4305f,38.0952f},
+ {82.4305f,61.9048f},
+ {77.6686f,76.1905f},
+ {72.9067f,85.7143f},
+ {63.3829f,95.2381f},
+ {53.859f,100.0f},
+ {34.8114f,100.0f}
+};
+
+static const SFG_StrokeStrip ch79st[] =
+{
+ {21,ch79st0}
+};
+
+static const SFG_StrokeChar ch79 = {88.8305f,1,ch79st};
+
+/* char: 0x50 */
+
+static const SFG_StrokeVertex ch80st0[] =
+{
+ {12.1f,100.0f},
+ {12.1f,0.0f}
+};
+
+static const SFG_StrokeVertex ch80st1[] =
+{
+ {12.1f,100.0f},
+ {54.9571f,100.0f},
+ {69.2429f,95.2381f},
+ {74.0048f,90.4762f},
+ {78.7667f,80.9524f},
+ {78.7667f,66.6667f},
+ {74.0048f,57.1429f},
+ {69.2429f,52.381f},
+ {54.9571f,47.619f},
+ {12.1f,47.619f}
+};
+
+static const SFG_StrokeStrip ch80st[] =
+{
+ {2,ch80st0},
+ {10,ch80st1}
+};
+
+static const SFG_StrokeChar ch80 = {85.6667f,2,ch80st};
+
+/* char: 0x51 */
+
+static const SFG_StrokeVertex ch81st0[] =
+{
+ {33.8714f,100.0f},
+ {24.3476f,95.2381f},
+ {14.8238f,85.7143f},
+ {10.0619f,76.1905f},
+ {5.3f,61.9048f},
+ {5.3f,38.0952f},
+ {10.0619f,23.8095f},
+ {14.8238f,14.2857f},
+ {24.3476f,4.7619f},
+ {33.8714f,0.0f},
+ {52.919f,0.0f},
+ {62.4429f,4.7619f},
+ {71.9667f,14.2857f},
+ {76.7286f,23.8095f},
+ {81.4905f,38.0952f},
+ {81.4905f,61.9048f},
+ {76.7286f,76.1905f},
+ {71.9667f,85.7143f},
+ {62.4429f,95.2381f},
+ {52.919f,100.0f},
+ {33.8714f,100.0f}
+};
+
+static const SFG_StrokeVertex ch81st1[] =
+{
+ {48.1571f,19.0476f},
+ {76.7286f,-9.5238f}
+};
+
+static const SFG_StrokeStrip ch81st[] =
+{
+ {21,ch81st0},
+ {2,ch81st1}
+};
+
+static const SFG_StrokeChar ch81 = {88.0905f,2,ch81st};
+
+/* char: 0x52 */
+
+static const SFG_StrokeVertex ch82st0[] =
+{
+ {11.68f,100.0f},
+ {11.68f,0.0f}
+};
+
+static const SFG_StrokeVertex ch82st1[] =
+{
+ {11.68f,100.0f},
+ {54.5371f,100.0f},
+ {68.8229f,95.2381f},
+ {73.5848f,90.4762f},
+ {78.3467f,80.9524f},
+ {78.3467f,71.4286f},
+ {73.5848f,61.9048f},
+ {68.8229f,57.1429f},
+ {54.5371f,52.381f},
+ {11.68f,52.381f}
+};
+
+static const SFG_StrokeVertex ch82st2[] =
+{
+ {45.0133f,52.381f},
+ {78.3467f,0.0f}
+};
+
+static const SFG_StrokeStrip ch82st[] =
+{
+ {2,ch82st0},
+ {10,ch82st1},
+ {2,ch82st2}
+};
+
+static const SFG_StrokeChar ch82 = {82.3667f,3,ch82st};
+
+/* char: 0x53 */
+
+static const SFG_StrokeVertex ch83st0[] =
+{
+ {74.6667f,85.7143f},
+ {65.1429f,95.2381f},
+ {50.8571f,100.0f},
+ {31.8095f,100.0f},
+ {17.5238f,95.2381f},
+ {8.0f,85.7143f},
+ {8.0f,76.1905f},
+ {12.7619f,66.6667f},
+ {17.5238f,61.9048f},
+ {27.0476f,57.1429f},
+ {55.619f,47.619f},
+ {65.1429f,42.8571f},
+ {69.9048f,38.0952f},
+ {74.6667f,28.5714f},
+ {74.6667f,14.2857f},
+ {65.1429f,4.7619f},
+ {50.8571f,0.0f},
+ {31.8095f,0.0f},
+ {17.5238f,4.7619f},
+ {8.0f,14.2857f}
+};
+
+static const SFG_StrokeStrip ch83st[] =
+{
+ {20,ch83st0}
+};
+
+static const SFG_StrokeChar ch83 = {80.8267f,1,ch83st};
+
+/* char: 0x54 */
+
+static const SFG_StrokeVertex ch84st0[] =
+{
+ {35.6933f,100.0f},
+ {35.6933f,0.0f}
+};
+
+static const SFG_StrokeVertex ch84st1[] =
+{
+ {2.36f,100.0f},
+ {69.0267f,100.0f}
+};
+
+static const SFG_StrokeStrip ch84st[] =
+{
+ {2,ch84st0},
+ {2,ch84st1}
+};
+
+static const SFG_StrokeChar ch84 = {71.9467f,2,ch84st};
+
+/* char: 0x55 */
+
+static const SFG_StrokeVertex ch85st0[] =
+{
+ {11.54f,100.0f},
+ {11.54f,28.5714f},
+ {16.3019f,14.2857f},
+ {25.8257f,4.7619f},
+ {40.1114f,0.0f},
+ {49.6352f,0.0f},
+ {63.921f,4.7619f},
+ {73.4448f,14.2857f},
+ {78.2067f,28.5714f},
+ {78.2067f,100.0f}
+};
+
+static const SFG_StrokeStrip ch85st[] =
+{
+ {10,ch85st0}
+};
+
+static const SFG_StrokeChar ch85 = {89.4867f,1,ch85st};
+
+/* char: 0x56 */
+
+static const SFG_StrokeVertex ch86st0[] =
+{
+ {2.36f,100.0f},
+ {40.4552f,0.0f}
+};
+
+static const SFG_StrokeVertex ch86st1[] =
+{
+ {78.5505f,100.0f},
+ {40.4552f,0.0f}
+};
+
+static const SFG_StrokeStrip ch86st[] =
+{
+ {2,ch86st0},
+ {2,ch86st1}
+};
+
+static const SFG_StrokeChar ch86 = {81.6105f,2,ch86st};
+
+/* char: 0x57 */
+
+static const SFG_StrokeVertex ch87st0[] =
+{
+ {2.22f,100.0f},
+ {26.0295f,0.0f}
+};
+
+static const SFG_StrokeVertex ch87st1[] =
+{
+ {49.839f,100.0f},
+ {26.0295f,0.0f}
+};
+
+static const SFG_StrokeVertex ch87st2[] =
+{
+ {49.839f,100.0f},
+ {73.6486f,0.0f}
+};
+
+static const SFG_StrokeVertex ch87st3[] =
+{
+ {97.4581f,100.0f},
+ {73.6486f,0.0f}
+};
+
+static const SFG_StrokeStrip ch87st[] =
+{
+ {2,ch87st0},
+ {2,ch87st1},
+ {2,ch87st2},
+ {2,ch87st3}
+};
+
+static const SFG_StrokeChar ch87 = {100.518f,4,ch87st};
+
+/* char: 0x58 */
+
+static const SFG_StrokeVertex ch88st0[] =
+{
+ {2.5f,100.0f},
+ {69.1667f,0.0f}
+};
+
+static const SFG_StrokeVertex ch88st1[] =
+{
+ {69.1667f,100.0f},
+ {2.5f,0.0f}
+};
+
+static const SFG_StrokeStrip ch88st[] =
+{
+ {2,ch88st0},
+ {2,ch88st1}
+};
+
+static const SFG_StrokeChar ch88 = {72.3667f,2,ch88st};
+
+/* char: 0x59 */
+
+static const SFG_StrokeVertex ch89st0[] =
+{
+ {1.52f,100.0f},
+ {39.6152f,52.381f},
+ {39.6152f,0.0f}
+};
+
+static const SFG_StrokeVertex ch89st1[] =
+{
+ {77.7105f,100.0f},
+ {39.6152f,52.381f}
+};
+
+static const SFG_StrokeStrip ch89st[] =
+{
+ {3,ch89st0},
+ {2,ch89st1}
+};
+
+static const SFG_StrokeChar ch89 = {79.6505f,2,ch89st};
+
+/* char: 0x5a */
+
+static const SFG_StrokeVertex ch90st0[] =
+{
+ {69.1667f,100.0f},
+ {2.5f,0.0f}
+};
+
+static const SFG_StrokeVertex ch90st1[] =
+{
+ {2.5f,100.0f},
+ {69.1667f,100.0f}
+};
+
+static const SFG_StrokeVertex ch90st2[] =
+{
+ {2.5f,0.0f},
+ {69.1667f,0.0f}
+};
+
+static const SFG_StrokeStrip ch90st[] =
+{
+ {2,ch90st0},
+ {2,ch90st1},
+ {2,ch90st2}
+};
+
+static const SFG_StrokeChar ch90 = {73.7467f,3,ch90st};
+
+/* char: 0x5b */
+
+static const SFG_StrokeVertex ch91st0[] =
+{
+ {7.78f,119.048f},
+ {7.78f,-33.3333f}
+};
+
+static const SFG_StrokeVertex ch91st1[] =
+{
+ {12.5419f,119.048f},
+ {12.5419f,-33.3333f}
+};
+
+static const SFG_StrokeVertex ch91st2[] =
+{
+ {7.78f,119.048f},
+ {41.1133f,119.048f}
+};
+
+static const SFG_StrokeVertex ch91st3[] =
+{
+ {7.78f,-33.3333f},
+ {41.1133f,-33.3333f}
+};
+
+static const SFG_StrokeStrip ch91st[] =
+{
+ {2,ch91st0},
+ {2,ch91st1},
+ {2,ch91st2},
+ {2,ch91st3}
+};
+
+static const SFG_StrokeChar ch91 = {46.1133f,4,ch91st};
+
+/* char: 0x5c */
+
+static const SFG_StrokeVertex ch92st0[] =
+{
+ {5.84f,100.0f},
+ {72.5067f,-14.2857f}
+};
+
+static const SFG_StrokeStrip ch92st[] =
+{
+ {2,ch92st0}
+};
+
+static const SFG_StrokeChar ch92 = {78.2067f,1,ch92st};
+
+/* char: 0x5d */
+
+static const SFG_StrokeVertex ch93st0[] =
+{
+ {33.0114f,119.048f},
+ {33.0114f,-33.3333f}
+};
+
+static const SFG_StrokeVertex ch93st1[] =
+{
+ {37.7733f,119.048f},
+ {37.7733f,-33.3333f}
+};
+
+static const SFG_StrokeVertex ch93st2[] =
+{
+ {4.44f,119.048f},
+ {37.7733f,119.048f}
+};
+
+static const SFG_StrokeVertex ch93st3[] =
+{
+ {4.44f,-33.3333f},
+ {37.7733f,-33.3333f}
+};
+
+static const SFG_StrokeStrip ch93st[] =
+{
+ {2,ch93st0},
+ {2,ch93st1},
+ {2,ch93st2},
+ {2,ch93st3}
+};
+
+static const SFG_StrokeChar ch93 = {46.3933f,4,ch93st};
+
+/* char: 0x5e */
+
+static const SFG_StrokeVertex ch94st0[] =
+{
+ {44.0752f,109.524f},
+ {5.98f,42.8571f}
+};
+
+static const SFG_StrokeVertex ch94st1[] =
+{
+ {44.0752f,109.524f},
+ {82.1705f,42.8571f}
+};
+
+static const SFG_StrokeStrip ch94st[] =
+{
+ {2,ch94st0},
+ {2,ch94st1}
+};
+
+static const SFG_StrokeChar ch94 = {90.2305f,2,ch94st};
+
+/* char: 0x5f */
+
+static const SFG_StrokeVertex ch95st0[] =
+{
+ {-1.1f,-33.3333f},
+ {103.662f,-33.3333f},
+ {103.662f,-28.5714f},
+ {-1.1f,-28.5714f},
+ {-1.1f,-33.3333f}
+};
+
+static const SFG_StrokeStrip ch95st[] =
+{
+ {5,ch95st0}
+};
+
+static const SFG_StrokeChar ch95 = {104.062f,1,ch95st};
+
+/* char: 0x60 */
+
+static const SFG_StrokeVertex ch96st0[] =
+{
+ {33.0219f,100.0f},
+ {56.8314f,71.4286f}
+};
+
+static const SFG_StrokeVertex ch96st1[] =
+{
+ {33.0219f,100.0f},
+ {28.26f,95.2381f},
+ {56.8314f,71.4286f}
+};
+
+static const SFG_StrokeStrip ch96st[] =
+{
+ {2,ch96st0},
+ {3,ch96st1}
+};
+
+static const SFG_StrokeChar ch96 = {83.5714f,2,ch96st};
+
+/* char: 0x61 */
+
+static const SFG_StrokeVertex ch97st0[] =
+{
+ {63.8229f,66.6667f},
+ {63.8229f,0.0f}
+};
+
+static const SFG_StrokeVertex ch97st1[] =
+{
+ {63.8229f,52.381f},
+ {54.299f,61.9048f},
+ {44.7752f,66.6667f},
+ {30.4895f,66.6667f},
+ {20.9657f,61.9048f},
+ {11.4419f,52.381f},
+ {6.68f,38.0952f},
+ {6.68f,28.5714f},
+ {11.4419f,14.2857f},
+ {20.9657f,4.7619f},
+ {30.4895f,0.0f},
+ {44.7752f,0.0f},
+ {54.299f,4.7619f},
+ {63.8229f,14.2857f}
+};
+
+static const SFG_StrokeStrip ch97st[] =
+{
+ {2,ch97st0},
+ {14,ch97st1}
+};
+
+static const SFG_StrokeChar ch97 = {66.6029f,2,ch97st};
+
+/* char: 0x62 */
+
+static const SFG_StrokeVertex ch98st0[] =
+{
+ {8.76f,100.0f},
+ {8.76f,0.0f}
+};
+
+static const SFG_StrokeVertex ch98st1[] =
+{
+ {8.76f,52.381f},
+ {18.2838f,61.9048f},
+ {27.8076f,66.6667f},
+ {42.0933f,66.6667f},
+ {51.6171f,61.9048f},
+ {61.141f,52.381f},
+ {65.9029f,38.0952f},
+ {65.9029f,28.5714f},
+ {61.141f,14.2857f},
+ {51.6171f,4.7619f},
+ {42.0933f,0.0f},
+ {27.8076f,0.0f},
+ {18.2838f,4.7619f},
+ {8.76f,14.2857f}
+};
+
+static const SFG_StrokeStrip ch98st[] =
+{
+ {2,ch98st0},
+ {14,ch98st1}
+};
+
+static const SFG_StrokeChar ch98 = {70.4629f,2,ch98st};
+
+/* char: 0x63 */
+
+static const SFG_StrokeVertex ch99st0[] =
+{
+ {62.6629f,52.381f},
+ {53.139f,61.9048f},
+ {43.6152f,66.6667f},
+ {29.3295f,66.6667f},
+ {19.8057f,61.9048f},
+ {10.2819f,52.381f},
+ {5.52f,38.0952f},
+ {5.52f,28.5714f},
+ {10.2819f,14.2857f},
+ {19.8057f,4.7619f},
+ {29.3295f,0.0f},
+ {43.6152f,0.0f},
+ {53.139f,4.7619f},
+ {62.6629f,14.2857f}
+};
+
+static const SFG_StrokeStrip ch99st[] =
+{
+ {14,ch99st0}
+};
+
+static const SFG_StrokeChar ch99 = {68.9229f,1,ch99st};
+
+/* char: 0x64 */
+
+static const SFG_StrokeVertex ch100st0[] =
+{
+ {61.7829f,100.0f},
+ {61.7829f,0.0f}
+};
+
+static const SFG_StrokeVertex ch100st1[] =
+{
+ {61.7829f,52.381f},
+ {52.259f,61.9048f},
+ {42.7352f,66.6667f},
+ {28.4495f,66.6667f},
+ {18.9257f,61.9048f},
+ {9.4019f,52.381f},
+ {4.64f,38.0952f},
+ {4.64f,28.5714f},
+ {9.4019f,14.2857f},
+ {18.9257f,4.7619f},
+ {28.4495f,0.0f},
+ {42.7352f,0.0f},
+ {52.259f,4.7619f},
+ {61.7829f,14.2857f}
+};
+
+static const SFG_StrokeStrip ch100st[] =
+{
+ {2,ch100st0},
+ {14,ch100st1}
+};
+
+static const SFG_StrokeChar ch100 = {70.2629f,2,ch100st};
+
+/* char: 0x65 */
+
+static const SFG_StrokeVertex ch101st0[] =
+{
+ {5.72f,38.0952f},
+ {62.8629f,38.0952f},
+ {62.8629f,47.619f},
+ {58.101f,57.1429f},
+ {53.339f,61.9048f},
+ {43.8152f,66.6667f},
+ {29.5295f,66.6667f},
+ {20.0057f,61.9048f},
+ {10.4819f,52.381f},
+ {5.72f,38.0952f},
+ {5.72f,28.5714f},
+ {10.4819f,14.2857f},
+ {20.0057f,4.7619f},
+ {29.5295f,0.0f},
+ {43.8152f,0.0f},
+ {53.339f,4.7619f},
+ {62.8629f,14.2857f}
+};
+
+static const SFG_StrokeStrip ch101st[] =
+{
+ {17,ch101st0}
+};
+
+static const SFG_StrokeChar ch101 = {68.5229f,1,ch101st};
+
+/* char: 0x66 */
+
+static const SFG_StrokeVertex ch102st0[] =
+{
+ {38.7752f,100.0f},
+ {29.2514f,100.0f},
+ {19.7276f,95.2381f},
+ {14.9657f,80.9524f},
+ {14.9657f,0.0f}
+};
+
+static const SFG_StrokeVertex ch102st1[] =
+{
+ {0.68f,66.6667f},
+ {34.0133f,66.6667f}
+};
+
+static const SFG_StrokeStrip ch102st[] =
+{
+ {5,ch102st0},
+ {2,ch102st1}
+};
+
+static const SFG_StrokeChar ch102 = {38.6552f,2,ch102st};
+
+/* char: 0x67 */
+
+static const SFG_StrokeVertex ch103st0[] =
+{
+ {62.5029f,66.6667f},
+ {62.5029f,-9.5238f},
+ {57.741f,-23.8095f},
+ {52.979f,-28.5714f},
+ {43.4552f,-33.3333f},
+ {29.1695f,-33.3333f},
+ {19.6457f,-28.5714f}
+};
+
+static const SFG_StrokeVertex ch103st1[] =
+{
+ {62.5029f,52.381f},
+ {52.979f,61.9048f},
+ {43.4552f,66.6667f},
+ {29.1695f,66.6667f},
+ {19.6457f,61.9048f},
+ {10.1219f,52.381f},
+ {5.36f,38.0952f},
+ {5.36f,28.5714f},
+ {10.1219f,14.2857f},
+ {19.6457f,4.7619f},
+ {29.1695f,0.0f},
+ {43.4552f,0.0f},
+ {52.979f,4.7619f},
+ {62.5029f,14.2857f}
+};
+
+static const SFG_StrokeStrip ch103st[] =
+{
+ {7,ch103st0},
+ {14,ch103st1}
+};
+
+static const SFG_StrokeChar ch103 = {70.9829f,2,ch103st};
+
+/* char: 0x68 */
+
+static const SFG_StrokeVertex ch104st0[] =
+{
+ {9.6f,100.0f},
+ {9.6f,0.0f}
+};
+
+static const SFG_StrokeVertex ch104st1[] =
+{
+ {9.6f,47.619f},
+ {23.8857f,61.9048f},
+ {33.4095f,66.6667f},
+ {47.6952f,66.6667f},
+ {57.219f,61.9048f},
+ {61.981f,47.619f},
+ {61.981f,0.0f}
+};
+
+static const SFG_StrokeStrip ch104st[] =
+{
+ {2,ch104st0},
+ {7,ch104st1}
+};
+
+static const SFG_StrokeChar ch104 = {71.021f,2,ch104st};
+
+/* char: 0x69 */
+
+static const SFG_StrokeVertex ch105st0[] =
+{
+ {10.02f,100.0f},
+ {14.7819f,95.2381f},
+ {19.5438f,100.0f},
+ {14.7819f,104.762f},
+ {10.02f,100.0f}
+};
+
+static const SFG_StrokeVertex ch105st1[] =
+{
+ {14.7819f,66.6667f},
+ {14.7819f,0.0f}
+};
+
+static const SFG_StrokeStrip ch105st[] =
+{
+ {5,ch105st0},
+ {2,ch105st1}
+};
+
+static const SFG_StrokeChar ch105 = {28.8638f,2,ch105st};
+
+/* char: 0x6a */
+
+static const SFG_StrokeVertex ch106st0[] =
+{
+ {17.3876f,100.0f},
+ {22.1495f,95.2381f},
+ {26.9114f,100.0f},
+ {22.1495f,104.762f},
+ {17.3876f,100.0f}
+};
+
+static const SFG_StrokeVertex ch106st1[] =
+{
+ {22.1495f,66.6667f},
+ {22.1495f,-14.2857f},
+ {17.3876f,-28.5714f},
+ {7.8638f,-33.3333f},
+ {-1.66f,-33.3333f}
+};
+
+static const SFG_StrokeStrip ch106st[] =
+{
+ {5,ch106st0},
+ {5,ch106st1}
+};
+
+static const SFG_StrokeChar ch106 = {36.2314f,2,ch106st};
+
+/* char: 0x6b */
+
+static const SFG_StrokeVertex ch107st0[] =
+{
+ {9.6f,100.0f},
+ {9.6f,0.0f}
+};
+
+static const SFG_StrokeVertex ch107st1[] =
+{
+ {57.219f,66.6667f},
+ {9.6f,19.0476f}
+};
+
+static const SFG_StrokeVertex ch107st2[] =
+{
+ {28.6476f,38.0952f},
+ {61.981f,0.0f}
+};
+
+static const SFG_StrokeStrip ch107st[] =
+{
+ {2,ch107st0},
+ {2,ch107st1},
+ {2,ch107st2}
+};
+
+static const SFG_StrokeChar ch107 = {62.521f,3,ch107st};
+
+/* char: 0x6c */
+
+static const SFG_StrokeVertex ch108st0[] =
+{
+ {10.02f,100.0f},
+ {10.02f,0.0f}
+};
+
+static const SFG_StrokeStrip ch108st[] =
+{
+ {2,ch108st0}
+};
+
+static const SFG_StrokeChar ch108 = {19.34f,1,ch108st};
+
+/* char: 0x6d */
+
+static const SFG_StrokeVertex ch109st0[] =
+{
+ {9.6f,66.6667f},
+ {9.6f,0.0f}
+};
+
+static const SFG_StrokeVertex ch109st1[] =
+{
+ {9.6f,47.619f},
+ {23.8857f,61.9048f},
+ {33.4095f,66.6667f},
+ {47.6952f,66.6667f},
+ {57.219f,61.9048f},
+ {61.981f,47.619f},
+ {61.981f,0.0f}
+};
+
+static const SFG_StrokeVertex ch109st2[] =
+{
+ {61.981f,47.619f},
+ {76.2667f,61.9048f},
+ {85.7905f,66.6667f},
+ {100.076f,66.6667f},
+ {109.6f,61.9048f},
+ {114.362f,47.619f},
+ {114.362f,0.0f}
+};
+
+static const SFG_StrokeStrip ch109st[] =
+{
+ {2,ch109st0},
+ {7,ch109st1},
+ {7,ch109st2}
+};
+
+static const SFG_StrokeChar ch109 = {123.962f,3,ch109st};
+
+/* char: 0x6e */
+
+static const SFG_StrokeVertex ch110st0[] =
+{
+ {9.18f,66.6667f},
+ {9.18f,0.0f}
+};
+
+static const SFG_StrokeVertex ch110st1[] =
+{
+ {9.18f,47.619f},
+ {23.4657f,61.9048f},
+ {32.9895f,66.6667f},
+ {47.2752f,66.6667f},
+ {56.799f,61.9048f},
+ {61.561f,47.619f},
+ {61.561f,0.0f}
+};
+
+static const SFG_StrokeStrip ch110st[] =
+{
+ {2,ch110st0},
+ {7,ch110st1}
+};
+
+static const SFG_StrokeChar ch110 = {70.881f,2,ch110st};
+
+/* char: 0x6f */
+
+static const SFG_StrokeVertex ch111st0[] =
+{
+ {28.7895f,66.6667f},
+ {19.2657f,61.9048f},
+ {9.7419f,52.381f},
+ {4.98f,38.0952f},
+ {4.98f,28.5714f},
+ {9.7419f,14.2857f},
+ {19.2657f,4.7619f},
+ {28.7895f,0.0f},
+ {43.0752f,0.0f},
+ {52.599f,4.7619f},
+ {62.1229f,14.2857f},
+ {66.8848f,28.5714f},
+ {66.8848f,38.0952f},
+ {62.1229f,52.381f},
+ {52.599f,61.9048f},
+ {43.0752f,66.6667f},
+ {28.7895f,66.6667f}
+};
+
+static const SFG_StrokeStrip ch111st[] =
+{
+ {17,ch111st0}
+};
+
+static const SFG_StrokeChar ch111 = {71.7448f,1,ch111st};
+
+/* char: 0x70 */
+
+static const SFG_StrokeVertex ch112st0[] =
+{
+ {9.46f,66.6667f},
+ {9.46f,-33.3333f}
+};
+
+static const SFG_StrokeVertex ch112st1[] =
+{
+ {9.46f,52.381f},
+ {18.9838f,61.9048f},
+ {28.5076f,66.6667f},
+ {42.7933f,66.6667f},
+ {52.3171f,61.9048f},
+ {61.841f,52.381f},
+ {66.6029f,38.0952f},
+ {66.6029f,28.5714f},
+ {61.841f,14.2857f},
+ {52.3171f,4.7619f},
+ {42.7933f,0.0f},
+ {28.5076f,0.0f},
+ {18.9838f,4.7619f},
+ {9.46f,14.2857f}
+};
+
+static const SFG_StrokeStrip ch112st[] =
+{
+ {2,ch112st0},
+ {14,ch112st1}
+};
+
+static const SFG_StrokeChar ch112 = {70.8029f,2,ch112st};
+
+/* char: 0x71 */
+
+static const SFG_StrokeVertex ch113st0[] =
+{
+ {61.9829f,66.6667f},
+ {61.9829f,-33.3333f}
+};
+
+static const SFG_StrokeVertex ch113st1[] =
+{
+ {61.9829f,52.381f},
+ {52.459f,61.9048f},
+ {42.9352f,66.6667f},
+ {28.6495f,66.6667f},
+ {19.1257f,61.9048f},
+ {9.6019f,52.381f},
+ {4.84f,38.0952f},
+ {4.84f,28.5714f},
+ {9.6019f,14.2857f},
+ {19.1257f,4.7619f},
+ {28.6495f,0.0f},
+ {42.9352f,0.0f},
+ {52.459f,4.7619f},
+ {61.9829f,14.2857f}
+};
+
+static const SFG_StrokeStrip ch113st[] =
+{
+ {2,ch113st0},
+ {14,ch113st1}
+};
+
+static const SFG_StrokeChar ch113 = {70.7429f,2,ch113st};
+
+/* char: 0x72 */
+
+static const SFG_StrokeVertex ch114st0[] =
+{
+ {9.46f,66.6667f},
+ {9.46f,0.0f}
+};
+
+static const SFG_StrokeVertex ch114st1[] =
+{
+ {9.46f,38.0952f},
+ {14.2219f,52.381f},
+ {23.7457f,61.9048f},
+ {33.2695f,66.6667f},
+ {47.5552f,66.6667f}
+};
+
+static const SFG_StrokeStrip ch114st[] =
+{
+ {2,ch114st0},
+ {5,ch114st1}
+};
+
+static const SFG_StrokeChar ch114 = {49.4952f,2,ch114st};
+
+/* char: 0x73 */
+
+static const SFG_StrokeVertex ch115st0[] =
+{
+ {57.081f,52.381f},
+ {52.319f,61.9048f},
+ {38.0333f,66.6667f},
+ {23.7476f,66.6667f},
+ {9.4619f,61.9048f},
+ {4.7f,52.381f},
+ {9.4619f,42.8571f},
+ {18.9857f,38.0952f},
+ {42.7952f,33.3333f},
+ {52.319f,28.5714f},
+ {57.081f,19.0476f},
+ {57.081f,14.2857f},
+ {52.319f,4.7619f},
+ {38.0333f,0.0f},
+ {23.7476f,0.0f},
+ {9.4619f,4.7619f},
+ {4.7f,14.2857f}
+};
+
+static const SFG_StrokeStrip ch115st[] =
+{
+ {17,ch115st0}
+};
+
+static const SFG_StrokeChar ch115 = {62.321f,1,ch115st};
+
+/* char: 0x74 */
+
+static const SFG_StrokeVertex ch116st0[] =
+{
+ {14.8257f,100.0f},
+ {14.8257f,19.0476f},
+ {19.5876f,4.7619f},
+ {29.1114f,0.0f},
+ {38.6352f,0.0f}
+};
+
+static const SFG_StrokeVertex ch116st1[] =
+{
+ {0.54f,66.6667f},
+ {33.8733f,66.6667f}
+};
+
+static const SFG_StrokeStrip ch116st[] =
+{
+ {5,ch116st0},
+ {2,ch116st1}
+};
+
+static const SFG_StrokeChar ch116 = {39.3152f,2,ch116st};
+
+/* char: 0x75 */
+
+static const SFG_StrokeVertex ch117st0[] =
+{
+ {9.46f,66.6667f},
+ {9.46f,19.0476f},
+ {14.2219f,4.7619f},
+ {23.7457f,0.0f},
+ {38.0314f,0.0f},
+ {47.5552f,4.7619f},
+ {61.841f,19.0476f}
+};
+
+static const SFG_StrokeVertex ch117st1[] =
+{
+ {61.841f,66.6667f},
+ {61.841f,0.0f}
+};
+
+static const SFG_StrokeStrip ch117st[] =
+{
+ {7,ch117st0},
+ {2,ch117st1}
+};
+
+static const SFG_StrokeChar ch117 = {71.161f,2,ch117st};
+
+/* char: 0x76 */
+
+static const SFG_StrokeVertex ch118st0[] =
+{
+ {1.8f,66.6667f},
+ {30.3714f,0.0f}
+};
+
+static const SFG_StrokeVertex ch118st1[] =
+{
+ {58.9429f,66.6667f},
+ {30.3714f,0.0f}
+};
+
+static const SFG_StrokeStrip ch118st[] =
+{
+ {2,ch118st0},
+ {2,ch118st1}
+};
+
+static const SFG_StrokeChar ch118 = {60.6029f,2,ch118st};
+
+/* char: 0x77 */
+
+static const SFG_StrokeVertex ch119st0[] =
+{
+ {2.5f,66.6667f},
+ {21.5476f,0.0f}
+};
+
+static const SFG_StrokeVertex ch119st1[] =
+{
+ {40.5952f,66.6667f},
+ {21.5476f,0.0f}
+};
+
+static const SFG_StrokeVertex ch119st2[] =
+{
+ {40.5952f,66.6667f},
+ {59.6429f,0.0f}
+};
+
+static const SFG_StrokeVertex ch119st3[] =
+{
+ {78.6905f,66.6667f},
+ {59.6429f,0.0f}
+};
+
+static const SFG_StrokeStrip ch119st[] =
+{
+ {2,ch119st0},
+ {2,ch119st1},
+ {2,ch119st2},
+ {2,ch119st3}
+};
+
+static const SFG_StrokeChar ch119 = {80.4905f,4,ch119st};
+
+/* char: 0x78 */
+
+static const SFG_StrokeVertex ch120st0[] =
+{
+ {1.66f,66.6667f},
+ {54.041f,0.0f}
+};
+
+static const SFG_StrokeVertex ch120st1[] =
+{
+ {54.041f,66.6667f},
+ {1.66f,0.0f}
+};
+
+static const SFG_StrokeStrip ch120st[] =
+{
+ {2,ch120st0},
+ {2,ch120st1}
+};
+
+static const SFG_StrokeChar ch120 = {56.401f,2,ch120st};
+
+/* char: 0x79 */
+
+static const SFG_StrokeVertex ch121st0[] =
+{
+ {6.5619f,66.6667f},
+ {35.1333f,0.0f}
+};
+
+static const SFG_StrokeVertex ch121st1[] =
+{
+ {63.7048f,66.6667f},
+ {35.1333f,0.0f},
+ {25.6095f,-19.0476f},
+ {16.0857f,-28.5714f},
+ {6.5619f,-33.3333f},
+ {1.8f,-33.3333f}
+};
+
+static const SFG_StrokeStrip ch121st[] =
+{
+ {2,ch121st0},
+ {6,ch121st1}
+};
+
+static const SFG_StrokeChar ch121 = {66.0648f,2,ch121st};
+
+/* char: 0x7a */
+
+static const SFG_StrokeVertex ch122st0[] =
+{
+ {56.821f,66.6667f},
+ {4.44f,0.0f}
+};
+
+static const SFG_StrokeVertex ch122st1[] =
+{
+ {4.44f,66.6667f},
+ {56.821f,66.6667f}
+};
+
+static const SFG_StrokeVertex ch122st2[] =
+{
+ {4.44f,0.0f},
+ {56.821f,0.0f}
+};
+
+static const SFG_StrokeStrip ch122st[] =
+{
+ {2,ch122st0},
+ {2,ch122st1},
+ {2,ch122st2}
+};
+
+static const SFG_StrokeChar ch122 = {61.821f,3,ch122st};
+
+/* char: 0x7b */
+
+static const SFG_StrokeVertex ch123st0[] =
+{
+ {31.1895f,119.048f},
+ {21.6657f,114.286f},
+ {16.9038f,109.524f},
+ {12.1419f,100.0f},
+ {12.1419f,90.4762f},
+ {16.9038f,80.9524f},
+ {21.6657f,76.1905f},
+ {26.4276f,66.6667f},
+ {26.4276f,57.1429f},
+ {16.9038f,47.619f}
+};
+
+static const SFG_StrokeVertex ch123st1[] =
+{
+ {21.6657f,114.286f},
+ {16.9038f,104.762f},
+ {16.9038f,95.2381f},
+ {21.6657f,85.7143f},
+ {26.4276f,80.9524f},
+ {31.1895f,71.4286f},
+ {31.1895f,61.9048f},
+ {26.4276f,52.381f},
+ {7.38f,42.8571f},
+ {26.4276f,33.3333f},
+ {31.1895f,23.8095f},
+ {31.1895f,14.2857f},
+ {26.4276f,4.7619f},
+ {21.6657f,0.0f},
+ {16.9038f,-9.5238f},
+ {16.9038f,-19.0476f},
+ {21.6657f,-28.5714f}
+};
+
+static const SFG_StrokeVertex ch123st2[] =
+{
+ {16.9038f,38.0952f},
+ {26.4276f,28.5714f},
+ {26.4276f,19.0476f},
+ {21.6657f,9.5238f},
+ {16.9038f,4.7619f},
+ {12.1419f,-4.7619f},
+ {12.1419f,-14.2857f},
+ {16.9038f,-23.8095f},
+ {21.6657f,-28.5714f},
+ {31.1895f,-33.3333f}
+};
+
+static const SFG_StrokeStrip ch123st[] =
+{
+ {10,ch123st0},
+ {17,ch123st1},
+ {10,ch123st2}
+};
+
+static const SFG_StrokeChar ch123 = {41.6295f,3,ch123st};
+
+/* char: 0x7c */
+
+static const SFG_StrokeVertex ch124st0[] =
+{
+ {11.54f,119.048f},
+ {11.54f,-33.3333f}
+};
+
+static const SFG_StrokeStrip ch124st[] =
+{
+ {2,ch124st0}
+};
+
+static const SFG_StrokeChar ch124 = {23.78f,1,ch124st};
+
+/* char: 0x7d */
+
+static const SFG_StrokeVertex ch125st0[] =
+{
+ {9.18f,119.048f},
+ {18.7038f,114.286f},
+ {23.4657f,109.524f},
+ {28.2276f,100.0f},
+ {28.2276f,90.4762f},
+ {23.4657f,80.9524f},
+ {18.7038f,76.1905f},
+ {13.9419f,66.6667f},
+ {13.9419f,57.1429f},
+ {23.4657f,47.619f}
+};
+
+static const SFG_StrokeVertex ch125st1[] =
+{
+ {18.7038f,114.286f},
+ {23.4657f,104.762f},
+ {23.4657f,95.2381f},
+ {18.7038f,85.7143f},
+ {13.9419f,80.9524f},
+ {9.18f,71.4286f},
+ {9.18f,61.9048f},
+ {13.9419f,52.381f},
+ {32.9895f,42.8571f},
+ {13.9419f,33.3333f},
+ {9.18f,23.8095f},
+ {9.18f,14.2857f},
+ {13.9419f,4.7619f},
+ {18.7038f,0.0f},
+ {23.4657f,-9.5238f},
+ {23.4657f,-19.0476f},
+ {18.7038f,-28.5714f}
+};
+
+static const SFG_StrokeVertex ch125st2[] =
+{
+ {23.4657f,38.0952f},
+ {13.9419f,28.5714f},
+ {13.9419f,19.0476f},
+ {18.7038f,9.5238f},
+ {23.4657f,4.7619f},
+ {28.2276f,-4.7619f},
+ {28.2276f,-14.2857f},
+ {23.4657f,-23.8095f},
+ {18.7038f,-28.5714f},
+ {9.18f,-33.3333f}
+};
+
+static const SFG_StrokeStrip ch125st[] =
+{
+ {10,ch125st0},
+ {17,ch125st1},
+ {10,ch125st2}
+};
+
+static const SFG_StrokeChar ch125 = {41.4695f,3,ch125st};
+
+/* char: 0x7e */
+
+static const SFG_StrokeVertex ch126st0[] =
+{
+ {2.92f,28.5714f},
+ {2.92f,38.0952f},
+ {7.6819f,52.381f},
+ {17.2057f,57.1429f},
+ {26.7295f,57.1429f},
+ {36.2533f,52.381f},
+ {55.301f,38.0952f},
+ {64.8248f,33.3333f},
+ {74.3486f,33.3333f},
+ {83.8724f,38.0952f},
+ {88.6343f,47.619f}
+};
+
+static const SFG_StrokeVertex ch126st1[] =
+{
+ {2.92f,38.0952f},
+ {7.6819f,47.619f},
+ {17.2057f,52.381f},
+ {26.7295f,52.381f},
+ {36.2533f,47.619f},
+ {55.301f,33.3333f},
+ {64.8248f,28.5714f},
+ {74.3486f,28.5714f},
+ {83.8724f,33.3333f},
+ {88.6343f,47.619f},
+ {88.6343f,57.1429f}
+};
+
+static const SFG_StrokeStrip ch126st[] =
+{
+ {11,ch126st0},
+ {11,ch126st1}
+};
+
+static const SFG_StrokeChar ch126 = {91.2743f,2,ch126st};
+
+/* char: 0x7f */
+
+static const SFG_StrokeVertex ch127st0[] =
+{
+ {52.381f,100.0f},
+ {14.2857f,-33.3333f}
+};
+
+static const SFG_StrokeVertex ch127st1[] =
+{
+ {28.5714f,66.6667f},
+ {14.2857f,61.9048f},
+ {4.7619f,52.381f},
+ {0.0f,38.0952f},
+ {0.0f,23.8095f},
+ {4.7619f,14.2857f},
+ {14.2857f,4.7619f},
+ {28.5714f,0.0f},
+ {38.0952f,0.0f},
+ {52.381f,4.7619f},
+ {61.9048f,14.2857f},
+ {66.6667f,28.5714f},
+ {66.6667f,42.8571f},
+ {61.9048f,52.381f},
+ {52.381f,61.9048f},
+ {38.0952f,66.6667f},
+ {28.5714f,66.6667f}
+};
+
+static const SFG_StrokeStrip ch127st[] =
+{
+ {2,ch127st0},
+ {17,ch127st1}
+};
+
+static const SFG_StrokeChar ch127 = {66.6667f,2,ch127st};
+
+static const SFG_StrokeChar *chars[] =
+{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ &ch32, &ch33, &ch34, &ch35, &ch36, &ch37, &ch38, &ch39,
+ &ch40, &ch41, &ch42, &ch43, &ch44, &ch45, &ch46, &ch47,
+ &ch48, &ch49, &ch50, &ch51, &ch52, &ch53, &ch54, &ch55,
+ &ch56, &ch57, &ch58, &ch59, &ch60, &ch61, &ch62, &ch63,
+ &ch64, &ch65, &ch66, &ch67, &ch68, &ch69, &ch70, &ch71,
+ &ch72, &ch73, &ch74, &ch75, &ch76, &ch77, &ch78, &ch79,
+ &ch80, &ch81, &ch82, &ch83, &ch84, &ch85, &ch86, &ch87,
+ &ch88, &ch89, &ch90, &ch91, &ch92, &ch93, &ch94, &ch95,
+ &ch96, &ch97, &ch98, &ch99, &ch100, &ch101, &ch102,
&ch103,
+ &ch104, &ch105, &ch106, &ch107, &ch108, &ch109, &ch110,
&ch111,
+ &ch112, &ch113, &ch114, &ch115, &ch116, &ch117, &ch118,
&ch119,
+ &ch120, &ch121, &ch122, &ch123, &ch124, &ch125, &ch126,
&ch127
+};
+
+const SFG_StrokeFont fgStrokeRoman = {"Roman",128,152.381f,chars};
Index: external/trimesh/gluit/COPYING.freeglut
--- external/trimesh/gluit/COPYING.freeglut (revision 0)
+++ external/trimesh/gluit/COPYING.freeglut (revision 0)
@@ -0,0 +1,27 @@
+
+ Freeglut Copyright
+ ------------------
+
+ Freeglut code without an explicit copyright is covered by the following
+ copyright:
+
+ Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to
deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies or substantial portions of the Software.
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ Except as contained in this notice, the name of Pawel W. Olszta shall not be
+ used in advertising or otherwise to promote the sale, use or other dealings
+ in this Software without prior written authorization from Pawel W. Olszta.
Index: external/trimesh/gluit/freeglut_font.c
--- external/trimesh/gluit/freeglut_font.c (revision 0)
+++ external/trimesh/gluit/freeglut_font.c (revision 0)
@@ -0,0 +1,368 @@
+/*
+ * freeglut_font.c
+ *
+ * Bitmap and stroke fonts displaying.
+ *
+ * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
+ * Written by Pawel W. Olszta, <olszta(a)sourceforge.net>
+ * Creation date: Thu Dec 16 1999
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <GL/freeglut.h>
+#include "freeglut_internal.h"
+
+/*
+ * TODO BEFORE THE STABLE RELEASE:
+ *
+ * Test things out ...
+ */
+
+/* -- IMPORT DECLARATIONS -------------------------------------------------- */
+
+/*
+ * These are the font faces defined in freeglut_font_data.c file:
+ */
+extern SFG_Font fgFontFixed8x13;
+extern SFG_Font fgFontFixed9x15;
+extern SFG_Font fgFontHelvetica10;
+extern SFG_Font fgFontHelvetica12;
+extern SFG_Font fgFontHelvetica18;
+extern SFG_Font fgFontTimesRoman10;
+extern SFG_Font fgFontTimesRoman24;
+extern SFG_StrokeFont fgStrokeRoman;
+extern SFG_StrokeFont fgStrokeMonoRoman;
+
+
+/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
+
+/*
+ * Matches a font ID with a SFG_Font structure pointer.
+ * This was changed to match the GLUT header style.
+ */
+static SFG_Font* fghFontByID( void* font )
+{
+ if( font == GLUT_BITMAP_8_BY_13 )
+ return &fgFontFixed8x13;
+ if( font == GLUT_BITMAP_9_BY_15 )
+ return &fgFontFixed9x15;
+ if( font == GLUT_BITMAP_HELVETICA_10 )
+ return &fgFontHelvetica10;
+ if( font == GLUT_BITMAP_HELVETICA_12 )
+ return &fgFontHelvetica12;
+ if( font == GLUT_BITMAP_HELVETICA_18 )
+ return &fgFontHelvetica18;
+ if( font == GLUT_BITMAP_TIMES_ROMAN_10 )
+ return &fgFontTimesRoman10;
+ if( font == GLUT_BITMAP_TIMES_ROMAN_24 )
+ return &fgFontTimesRoman24;
+
+ fgError( "font 0x%08x not found", font );
+ return 0; /*** NOT REACHED ***/
+}
+
+/*
+ * Matches a font ID with a SFG_StrokeFont structure pointer.
+ * This was changed to match the GLUT header style.
+ */
+static SFG_StrokeFont* fghStrokeByID( void* font )
+{
+ if( font == GLUT_STROKE_ROMAN )
+ return &fgStrokeRoman;
+ if( font == GLUT_STROKE_MONO_ROMAN )
+ return &fgStrokeMonoRoman;
+
+ fgError( "stroke font 0x%08x not found", font );
+ return 0; /*** NOT REACHED ***/
+}
+
+
+/* -- INTERFACE FUNCTIONS -------------------------------------------------- */
+
+/*
+ * Draw a bitmap character
+ */
+void FGAPIENTRY glutBitmapCharacter( void* fontID, int character )
+{
+ const GLubyte* face;
+ SFG_Font* font = fghFontByID( fontID );
+
+ freeglut_return_if_fail( ( character >= 1 )&&( character < 256 ) );
+
+ /*
+ * Find the character we want to draw (???)
+ */
+ face = font->Characters[ character ];
+
+ glPushClientAttrib( GL_CLIENT_PIXEL_STORE_BIT );
+ glPixelStorei( GL_UNPACK_SWAP_BYTES, GL_FALSE );
+ glPixelStorei( GL_UNPACK_LSB_FIRST, GL_FALSE );
+ glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 );
+ glPixelStorei( GL_UNPACK_SKIP_ROWS, 0 );
+ glPixelStorei( GL_UNPACK_SKIP_PIXELS, 0 );
+ glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
+ glBitmap(
+ face[ 0 ], font->Height, /* The bitmap's width and height */
+ font->xorig, font->yorig, /* The origin in the font glyph */
+ ( float )( face[ 0 ] ), 0.0, /* The raster advance -- inc. x,y */
+ ( face + 1 ) /* The packed bitmap data... */
+ );
+ glPopClientAttrib( );
+}
+
+void FGAPIENTRY glutBitmapString( void* fontID, const unsigned char *string )
+{
+ int c;
+ int numchar = strlen( (char *) string );
+ SFG_Font* font = fghFontByID( fontID );
+ float raster_position[ 4 ];
+
+ glPushAttrib( GL_TRANSFORM_BIT );
+ glMatrixMode( GL_MODELVIEW );
+ glPushMatrix( );
+ glLoadIdentity( );
+ glMatrixMode( GL_PROJECTION );
+ glPushMatrix( );
+ glLoadIdentity( );
+ glOrtho(
+ 0, glutGet( GLUT_WINDOW_WIDTH ),
+ 0, glutGet( GLUT_WINDOW_HEIGHT ),
+ -10, 10
+ );
+
+ glGetFloatv ( GL_CURRENT_RASTER_POSITION, raster_position );
+ glPushClientAttrib( GL_CLIENT_PIXEL_STORE_BIT );
+ glPixelStorei( GL_UNPACK_SWAP_BYTES, GL_FALSE );
+ glPixelStorei( GL_UNPACK_LSB_FIRST, GL_FALSE );
+ glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 );
+ glPixelStorei( GL_UNPACK_SKIP_ROWS, 0 );
+ glPixelStorei( GL_UNPACK_SKIP_PIXELS, 0 );
+ glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
+
+ /*
+ * Step through the string, drawing each character.
+ * A newline will simply translate the next character's insertion
+ * point back to the start of the line and down one line.
+ */
+ for( c = 0; c < numchar; c++ )
+ if( string[c] == '\n' )
+ {
+ raster_position[ 1 ] -= ( float )font->Height;
+ glRasterPos4fv( raster_position );
+ }
+ else /* Not an EOL, draw the bitmap character */
+ {
+ const GLubyte* face = font->Characters[ string[ c ] ];
+
+ glBitmap(
+ face[ 0 ], font->Height, /* Bitmap's width and height */
+ font->xorig, font->yorig, /* The origin in the font glyph */
+ ( float )( face[ 0 ] ), 0.0, /* The raster advance; inc. x,y */
+ ( face + 1 ) /* The packed bitmap data... */
+ );
+ }
+
+ glPopClientAttrib( );
+ glPopMatrix( );
+ glMatrixMode( GL_MODELVIEW );
+ glPopMatrix( );
+ glPopAttrib( );
+}
+
+/*
+ * Returns the width in pixels of a font's character
+ */
+int FGAPIENTRY glutBitmapWidth( void* fontID, int character )
+{
+ SFG_Font* font = fghFontByID( fontID );
+
+ freeglut_return_val_if_fail( character > 0 && character < 256, 0 );
+ return *( font->Characters[ character ] );
+}
+
+/*
+ * Return the width of a string drawn using a bitmap font
+ */
+int FGAPIENTRY glutBitmapLength( void* fontID, const unsigned char* string )
+{
+ int c, length = 0, this_line_length = 0;
+ SFG_Font* font = fghFontByID( fontID );
+ int numchar = strlen( (char *) string );
+
+ for( c = 0; c < numchar; c++ )
+ {
+ if( string[ c ] != '\n' )/* Not an EOL, increment length of line */
+ this_line_length += *( font->Characters[ string[ c ] ]);
+ else /* EOL; reset the length of this line */
+ {
+ if( length < this_line_length )
+ length = this_line_length;
+ this_line_length = 0;
+ }
+ }
+ if ( length < this_line_length )
+ length = this_line_length;
+
+ return length;
+}
+
+/*
+ * Returns the height of a bitmap font
+ */
+int FGAPIENTRY glutBitmapHeight( void* fontID )
+{
+ SFG_Font* font = fghFontByID( fontID );
+ return font->Height;
+}
+
+/*
+ * Draw a stroke character
+ */
+void FGAPIENTRY glutStrokeCharacter( void* fontID, int character )
+{
+ const SFG_StrokeChar *schar;
+ const SFG_StrokeStrip *strip;
+ int i, j;
+ SFG_StrokeFont* font = fghStrokeByID( fontID );
+
+ freeglut_return_if_fail( character >= 0 );
+ freeglut_return_if_fail( character < font->Quantity );
+
+ schar = font->Characters[ character ];
+ freeglut_return_if_fail( schar );
+ strip = schar->Strips;
+
+ for( i = 0; i < schar->Number; i++, strip++ )
+ {
+ glBegin( GL_LINE_STRIP );
+ for( j = 0; j < strip->Number; j++ )
+ glVertex2f( strip->Vertices[ j ].X, strip->Vertices[ j ].Y );
+ glEnd( );
+ }
+ glTranslatef( schar->Right, 0.0, 0.0 );
+}
+
+void FGAPIENTRY glutStrokeString( void* fontID, const unsigned char *string )
+{
+ int c, i, j;
+ int numchar = strlen( (char *) string );
+ float length = 0.0;
+ SFG_StrokeFont* font = fghStrokeByID( fontID );
+
+ /*
+ * Step through the string, drawing each character.
+ * A newline will simply translate the next character's insertion
+ * point back to the start of the line and down one line.
+ */
+ for( c = 0; c < numchar; c++ )
+ if( string[ c ] < font->Quantity )
+ {
+ if( string[ c ] == '\n' )
+ {
+ glTranslatef ( -length, -( float )( font->Height ), 0.0 );
+ length = 0.0;
+ }
+ else /* Not an EOL, draw the bitmap character */
+ {
+ const SFG_StrokeChar *schar = font->Characters[ string[ c ] ];
+ if( schar )
+ {
+ const SFG_StrokeStrip *strip = schar->Strips;
+
+ for( i = 0; i < schar->Number; i++, strip++ )
+ {
+ glBegin( GL_LINE_STRIP );
+ for( j = 0; j < strip->Number; j++ )
+ glVertex2f( strip->Vertices[ j ].X,
+ strip->Vertices[ j ].Y);
+
+ glEnd( );
+ }
+
+ length += schar->Right;
+ glTranslatef( schar->Right, 0.0, 0.0 );
+ }
+ }
+ }
+}
+
+/*
+ * Return the width in pixels of a stroke character
+ */
+int FGAPIENTRY glutStrokeWidth( void* fontID, int character )
+{
+ const SFG_StrokeChar *schar;
+ SFG_StrokeFont* font = fghStrokeByID( fontID );
+
+ freeglut_return_val_if_fail( ( character >= 0 ) &&
+ ( character < font->Quantity ),
+ 0
+ );
+ schar = font->Characters[ character ];
+ freeglut_return_val_if_fail( schar, 0 );
+
+ return ( int )( schar->Right + 0.5 );
+}
+
+/*
+ * Return the width of a string drawn using a stroke font
+ */
+int FGAPIENTRY glutStrokeLength( void* fontID, const unsigned char* string )
+{
+ int c;
+ float length = 0.0;
+ float this_line_length = 0.0;
+ SFG_StrokeFont* font = fghStrokeByID( fontID );
+ int numchar = strlen( (char *) string );
+
+ for( c = 0; c < numchar; c++ )
+ if( string[ c ] < font->Quantity )
+ {
+ if( string[ c ] == '\n' ) /* EOL; reset the length of this line */
+ {
+ if( length < this_line_length )
+ length = this_line_length;
+ this_line_length = 0.0;
+ }
+ else /* Not an EOL, increment the length of this line */
+ {
+ const SFG_StrokeChar *schar = font->Characters[ string[ c ] ];
+ if( schar )
+ this_line_length += schar->Right;
+ }
+ }
+ if( length < this_line_length )
+ length = this_line_length;
+ return( int )( length + 0.5 );
+}
+
+/*
+ * Returns the height of a stroke font
+ */
+GLfloat FGAPIENTRY glutStrokeHeight( void* fontID )
+{
+ SFG_StrokeFont* font = fghStrokeByID( fontID );
+ return font->Height;
+}
+
+/*** END OF FILE ***/
Index: external/trimesh/gluit/glui_img_rightarrow.c
--- external/trimesh/gluit/glui_img_rightarrow.c (revision 0)
+++ external/trimesh/gluit/glui_img_rightarrow.c (revision 0)
@@ -0,0 +1,56 @@
+
+
+int glui_img_rightarrow[] = { 16, 16, /* width, height */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 192,192,192, 128,128,128, 128,128,128, 128,128,128,
+ 128,128,128, 128,128,128, 128,128,128, 128,128,128, 128,128,128,
+ 128,128,128, 128,128,128, 128,128,128, 128,128,128, 128,128,128,
+ 128,128,128, 0, 0, 0, 192,192,192, 255,255,255, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 128,128,128, 0, 0, 0, 192,192,192, 255,255,255,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 128,128,128, 0, 0, 0, 192,192,192,
+ 255,255,255, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 128,128,128, 0, 0, 0,
+ 192,192,192, 255,255,255, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 0, 0, 0, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 128,128,128,
+ 0, 0, 0, 192,192,192, 255,255,255, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 0, 0, 0, 0, 0, 0, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 128,128,128, 0, 0, 0, 192,192,192, 255,255,255, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 128,128,128, 0, 0, 0, 192,192,192, 255,255,255,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 128,128,128, 0, 0, 0, 192,192,192,
+ 255,255,255, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 128,128,128, 0, 0, 0,
+ 192,192,192, 255,255,255, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 0, 0, 0, 0, 0, 0, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 128,128,128,
+ 0, 0, 0, 192,192,192, 255,255,255, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 0, 0, 0, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 128,128,128, 0, 0, 0, 192,192,192, 255,255,255, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 128,128,128, 0, 0, 0, 192,192,192, 255,255,255,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 128,128,128, 0, 0, 0, 192,192,192,
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 128,128,128, 0, 0, 0,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 0, 0, 0,
+};
Index: external/trimesh/gluit/glui_stdinc.h
--- external/trimesh/gluit/glui_stdinc.h (revision 0)
+++ external/trimesh/gluit/glui_stdinc.h (revision 0)
@@ -0,0 +1,131 @@
+#ifndef _STDINC_H_
+#define _STDINC_H_
+
+#include <stdio.h>
+#include <math.h>
+
+#ifndef AND
+#define AND &&
+#define OR ||
+#define NOT !
+#endif
+
+#ifndef true
+#define true 1
+#define false 0
+#endif
+
+#ifndef Bool
+typedef char Bool;
+#endif
+
+#ifndef MAX
+#define MAX(a,b) ((a)>(b) ? (a) : (b))
+#define MIN(a,b) ((a)<(b) ? (a) : (b))
+#endif
+
+#ifndef ABS
+#define ABS(a) ((a)>=0 ? (a) : (-(a)))
+#endif
+
+/********* TOGGLE_BOOL(boolean) : toggles values of 'boolean' ******/
+#ifndef TOGGLE_BOOL
+#define TOGGLE_BOOL(a) ((a)=1-(a))
+#endif
+
+
+/******************** bit comparisons and operations ***************/
+#ifndef TEST_BIT
+#define TEST_BIT( x, b ) (((x) & (1<<(b))) != 0 )
+#define SET_BIT( x, b ) ((x) |= (1 << (b)))
+#define CLEAR_BIT( x, b ) ((x) &= ~(1 << (b)))
+#define TOGGLE_BIT( x, b ) ((TEST_BIT(x,b)) ?(CLEAR_BIT(x,b)):(SET_BIT(x,b)))
+#endif
+
+#ifndef TEST_AND
+#define TEST_AND( a, b ) ((a&b)==b)
+#endif
+
+
+#ifndef M_PI
+#define M_PI 3.141592654
+#endif
+
+typedef char String[81];
+
+
+/*********** flush the stdout and stderr output streams *************/
+#ifndef flushout
+#define flushout fflush(stdout)
+#define flusherr fflush(stderr)
+#endif
+
+
+/********** Debugging functions *************************************/
+#ifndef error_return
+#define error_return( c ); {fprintf(stderr,c);return;}
+#endif
+
+
+/************************* floating-point random ********************/
+#ifndef randf
+#define randf() ((float) rand() / (float)RAND_MAX )
+#endif
+
+#ifndef SIGN
+#define SIGN(x) ((x)>=0 ? 1 : -1)
+#endif
+
+
+/****************** conversion between degrees and radians **********/
+#ifndef DEG2RAD
+#define DEG2RAD(x) ((x)/180.0*M_PI)
+#define RAD2DEG(x) ((x)/M_PI*180.0)
+#endif
+
+
+/***************** clamp a value to some fixed interval *************/
+#ifndef CLAMP
+#define CLAMP(x,lo,hi) {if ((x) < (lo)) {(x)=(lo);} else if((x) > (hi))
{(x)=(hi);}}
+#endif
+
+
+
+/************ check if a value lies within a closed interval *********/
+#ifndef IN_BOUNDS
+#define IN_BOUNDS( x, lo, hi ) ( (x) >= (lo) AND (x) <= (hi) )
+#endif
+
+
+/************ check if a 2D point lies within a 2D box ***************/
+#ifndef PT_IN_BOX
+#define PT_IN_BOX( x, y, lo_x, hi_x, lo_y, hi_y ) \
+( IN_BOUNDS(x,lo_x,hi_x) AND IN_BOUNDS(y,lo_y,hi_y) )
+#endif
+
+ /****** check if value lies on proper side of another value *****/
+ /*** if side is positive => proper side is positive, else negative **/
+#ifndef CHECK_PROPER_SIDE
+#define CHECK_PROPER_SIDE(x,val,side) ((side) > 0 ? (x) > (val) : (x) < (val))
+#endif
+
+
+ /***** Small value when we want to do a comparison to 'close to zero'
*****/
+#ifndef FUDGE
+#define FUDGE .00001
+#endif
+
+
+ /******************* swap two values, using a temp variable *********/
+#ifndef SWAP2
+#define SWAP2(a,b,t) {t=a;a=b;b=t;}
+#endif
+
+#define VEC3_TO_ARRAY(v,a) a[0]=v[0], a[1]=v[1], a[2]=v[2]
+
+#endif /* _STDINC_H_ */
+
+
+
+
+
Index: external/trimesh/gluit/glui_checkbox.cc
--- external/trimesh/gluit/glui_checkbox.cc (revision 0)
+++ external/trimesh/gluit/glui_checkbox.cc (revision 0)
@@ -0,0 +1,313 @@
+/****************************************************************************
+
+ GLUI User Interface Toolkit
+ ---------------------------
+
+ glui_checkbox - GLUI_Checkbox control class
+
+
+ --------------------------------------------------
+
+ Copyright (c) 1998 Paul Rademacher
+
+ This program is freely distributable without licensing fees and is
+ provided without guarantee or warrantee expressed or implied. This
+ program is -not- in the public domain.
+
+*****************************************************************************/
+
+#include "glui.h"
+#include "glui_stdinc.h"
+
+/****************************** GLUI_Checkbox::mouse_down_handler() **********/
+
+int GLUI_Checkbox::mouse_down_handler( int local_x, int local_y )
+{
+ orig_value = int_val;
+
+ TOGGLE_BOOL( int_val );
+
+ currently_inside = true;
+
+ if ( int_val )
+ draw_checked();
+ else
+ draw_unchecked();
+
+ return false;
+}
+
+
+/****************************** GLUI_Checkbox::mouse_up_handler() **********/
+
+int GLUI_Checkbox::mouse_up_handler( int local_x, int local_y, int inside )
+{
+ if ( NOT inside ) {
+ int_val = orig_value;
+ }
+ else {
+ set_int_val( int_val );
+
+ /*** Invoke the callback ***/
+ execute_callback();
+ }
+
+ if ( int_val )
+ draw_checked();
+ else
+ draw_unchecked();
+
+ return false;
+}
+
+
+/****************************** GLUI_Checkbox::mouse_held_down_handler() ******/
+
+int GLUI_Checkbox::mouse_held_down_handler( int local_x, int local_y,
+ int inside)
+{
+ /********** Toggle checked and unchecked bitmap if we're entering or
+ leaving the checkbox area **********/
+
+ /** oops, this was wrong!
+ if ( NOT inside AND currently_inside == true )
+ draw_unchecked();
+ else if ( inside AND currently_inside == false )
+ draw_checked();*/
+
+ if ( inside != currently_inside )
+ TOGGLE_BOOL( int_val );
+
+ currently_inside = inside;
+
+ if ( int_val )
+ draw_checked();
+ else
+ draw_unchecked();
+
+ return false;
+}
+
+
+/****************************** GLUI_Checkbox::key_handler() **********/
+
+int GLUI_Checkbox::key_handler( unsigned char key,int modifiers )
+{
+ return false;
+}
+
+
+/****************************** GLUI_Checkbox::draw() **********/
+
+void GLUI_Checkbox::draw( int x, int y )
+{
+ int orig;
+
+ if ( NOT can_draw() )
+ return;
+
+ orig = set_to_glut_window();
+
+ if ( int_val != 0 ) {
+ if ( enabled )
+ glui->std_bitmaps.draw( GLUI_STDBITMAP_CHECKBOX_ON, 0, 0 );
+ else
+ glui->std_bitmaps.draw( GLUI_STDBITMAP_CHECKBOX_ON_DIS, 0, 0 );
+ }
+ else {
+ if ( enabled )
+ glui->std_bitmaps.draw( GLUI_STDBITMAP_CHECKBOX_OFF, 0, 0 );
+ else
+ glui->std_bitmaps.draw( GLUI_STDBITMAP_CHECKBOX_OFF_DIS, 0, 0 );
+ }
+
+ draw_active_area();
+
+ draw_name( text_x_offset, 10);
+
+ restore_window(orig);
+}
+
+
+/************************************** GLUI_Checkbox::draw_checked() ******/
+
+void GLUI_Checkbox::draw_checked( void )
+{
+ int state, orig;
+
+ if ( NOT can_draw() )
+ return;
+
+ orig = set_to_glut_window();
+ state = glui->set_front_draw_buffer();
+
+ glColor3f( 0.0, 0.0, 0.0 );
+ glPushMatrix();
+ translate_to_origin();
+ if ( enabled )
+ glui->std_bitmaps.draw( GLUI_STDBITMAP_CHECKBOX_ON, 0, 0 );
+ else
+ glui->std_bitmaps.draw( GLUI_STDBITMAP_CHECKBOX_ON_DIS, 0, 0 );
+ draw_active_area();
+ glPopMatrix();
+
+ glui->restore_draw_buffer(state);
+ restore_window(orig);
+}
+
+
+/************************************** GLUI_Checkbox::draw_unchecked() ******/
+
+void GLUI_Checkbox::draw_unchecked( void )
+{
+ int state, orig;
+
+ if ( NOT can_draw() )
+ return;
+
+ orig = set_to_glut_window();
+ state = glui->set_front_draw_buffer();
+
+ glColor3f( 1.0, 1.0, 1.0 );
+ glPushMatrix();
+ translate_to_origin();
+ if ( enabled )
+ glui->std_bitmaps.draw( GLUI_STDBITMAP_CHECKBOX_OFF, 0, 0 );
+ else
+ glui->std_bitmaps.draw( GLUI_STDBITMAP_CHECKBOX_OFF_DIS, 0, 0 );
+ draw_active_area();
+ glPopMatrix();
+
+ glui->restore_draw_buffer(state);
+ restore_window(orig);
+}
+
+
+/**************************************** GLUI_Checkbox::draw_X() ************/
+
+void GLUI_Checkbox::draw_X( void )
+{
+ int orig;
+
+ orig = set_to_glut_window();
+
+ /* glPointSize( 1.0 );
+ glBegin( GL_POINTS );
+ for( i=2; i<=GLUI_CHECKBOX_SIZE-2; i++ ) {
+ glVertex2i( i,i );
+ glVertex2i( i,GLUI_CHECKBOX_SIZE-i );
+ }
+ glEnd();
+ */
+
+ /* glColor3f( 0.0, 0.0, 0.0 ); */
+
+ /*
+ glBegin( GL_LINES );
+ glVertex2i( 0, 0 );
+ glVertex2i( GLUI_CHECKBOX_SIZE-0, GLUI_CHECKBOX_SIZE-0 );
+ glVertex2i( GLUI_CHECKBOX_SIZE-0, 0 );
+ glVertex2i( 0, GLUI_CHECKBOX_SIZE-0 );
+ glEnd();*/
+
+ restore_window(orig);
+}
+
+
+/********************************** GLUI_Checkbox::draw_empty_box() **********/
+
+void GLUI_Checkbox::draw_empty_box( void )
+{
+ int orig;
+
+ if ( NOT can_draw())
+ return;
+
+ orig = set_to_glut_window();
+
+ glColor3f( 1.0, 1.0, 1.0 );
+ glBegin( GL_QUADS );
+ glVertex2i( 0, 0 );
+ glVertex2i( GLUI_CHECKBOX_SIZE, 0 );
+ glVertex2i( GLUI_CHECKBOX_SIZE, GLUI_CHECKBOX_SIZE );
+ glVertex2i( 0, GLUI_CHECKBOX_SIZE );
+ glEnd();
+
+ glColor3f( 0.0, 0.0, 0.0 );
+ glBegin( GL_LINE_LOOP );
+ glVertex2i( 0, 0 );
+ glVertex2i( GLUI_CHECKBOX_SIZE, 0 );
+ glVertex2i( GLUI_CHECKBOX_SIZE, GLUI_CHECKBOX_SIZE );
+ glVertex2i( 0, GLUI_CHECKBOX_SIZE );
+ glEnd();
+
+ restore_window(orig);
+}
+
+
+/************************************ GLUI_Checkbox::update_size() **********/
+
+void GLUI_Checkbox::update_size( void )
+{
+ int text_size;
+
+ if ( NOT glui )
+ return;
+
+ text_size = _glutBitmapWidthString( glui->font, name );
+
+ /* if ( w < text_x_offset + text_size + 6 ) */
+ w = text_x_offset + text_size + 6 ;
+}
+
+
+/**************************** GLUI_Checkbox::draw_active_area() **************/
+
+void GLUI_Checkbox::draw_active_area( void )
+{
+ int text_width, left, right, orig;
+
+ if ( NOT can_draw())
+ return;
+
+ orig = set_to_glut_window();
+
+ text_width = _glutBitmapWidthString( glui->font, name );
+ left = text_x_offset-3;
+ right = left + 7 + text_width;
+
+ if ( active ) {
+ glEnable( GL_LINE_STIPPLE );
+ glLineStipple( 1, 0x5555 );
+ glColor3f( 0., 0., 0. );
+ } else {
+ glColor3ub( glui->bkgd_color.r, glui->bkgd_color.g, glui->bkgd_color.b );
+ }
+
+ glBegin( GL_LINE_LOOP );
+ glVertex2i(left,0); glVertex2i( right,0);
+ glVertex2i(right,h+1); glVertex2i( left,h+1);
+ glEnd();
+
+ glDisable( GL_LINE_STIPPLE );
+
+ restore_window(orig);
+}
+
+
+/********************************* GLUI_Checkbox::set_int_val() **************/
+
+void GLUI_Checkbox::set_int_val( int new_val )
+{
+ int_val = new_val;
+
+ /*** Update the variable we're (possibly) pointing to ***/
+ output_live(true);
+
+ if ( can_draw() ) {
+ if ( int_val )
+ draw_checked();
+ else
+ draw_unchecked();
+ }
+}
Index: external/trimesh/gluit/freeglut_state.c
--- external/trimesh/gluit/freeglut_state.c (revision 0)
+++ external/trimesh/gluit/freeglut_state.c (revision 0)
@@ -0,0 +1,694 @@
+/*
+ * freeglut_state.c
+ *
+ * Freeglut state query methods.
+ *
+ * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
+ * Written by Pawel W. Olszta, <olszta(a)sourceforge.net>
+ * Creation date: Thu Dec 16 1999
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <GL/freeglut.h>
+#include "freeglut_internal.h"
+
+/*
+ * TODO BEFORE THE STABLE RELEASE:
+ *
+ * glutGet() -- X11 tests passed, but check if all enums
+ * handled (what about Win32?)
+ * glutDeviceGet() -- X11 tests passed, but check if all enums
+ * handled (what about Win32?)
+ * glutGetModifiers() -- OK, but could also remove the limitation
+ * glutLayerGet() -- what about GLUT_NORMAL_DAMAGED?
+ *
+ * The fail-on-call policy will help adding the most needed things imho.
+ */
+
+/* -- LOCAL DEFINITIONS ---------------------------------------------------- */
+
+/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
+
+#if TARGET_HOST_UNIX_X11
+/*
+ * Queries the GL context about some attributes
+ */
+static int fghGetConfig( int attribute )
+{
+ int returnValue = 0;
+
+ if( fgStructure.Window )
+ glXGetConfig( fgDisplay.Display, fgStructure.Window->Window.VisualInfo,
+ attribute, &returnValue );
+
+ return returnValue;
+}
+#endif
+
+/* -- INTERFACE FUNCTIONS -------------------------------------------------- */
+
+/*
+ * General settings assignment method
+ */
+void FGAPIENTRY glutSetOption( GLenum eWhat, int value )
+{
+ freeglut_assert_ready;
+
+ /*
+ * XXX In chronological code add order. (WHY in that order?)
+ */
+ switch( eWhat )
+ {
+ case GLUT_INIT_WINDOW_X:
+ fgState.Position.X = (GLint)value;
+ break;
+
+ case GLUT_INIT_WINDOW_Y:
+ fgState.Position.Y = (GLint)value;
+ break;
+
+ case GLUT_INIT_WINDOW_WIDTH:
+ fgState.Size.X = (GLint)value;
+ break;
+
+ case GLUT_INIT_WINDOW_HEIGHT:
+ fgState.Size.Y = (GLint)value;
+ break;
+
+ case GLUT_INIT_DISPLAY_MODE:
+ fgState.DisplayMode = (unsigned int)value;
+ break;
+
+ case GLUT_ACTION_ON_WINDOW_CLOSE:
+ fgState.ActionOnWindowClose = value;
+ break;
+
+ case GLUT_RENDERING_CONTEXT:
+ fgState.UseCurrentContext =
+ ( value == GLUT_USE_CURRENT_CONTEXT ) ? GL_TRUE : GL_FALSE;
+ break;
+
+ case GLUT_DIRECT_RENDERING:
+ fgState.DirectContext = value;
+ break;
+
+ case GLUT_WINDOW_CURSOR:
+ if( fgStructure.Window != NULL )
+ fgStructure.Window->State.Cursor = value;
+ break;
+
+ default:
+ fgWarning( "glutSetOption(): missing enum handle %i\n", eWhat );
+ break;
+ }
+}
+
+/*
+ * General settings query method
+ */
+int FGAPIENTRY glutGet( GLenum eWhat )
+{
+#if TARGET_HOST_WIN32 || TARGET_HOST_WINCE
+ int returnValue ;
+ GLboolean boolValue ;
+#endif
+
+ switch (eWhat)
+ {
+ case GLUT_INIT_STATE:
+ return fgState.Initialised;
+
+ case GLUT_ELAPSED_TIME:
+ return fgElapsedTime();
+ }
+
+ freeglut_assert_ready;
+
+ /*
+ * XXX In chronological code add order. (WHY in that order?)
+ */
+ switch( eWhat )
+ {
+ /*
+ * Following values are stored in fgState and fgDisplay global structures
+ */
+ case GLUT_SCREEN_WIDTH: return fgDisplay.ScreenWidth ;
+ case GLUT_SCREEN_HEIGHT: return fgDisplay.ScreenHeight ;
+ case GLUT_SCREEN_WIDTH_MM: return fgDisplay.ScreenWidthMM ;
+ case GLUT_SCREEN_HEIGHT_MM: return fgDisplay.ScreenHeightMM;
+ case GLUT_INIT_WINDOW_X: return fgState.Position.X ;
+ case GLUT_INIT_WINDOW_Y: return fgState.Position.Y ;
+ case GLUT_INIT_WINDOW_WIDTH: return fgState.Size.X ;
+ case GLUT_INIT_WINDOW_HEIGHT: return fgState.Size.Y ;
+ case GLUT_INIT_DISPLAY_MODE: return fgState.DisplayMode ;
+
+ /*
+ * The window/context specific queries are handled mostly by
+ * fghGetConfig().
+ */
+ case GLUT_WINDOW_NUM_SAMPLES:
+ /*
+ * XXX Multisampling. Return what I know about multisampling.
+ */
+ return 0;
+
+#if TARGET_HOST_UNIX_X11
+ /*
+ * The rest of GLX queries under X are general enough to use a macro to
+ * check them
+ */
+# define GLX_QUERY(a,b) case a: return fghGetConfig( b );
+
+ GLX_QUERY( GLUT_WINDOW_RGBA, GLX_RGBA );
+ GLX_QUERY( GLUT_WINDOW_DOUBLEBUFFER, GLX_DOUBLEBUFFER );
+ GLX_QUERY( GLUT_WINDOW_BUFFER_SIZE, GLX_BUFFER_SIZE );
+ GLX_QUERY( GLUT_WINDOW_STENCIL_SIZE, GLX_STENCIL_SIZE );
+ GLX_QUERY( GLUT_WINDOW_DEPTH_SIZE, GLX_DEPTH_SIZE );
+ GLX_QUERY( GLUT_WINDOW_RED_SIZE, GLX_RED_SIZE );
+ GLX_QUERY( GLUT_WINDOW_GREEN_SIZE, GLX_GREEN_SIZE );
+ GLX_QUERY( GLUT_WINDOW_BLUE_SIZE, GLX_BLUE_SIZE );
+ GLX_QUERY( GLUT_WINDOW_ALPHA_SIZE, GLX_ALPHA_SIZE );
+ GLX_QUERY( GLUT_WINDOW_ACCUM_RED_SIZE, GLX_ACCUM_RED_SIZE );
+ GLX_QUERY( GLUT_WINDOW_ACCUM_GREEN_SIZE, GLX_ACCUM_GREEN_SIZE );
+ GLX_QUERY( GLUT_WINDOW_ACCUM_BLUE_SIZE, GLX_ACCUM_BLUE_SIZE );
+ GLX_QUERY( GLUT_WINDOW_ACCUM_ALPHA_SIZE, GLX_ACCUM_ALPHA_SIZE );
+ GLX_QUERY( GLUT_WINDOW_STEREO, GLX_STEREO );
+
+# undef GLX_QUERY
+
+ /*
+ * Colormap size is handled in a bit different way than all the rest
+ */
+ case GLUT_WINDOW_COLORMAP_SIZE:
+ if( (fghGetConfig( GLX_RGBA )) || (fgStructure.Window == NULL) )
+ {
+ /*
+ * We've got a RGBA visual, so there is no colormap at all.
+ * The other possibility is that we have no current window set.
+ */
+ return 0;
+ }
+ return fgStructure.Window->Window.VisualInfo->visual->map_entries;
+
+ /*
+ * Those calls are somewhat similiar, as they use XGetWindowAttributes()
+ * function
+ */
+ case GLUT_WINDOW_X:
+ case GLUT_WINDOW_Y:
+ case GLUT_WINDOW_BORDER_WIDTH:
+ case GLUT_WINDOW_HEADER_HEIGHT:
+ {
+ int x, y;
+ Window w;
+
+ if( fgStructure.Window == NULL )
+ return 0;
+
+ XTranslateCoordinates(
+ fgDisplay.Display,
+ fgStructure.Window->Window.Handle,
+ fgDisplay.RootWindow,
+ 0, 0, &x, &y, &w);
+
+ switch ( eWhat )
+ {
+ case GLUT_WINDOW_X: return x;
+ case GLUT_WINDOW_Y: return y;
+ }
+
+ if ( w == 0 )
+ return 0;
+ XTranslateCoordinates(
+ fgDisplay.Display,
+ fgStructure.Window->Window.Handle,
+ w, 0, 0, &x, &y, &w);
+
+ switch ( eWhat )
+ {
+ case GLUT_WINDOW_BORDER_WIDTH: return x;
+ case GLUT_WINDOW_HEADER_HEIGHT: return y;
+ }
+ }
+
+ case GLUT_WINDOW_WIDTH:
+ case GLUT_WINDOW_HEIGHT:
+ {
+ XWindowAttributes winAttributes;
+
+ if( fgStructure.Window == NULL )
+ return 0;
+ XGetWindowAttributes(
+ fgDisplay.Display,
+ fgStructure.Window->Window.Handle,
+ &winAttributes
+ );
+ switch ( eWhat )
+ {
+ case GLUT_WINDOW_WIDTH: return winAttributes.width ;
+ case GLUT_WINDOW_HEIGHT: return winAttributes.height ;
+ }
+ }
+
+ /*
+ * I do not know yet if there will be a fgChooseVisual() function for Win32
+ */
+ case GLUT_DISPLAY_MODE_POSSIBLE:
+ return( fgChooseVisual() == NULL ? 0 : 1 );
+
+ /*
+ * This is system-dependant
+ */
+ case GLUT_WINDOW_FORMAT_ID:
+ if( fgStructure.Window == NULL )
+ return 0;
+
+ return fgStructure.Window->Window.VisualInfo->visualid;
+
+#elif TARGET_HOST_WIN32 || TARGET_HOST_WINCE
+
+ /*
+ * Handle the OpenGL inquiries
+ */
+ case GLUT_WINDOW_RGBA:
+ glGetBooleanv ( GL_RGBA_MODE, &boolValue );
+ returnValue = boolValue ? 1 : 0;
+ return returnValue;
+ case GLUT_WINDOW_DOUBLEBUFFER:
+ glGetBooleanv ( GL_DOUBLEBUFFER, &boolValue );
+ returnValue = boolValue ? 1 : 0;
+ return returnValue;
+ case GLUT_WINDOW_STEREO:
+ glGetBooleanv ( GL_STEREO, &boolValue );
+ returnValue = boolValue ? 1 : 0;
+ return returnValue;
+
+ case GLUT_WINDOW_RED_SIZE:
+ glGetIntegerv ( GL_RED_BITS, &returnValue );
+ return returnValue;
+ case GLUT_WINDOW_GREEN_SIZE:
+ glGetIntegerv ( GL_GREEN_BITS, &returnValue );
+ return returnValue;
+ case GLUT_WINDOW_BLUE_SIZE:
+ glGetIntegerv ( GL_BLUE_BITS, &returnValue );
+ return returnValue;
+ case GLUT_WINDOW_ALPHA_SIZE:
+ glGetIntegerv ( GL_ALPHA_BITS, &returnValue );
+ return returnValue;
+ case GLUT_WINDOW_ACCUM_RED_SIZE:
+ glGetIntegerv ( GL_ACCUM_RED_BITS, &returnValue );
+ return returnValue;
+ case GLUT_WINDOW_ACCUM_GREEN_SIZE:
+ glGetIntegerv ( GL_ACCUM_GREEN_BITS, &returnValue );
+ return returnValue;
+ case GLUT_WINDOW_ACCUM_BLUE_SIZE:
+ glGetIntegerv ( GL_ACCUM_BLUE_BITS, &returnValue );
+ return returnValue;
+ case GLUT_WINDOW_ACCUM_ALPHA_SIZE:
+ glGetIntegerv ( GL_ACCUM_ALPHA_BITS, &returnValue );
+ return returnValue;
+ case GLUT_WINDOW_DEPTH_SIZE:
+ glGetIntegerv ( GL_DEPTH_BITS, &returnValue );
+ return returnValue;
+
+ case GLUT_WINDOW_BUFFER_SIZE:
+ returnValue = 1 ; /* ????? */
+ return returnValue;
+ case GLUT_WINDOW_STENCIL_SIZE:
+ returnValue = 0 ; /* ????? */
+ return returnValue;
+
+ case GLUT_WINDOW_X:
+ case GLUT_WINDOW_Y:
+ case GLUT_WINDOW_WIDTH:
+ case GLUT_WINDOW_HEIGHT:
+ {
+ /*
+ * There is considerable confusion about the "right thing to
+ * do" concerning window size and position. GLUT itself is
+ * not consistent between Windows and UNIX/X11; since
+ * platform independence is a virtue for "freeglut", we
+ * decided to break with GLUT's behaviour.
+ *
+ * Under UNIX/X11, it is apparently not possible to get the
+ * window border sizes in order to subtract them off the
+ * window's initial position until some time after the window
+ * has been created. Therefore we decided on the following
+ * behaviour, both under Windows and under UNIX/X11:
+ * - When you create a window with position (x,y) and size
+ * (w,h), the upper left hand corner of the outside of the
+ * window is at (x,y) and the size of the drawable area is
+ * (w,h).
+ * - When you query the size and position of the window--as
+ * is happening here for Windows--"freeglut" will return
+ * the size of the drawable area--the (w,h) that you
+ * specified when you created the window--and the coordinates
+ * of the upper left hand corner of the drawable
+ * area--which is NOT the (x,y) you specified.
+ */
+
+ RECT winRect;
+
+ freeglut_return_val_if_fail( fgStructure.Window != NULL, 0 );
+
+ /*
+ * We need to call GetWindowRect() first...
+ * (this returns the pixel coordinates of the outside of the window)
+ */
+ GetWindowRect( fgStructure.Window->Window.Handle, &winRect );
+
+ /*
+ * ...then we've got to correct the results we've just received...
+ */
+
+#if !TARGET_HOST_WINCE
+ if ( ( fgStructure.GameMode != fgStructure.Window ) && (
fgStructure.Window->Parent == NULL ) &&
+ ( ! fgStructure.Window->IsMenu ) )
+ {
+ winRect.left += GetSystemMetrics( SM_CXSIZEFRAME );
+ winRect.right -= GetSystemMetrics( SM_CXSIZEFRAME );
+ winRect.top += GetSystemMetrics( SM_CYSIZEFRAME ) + GetSystemMetrics(
SM_CYCAPTION );
+ winRect.bottom -= GetSystemMetrics( SM_CYSIZEFRAME );
+ }
+#endif /* !TARGET_HOST_WINCE */
+
+ switch( eWhat )
+ {
+ case GLUT_WINDOW_X: return winRect.left ;
+ case GLUT_WINDOW_Y: return winRect.top ;
+ case GLUT_WINDOW_WIDTH: return winRect.right - winRect.left;
+ case GLUT_WINDOW_HEIGHT: return winRect.bottom - winRect.top;
+ }
+ }
+ break;
+
+ case GLUT_WINDOW_BORDER_WIDTH :
+#if TARGET_HOST_WINCE
+ return 0;
+#else
+ return GetSystemMetrics( SM_CXSIZEFRAME );
+#endif /* !TARGET_HOST_WINCE */
+
+ case GLUT_WINDOW_HEADER_HEIGHT :
+#if TARGET_HOST_WINCE
+ return 0;
+#else
+ return GetSystemMetrics( SM_CYCAPTION );
+#endif /* TARGET_HOST_WINCE */
+
+ case GLUT_DISPLAY_MODE_POSSIBLE:
+#if TARGET_HOST_WINCE
+ return GL_FALSE;
+#else
+ return fgSetupPixelFormat( fgStructure.Window, GL_TRUE,
+ PFD_MAIN_PLANE );
+#endif /* TARGET_HOST_WINCE */
+
+
+ case GLUT_WINDOW_FORMAT_ID:
+#if !TARGET_HOST_WINCE
+ if( fgStructure.Window != NULL )
+ return GetPixelFormat( fgStructure.Window->Window.Device );
+#endif /* TARGET_HOST_WINCE */
+ return 0;
+
+#endif
+
+ /*
+ * The window structure queries
+ */
+ case GLUT_WINDOW_PARENT:
+ if( fgStructure.Window == NULL ) return 0;
+ if( fgStructure.Window->Parent == NULL ) return 0;
+ return fgStructure.Window->Parent->ID;
+
+ case GLUT_WINDOW_NUM_CHILDREN:
+ if( fgStructure.Window == NULL )
+ return 0;
+ return fgListLength( &fgStructure.Window->Children );
+
+ case GLUT_WINDOW_CURSOR:
+ if( fgStructure.Window == NULL )
+ return 0;
+ return fgStructure.Window->State.Cursor;
+
+ case GLUT_MENU_NUM_ITEMS:
+ if( fgStructure.Menu == NULL )
+ return 0;
+ return fgListLength( &fgStructure.Menu->Entries );
+
+ case GLUT_ACTION_ON_WINDOW_CLOSE:
+ return fgState.ActionOnWindowClose;
+
+ case GLUT_VERSION :
+ return VERSION_MAJOR * 10000 + VERSION_MINOR * 100 + VERSION_PATCH;
+
+ case GLUT_RENDERING_CONTEXT:
+ return fgState.UseCurrentContext ? GLUT_USE_CURRENT_CONTEXT
+ : GLUT_CREATE_NEW_CONTEXT;
+
+ case GLUT_DIRECT_RENDERING:
+ return fgState.DirectContext;
+ break;
+
+ default:
+ fgWarning( "glutGet(): missing enum handle %i\n", eWhat );
+ break;
+ }
+ return -1;
+}
+
+/*
+ * Returns various device information.
+ */
+int FGAPIENTRY glutDeviceGet( GLenum eWhat )
+{
+ freeglut_assert_ready;
+
+ /*
+ * XXX WARNING: we are mostly lying in this function.
+ */
+ switch( eWhat )
+ {
+ case GLUT_HAS_KEYBOARD:
+ /*
+ * We always have a keyboard present on PC machines...
+ *
+ * XXX I think that some of my PCs will boot without a keyboard.
+ * XXX Also, who says that we are running on a PC? UNIX/X11
+ * XXX is much more generic, and X11 can go over a network.
+ * XXX Though in actuality, we can probably assume BOTH a
+ * XXX mouse and keyboard for most/all of our users.
+ */
+ return TRUE ;
+
+#if TARGET_HOST_UNIX_X11
+
+ case GLUT_HAS_MOUSE:
+ return TRUE ;
+
+ case GLUT_NUM_MOUSE_BUTTONS:
+ /*
+ * Return the number of mouse buttons available. This is a big guess.
+ *
+ * XXX We can probe /var/run/dmesg.boot which is world-readable.
+ * XXX This would be somewhat system-dependant, but is doable.
+ * XXX E.g., on NetBSD, my USB mouse registers:
+ * XXX ums0 at uhidev0: 3 buttons and Z dir.
+ * XXX We can also probe /var/log/XFree86\..*\.log to get
+ * XXX lines such as:
+ * XXX (**) Option "Buttons" "5"
+ * XXX (**) Option "ZAxisMapping" "4 5"
+ * XXX (**) Mouse0: ZAxisMapping: buttons 4 and 5
+ * XXX (**) Mouse0: Buttons: 5
+ * XXX ...which tells us even more, and is a bit less
+ * XXX system-dependant. (Other than MS-WINDOWS, all
+ * XXX target hosts with actual users are probably running
+ * XXX XFree86...) It is at least worth taking a look at
+ * XXX this file.
+ */
+ return 3 ;
+
+#elif TARGET_HOST_WIN32 || TARGET_HOST_WINCE
+
+ case GLUT_HAS_MOUSE:
+ /*
+ * The Windows can be booted without a mouse.
+ * It would be nice to have this reported.
+ */
+ return GetSystemMetrics( SM_MOUSEPRESENT );
+
+ case GLUT_NUM_MOUSE_BUTTONS:
+ /*
+ * We are much more fortunate under Win32 about this...
+ */
+#if TARGET_HOST_WINCE
+ return 1;
+#else
+ return GetSystemMetrics( SM_CMOUSEBUTTONS );
+#endif /* TARGET_HOST_WINCE */
+
+#endif
+
+ case GLUT_JOYSTICK_POLL_RATE:
+ case GLUT_HAS_JOYSTICK:
+ case GLUT_OWNS_JOYSTICK:
+ case GLUT_JOYSTICK_BUTTONS:
+ case GLUT_JOYSTICK_AXES:
+ /*
+ * XXX WARNING: THIS IS A BIG LIE!
+ */
+ return 0;
+
+ case GLUT_HAS_SPACEBALL:
+ case GLUT_HAS_DIAL_AND_BUTTON_BOX:
+ case GLUT_HAS_TABLET:
+ return FALSE;
+
+ case GLUT_NUM_SPACEBALL_BUTTONS:
+ case GLUT_NUM_BUTTON_BOX_BUTTONS:
+ case GLUT_NUM_DIALS:
+ case GLUT_NUM_TABLET_BUTTONS:
+ return 0;
+
+ case GLUT_DEVICE_IGNORE_KEY_REPEAT:
+ return fgStructure.Window ? fgStructure.Window->State.IgnoreKeyRepeat : 0;
+
+ case GLUT_DEVICE_KEY_REPEAT:
+ /*
+ * XXX WARNING: THIS IS A BIG LIE!
+ */
+ return GLUT_KEY_REPEAT_DEFAULT;
+
+ default:
+ fgWarning( "glutDeviceGet(): missing enum handle %i\n", eWhat );
+ break;
+ }
+
+ /*
+ * And now -- the failure.
+ */
+ return -1;
+}
+
+/*
+ * This should return the current state of ALT, SHIFT and CTRL keys.
+ */
+int FGAPIENTRY glutGetModifiers( void )
+{
+ if( fgState.Modifiers == 0xffffffff )
+ {
+ fgWarning( "glutGetModifiers() called outside an input callback" );
+ return 0;
+ }
+
+ return fgState.Modifiers;
+}
+
+/*
+ * Return the state of the GLUT API overlay subsystem. A misery ;-)
+ */
+int FGAPIENTRY glutLayerGet( GLenum eWhat )
+{
+ freeglut_assert_ready;
+
+ /*
+ * This is easy as layers are not implemented ;-)
+ *
+ * XXX Can we merge the UNIX/X11 and WIN32 sections? Or
+ * XXX is overlay support planned?
+ */
+ switch( eWhat )
+ {
+
+#if TARGET_HOST_UNIX_X11
+
+ case GLUT_OVERLAY_POSSIBLE:
+ return FALSE;
+
+ case GLUT_LAYER_IN_USE:
+ return GLUT_NORMAL;
+
+ case GLUT_HAS_OVERLAY:
+ return FALSE;
+
+ case GLUT_TRANSPARENT_INDEX:
+ /*
+ * Return just anything, which is always defined as zero
+ *
+ * XXX HUH?
+ */
+ return 0;
+
+ case GLUT_NORMAL_DAMAGED:
+ /*
+ * XXX Actually I do not know. Maybe.
+ */
+ return FALSE;
+
+ case GLUT_OVERLAY_DAMAGED:
+ return -1;
+
+#elif TARGET_HOST_WIN32 || TARGET_HOST_WINCE
+
+ case GLUT_OVERLAY_POSSIBLE:
+/* return fgSetupPixelFormat( fgStructure.Window, GL_TRUE,
+ PFD_OVERLAY_PLANE ); */
+ return FALSE ;
+
+ case GLUT_LAYER_IN_USE:
+ return GLUT_NORMAL;
+
+ case GLUT_HAS_OVERLAY:
+ return FALSE;
+
+ case GLUT_TRANSPARENT_INDEX:
+ /*
+ * Return just anything, which is always defined as zero
+ *
+ * XXX HUH?
+ */
+ return 0;
+
+ case GLUT_NORMAL_DAMAGED:
+ /*
+ * XXX Actually I do not know. Maybe.
+ */
+ return FALSE;
+
+ case GLUT_OVERLAY_DAMAGED:
+ return -1;
+#endif
+
+ default:
+ fgWarning( "glutLayerGet(): missing enum handle %i\n", eWhat );
+ break;
+ }
+
+ /*
+ * And fail. That's good. Programs do love failing.
+ */
+ return -1;
+}
+
+/*** END OF FILE ***/
Index: external/trimesh/gluit/freeglut_overlay.c
--- external/trimesh/gluit/freeglut_overlay.c (revision 0)
+++ external/trimesh/gluit/freeglut_overlay.c (revision 0)
@@ -0,0 +1,49 @@
+/*
+ * freeglut_overlay.c
+ *
+ * Overlay management functions (as defined by GLUT API)
+ *
+ * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
+ * Written by Pawel W. Olszta, <olszta(a)sourceforge.net>
+ * Creation date: Thu Dec 16 1999
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <GL/freeglut.h>
+#include "freeglut_internal.h"
+
+/*
+ * NOTE: functions declared in this file probably will not be implemented.
+ */
+
+/* -- INTERFACE FUNCTIONS -------------------------------------------------- */
+
+void FGAPIENTRY glutEstablishOverlay( void ) { /* Not implemented */ }
+void FGAPIENTRY glutRemoveOverlay( void ) { /* Not implemented */ }
+void FGAPIENTRY glutUseLayer( GLenum layer ) { /* Not implemented */ }
+void FGAPIENTRY glutPostOverlayRedisplay( void ) { /* Not implemented */ }
+void FGAPIENTRY glutPostWindowOverlayRedisplay( int ID ) { /* Not implemented */ }
+void FGAPIENTRY glutShowOverlay( void ) { /* Not implemented */ }
+void FGAPIENTRY glutHideOverlay( void ) { /* Not implemented */ }
+
+/*** END OF FILE ***/
Index: external/trimesh/gluit/glui_translation.cc
--- external/trimesh/gluit/glui_translation.cc (revision 0)
+++ external/trimesh/gluit/glui_translation.cc (revision 0)
@@ -0,0 +1,518 @@
+/****************************************************************************
+
+ GLUI User Interface Toolkit
+ ---------------------------
+
+ glui_translation - GLUI_Translation control class
+
+
+ --------------------------------------------------
+
+ Copyright (c) 1998 Paul Rademacher
+
+ This program is freely distributable without licensing fees and is
+ provided without guarantee or warrantee expressed or implied. This
+ program is -not- in the public domain.
+
+*****************************************************************************/
+
+#include "glui.h"
+#include "glui_stdinc.h"
+#include "glui_algebra3.h"
+
+/********************** GLUI_Translation::iaction_mouse_down_handler() ***/
+/* These are really in local coords (5/10/99) */
+
+int GLUI_Translation::iaction_mouse_down_handler( int local_x,
+ int local_y )
+{
+ int center_x, center_y;
+
+ down_x = local_x;
+ down_y = local_y;
+
+ if ( trans_type == GLUI_TRANSLATION_XY ) {
+ orig_x = float_array_val[0];
+ orig_y = float_array_val[1];
+
+ /** Check if the Alt key is down, which means lock to an axis **/
+
+ center_x = w/2;
+ center_y = (h-18)/2;
+
+ if ( glui->curr_modifiers & GLUT_ACTIVE_ALT ) {
+ if ( ABS(local_y-center_y) > ABS(local_x-center_x) ) {
+ locked = GLUI_TRANSLATION_LOCK_Y;
+ glutSetCursor( GLUT_CURSOR_UP_DOWN );
+ }
+ else {
+ locked = GLUI_TRANSLATION_LOCK_X;
+ glutSetCursor( GLUT_CURSOR_LEFT_RIGHT );
+ }
+ }
+ else {
+ locked = GLUI_TRANSLATION_LOCK_NONE;
+ glutSetCursor( GLUT_CURSOR_SPRAY );
+ }
+ }
+ else if ( trans_type == GLUI_TRANSLATION_X ) {
+ glutSetCursor( GLUT_CURSOR_LEFT_RIGHT );
+ orig_x = float_array_val[0];
+ }
+ else if ( trans_type == GLUI_TRANSLATION_Y ) {
+ glutSetCursor( GLUT_CURSOR_UP_DOWN );
+ orig_y = float_array_val[0];
+ }
+ else if ( trans_type == GLUI_TRANSLATION_Z ) {
+ glutSetCursor( GLUT_CURSOR_UP_DOWN );
+ orig_z = float_array_val[0];
+ }
+
+ trans_mouse_code = 1;
+ translate_and_draw_front();
+
+ return false;
+}
+
+
+/*********************** GLUI_Translation::iaction_mouse_up_handler() **********/
+
+int GLUI_Translation::iaction_mouse_up_handler( int local_x, int local_y,
+ int inside )
+{
+ trans_mouse_code = GLUI_TRANSLATION_MOUSE_NONE;
+ locked = GLUI_TRANSLATION_LOCK_NONE;
+
+ translate_and_draw_front();
+
+ return false;
+}
+
+
+/******************* GLUI_Translation::iaction_mouse_held_down_handler() ******/
+
+int GLUI_Translation::iaction_mouse_held_down_handler( int local_x, int local_y,
+ int inside)
+{
+ float x_off, y_off;
+ float off_array[2];
+
+ x_off = scale_factor * (float)(local_x - down_x);
+ y_off = -scale_factor * (float)(local_y - down_y);
+
+ if ( glui->curr_modifiers & GLUT_ACTIVE_SHIFT ) {
+ x_off *= 100.0f;
+ y_off *= 100.0f;
+ }
+ else if ( glui->curr_modifiers & GLUT_ACTIVE_CTRL ) {
+ x_off *= .01f;
+ y_off *= .01f;
+ }
+
+
+ if ( trans_type == GLUI_TRANSLATION_XY ) {
+
+ if ( locked == GLUI_TRANSLATION_LOCK_X )
+ y_off = 0.0;
+ else if ( locked == GLUI_TRANSLATION_LOCK_Y )
+ x_off = 0.0;
+
+ off_array[0] = x_off + orig_x;
+ off_array[1] = y_off + orig_y;
+ }
+ else if ( trans_type == GLUI_TRANSLATION_X ) {
+ off_array[0] = x_off + orig_x;
+ }
+ else if ( trans_type == GLUI_TRANSLATION_Y ) {
+ off_array[0] = y_off + orig_y;
+ }
+ else if ( trans_type == GLUI_TRANSLATION_Z ) {
+ off_array[0] = y_off + orig_z;
+ }
+
+ set_float_array_val( (float*) &off_array[0] );
+
+ return false;
+}
+
+
+/******************** GLUI_Translation::iaction_draw_active_area_persp() **************/
+
+void GLUI_Translation::iaction_draw_active_area_persp( void )
+{
+ if ( NOT can_draw() )
+ return;
+}
+
+
+/******************** GLUI_Translation::iaction_draw_active_area_ortho() **********/
+
+void GLUI_Translation::iaction_draw_active_area_ortho( void )
+{
+ if ( NOT can_draw() )
+ return;
+
+ /********* Draw emboss circles around arcball control *********/
+ float radius;
+ radius = (float)(h-22)/2.0; /* MIN((float)w/2.0, (float)h/2.0); */
+ glLineWidth( 1.0 );
+
+ draw_emboss_box( (int) -radius-2, (int)radius+2,
+ (int)-radius-2, (int)radius+2 );
+
+ glMatrixMode( GL_MODELVIEW );
+ glPushMatrix();
+ glTranslatef( .5, .5, .5 );
+ /* glScalef( radius-1.0, radius-1.0, radius-1.0 ); */
+ if ( trans_type == GLUI_TRANSLATION_Z )
+ draw_2d_z_arrows((int)radius-1);
+ else if ( trans_type == GLUI_TRANSLATION_XY )
+ draw_2d_xy_arrows((int)radius-1);
+ else if ( trans_type == GLUI_TRANSLATION_X )
+ draw_2d_x_arrows((int)radius-1);
+ else if ( trans_type == GLUI_TRANSLATION_Y )
+ draw_2d_y_arrows((int)radius-1);
+
+ glPopMatrix();
+}
+
+
+/******************************** GLUI_Translation::iaction_dump() **********/
+
+void GLUI_Translation::iaction_dump( FILE *output )
+{
+}
+
+
+/******************** GLUI_Translation::iaction_special_handler() **********/
+
+int GLUI_Translation::iaction_special_handler( int key,int modifiers )
+{
+
+ return false;
+}
+
+
+
+/*************************** GLUI_Translation::draw_2d_z_arrows() **************/
+
+void GLUI_Translation::draw_2d_z_arrows( int radius )
+{
+ if ( trans_mouse_code != GLUI_TRANSLATION_MOUSE_NONE ) {
+ draw_2d_arrow(radius, true, 2);
+ draw_2d_arrow(radius, true, 0);
+ }
+ else {
+ draw_2d_arrow(radius, false, 2);
+ draw_2d_arrow(radius, false, 0);
+ }
+}
+
+
+/*************************** GLUI_Translation::draw_2d_x_arrows() **************/
+
+void GLUI_Translation::draw_2d_x_arrows( int radius )
+{
+ if ( trans_mouse_code != GLUI_TRANSLATION_MOUSE_NONE ) {
+ draw_2d_arrow(radius, true, 1);
+ draw_2d_arrow(radius, true, 3);
+ }
+ else {
+ draw_2d_arrow(radius, false, 1);
+ draw_2d_arrow(radius, false, 3);
+ }
+}
+
+
+/*************************** GLUI_Translation::draw_2d_y_arrows() **************/
+
+void GLUI_Translation::draw_2d_y_arrows( int radius )
+{
+ if ( trans_mouse_code != GLUI_TRANSLATION_MOUSE_NONE ) {
+ draw_2d_arrow(radius, true, 0);
+ draw_2d_arrow(radius, true, 2);
+ }
+ else {
+ draw_2d_arrow(radius, false, 0);
+ draw_2d_arrow(radius, false, 2);
+ }
+}
+
+
+/************************** GLUI_Translation::draw_2d_xy_arrows() **************/
+
+void GLUI_Translation::draw_2d_xy_arrows( int radius)
+{
+ if ( trans_mouse_code != GLUI_TRANSLATION_MOUSE_NONE ) {
+ if ( locked == GLUI_TRANSLATION_LOCK_X ) {
+ draw_2d_arrow(radius, false, 0);
+ draw_2d_arrow(radius, false, 2);
+ draw_2d_arrow(radius, true, 1);
+ draw_2d_arrow(radius, true, 3);
+ }
+ else if ( locked == GLUI_TRANSLATION_LOCK_Y ) {
+ draw_2d_arrow(radius, false, 1);
+ draw_2d_arrow(radius, false, 3);
+ draw_2d_arrow(radius, true, 0);
+ draw_2d_arrow(radius, true, 2);
+ }
+ else {
+ draw_2d_arrow(radius, true, 0);
+ draw_2d_arrow(radius, true, 1);
+ draw_2d_arrow(radius, true, 2);
+ draw_2d_arrow(radius, true, 3);
+ }
+ }
+ else {
+ draw_2d_arrow(radius, false, 0);
+ draw_2d_arrow(radius, false, 1);
+ draw_2d_arrow(radius, false, 2);
+ draw_2d_arrow(radius, false, 3);
+ }
+
+ return;
+}
+
+
+/*************************** GLUI_Translation::draw_2d_arrow() **************/
+/* ori: 0=up, 1=left, 2=down, 3=right */
+/* */
+/* */
+/* 0, y2 */
+/* / \ */
+/* / \ */
+/* / \ */
+/* / \ */
+/* / \ */
+/* / \ */
+/* / \ */
+/* / \ */
+/* -x2,y1 -x1b,y1 x1b,y1 x2,y1 */
+/* | | */
+/* | | */
+/* | | */
+/* | | */
+/* | | */
+/* -x1a,y0 x1a,y0 */
+/* */
+
+
+void GLUI_Translation::draw_2d_arrow( int radius, int filled, int orientation )
+{
+ float x1 = .2, x2 = .4, y1 = .54, y2 = .94, y0;
+ float x1a, x1b;
+/*
+ vec3 col1( 0.0, 0.0, 0.0 ), col2( .45, .45, .45 ),
+ col3( .7, .7, .7 ), col4( 1.0, 1.0, 1.0 );
+ vec3 c1, c2, c3, c4, c5, c6;
+*/
+ vec3 white(1.0,1.0,1.0), black(0.0,0.0,0.0), gray(.45,.45,.45),
+ bkgd(.7,.7,.7);
+ int c_off=0; /* color index offset */
+
+ if ( glui )
+ bkgd.set(glui->bkgd_color_f[0],
+ glui->bkgd_color_f[1],
+ glui->bkgd_color_f[2]);
+
+ /* bkgd[0] = 255.0; bkgd[1] = 0; */
+
+ /** The following 8 colors define the shading of an octagon, in
+ clockwise order, starting from the upstroke on the left **/
+ /** This is for an outside and inside octagons **/
+ vec3 colors_out[]={white, white, white, gray, black, black, black, gray};
+ vec3 colors_in[] ={bkgd,white,bkgd,gray,gray,gray,gray,gray};
+
+#define SET_COL_OUT(i) glColor3fv((float*) &colors_out[(i)%8][0]);
+#define SET_COL_IN(i) glColor3fv((float*) &colors_in[(i)%8][0]);
+
+ x1 = (float)radius * .2;
+ x2 = x1 * 2;
+ y1 = (float)radius * .54;
+ y2 = y1 + x2;
+ x1a = x1;
+ x1b = x1;
+
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+
+#define DRAW_SEG( xa,ya,xb,yb ) glVertex2f(xa,ya); glVertex2f(xb,yb);
+
+ glScalef( -1.0, 1.0, 1.0 );
+
+ if ( orientation == 2 ) {
+ c_off = 4;
+ }
+ else if ( orientation == 0 ) {
+ c_off = 0;
+ glRotatef( 180.0, 0.0, 0.0, 1.0 );
+ }
+ else if ( orientation == 1 ) {
+ c_off = 2;
+ glRotatef( 90.0, 0.0, 0.0, 1.0 );
+ }
+ else if ( orientation == 3 ) {
+ c_off = 6;
+ glRotatef( -90.0, 0.0, 0.0, 1.0 );
+ }
+
+ if ( trans_type == GLUI_TRANSLATION_Z )
+ y0 = 0.0;
+ else if ( trans_type == GLUI_TRANSLATION_XY )
+ y0 = x1;
+ else
+ y0 = 0.0;
+
+
+ if ( trans_type == GLUI_TRANSLATION_Z ) {
+ if ( orientation == 0 ) {
+ y1 += 2.0;
+ y2 += 0.0;
+
+ x1b -= 2.0;
+ x2 -= 2.0;
+ x1a += 2.0;
+ }
+ else if ( orientation == 2 ) {
+ y1 -= 6.0;
+ x1a += 2.0;
+ x1b += 4.0;
+ x2 += 6.0;
+ }
+ }
+
+ /*** Fill in inside of arrow ***/
+ if ( NOT filled ) { /*** Means button is up - control is not clicked ***/
+ /*glColor3f( .8, .8, .8 ); */
+ set_to_bkgd_color();
+ glColor3f( bkgd[0]+.07, bkgd[1]+.07, bkgd[2]+.07 );
+ }
+ else { /*** Button is down on control ***/
+ glColor3f( .6, .6, .6 );
+ c_off += 4; /* Indents the shadows - goes from a raised look to embossed */
+ }
+
+ /*** Check if control is enabled or not ***/
+ if ( NOT enabled ) {
+ set_to_bkgd_color();
+ /*c_off += 4; -- Indents the shadows - goes from a raised look to embossed */
+ colors_out[0] = colors_out[1] = colors_out[2] = colors_out[7] = gray;
+ colors_out[3] = colors_out[4] = colors_out[5] = colors_out[6] = white;
+ colors_in[0] = colors_in[1] = colors_in[2] = colors_in[7] = white;
+ colors_in[3] = colors_in[4] = colors_in[5] = colors_in[6] = gray;
+
+ }
+
+ glBegin( GL_POLYGON );
+ glVertex2f( 0.0, 0.0 ); glVertex2f( -x1a, 0.0 );
+ glVertex2f( -x1a, 0.0 ); glVertex2f( -x1b, y1 );
+ glVertex2f( x1b, y1); glVertex2f( x1a, 0.0 );
+ glVertex2f( x1a, 0.0 ); glVertex2f( 0.0, 0.0 );
+ glEnd();
+ glBegin( GL_TRIANGLES );
+ glVertex2f( -x2, y1 ); glVertex2f( 0.0, y2 ); glVertex2f( x2, y1 );
+ glEnd();
+
+ glLineWidth( 1.0 );
+ /*** Draw arrow outline ***/
+ glBegin( GL_LINES );
+
+ SET_COL_IN(1+c_off); DRAW_SEG( 0.0, y2-1.0, -x2, y1-1.0 );
+ SET_COL_IN(6+c_off); DRAW_SEG( -x2+2.0, y1+1.0, -x1b+1.0, y1+1.0 );
+ SET_COL_IN(0+c_off); DRAW_SEG( -x1b+1.0, y1+1.0, -x1a+1.0, y0 );
+ SET_COL_IN(3+c_off); DRAW_SEG( 0.0, y2-1.0, x2, y1-1.0 );
+ SET_COL_IN(6+c_off); DRAW_SEG( x2-1.0, y1+1.0, x1b-1.0, y1+1.0 );
+ SET_COL_IN(4+c_off); DRAW_SEG( x1b-1.0, y1+1.0, x1a-1.0, y0 );
+
+ SET_COL_OUT(0+c_off); DRAW_SEG( -x1a, y0, -x1b, y1 );
+ SET_COL_OUT(6+c_off); DRAW_SEG( -x1b, y1, -x2, y1 );
+ SET_COL_OUT(1+c_off); DRAW_SEG( -x2, y1, 0.0, y2 );
+ SET_COL_OUT(3+c_off); DRAW_SEG( 0.0, y2, x2, y1 );
+ SET_COL_OUT(6+c_off); DRAW_SEG( x2, y1, x1b, y1 );
+ SET_COL_OUT(4+c_off); DRAW_SEG( x1b, y1, x1a, y0 );
+
+ glEnd();
+
+#undef DRAW_SEG
+
+ glPopMatrix();
+}
+
+
+/*************************** GLUI_Translation::get_mouse_code() *************/
+
+int GLUI_Translation::get_mouse_code( int x, int y )
+{
+ if ( x == 0 AND y < 0 )
+ return GLUI_TRANSLATION_MOUSE_DOWN;
+ else if ( x == 0 AND y > 0 )
+ return GLUI_TRANSLATION_MOUSE_UP;
+ else if ( x > 0 AND y == 0 )
+ return GLUI_TRANSLATION_MOUSE_LEFT;
+ else if ( x < 0 AND y == 0 )
+ return GLUI_TRANSLATION_MOUSE_RIGHT;
+ else if ( x < 0 AND y < 0 )
+ return GLUI_TRANSLATION_MOUSE_DOWN_LEFT;
+ else if ( x < 0 AND y > 0 )
+ return GLUI_TRANSLATION_MOUSE_DOWN_RIGHT;
+ else if ( x > 0 AND y < 0 )
+ return GLUI_TRANSLATION_MOUSE_UP_LEFT;
+ else if ( x > 0 AND y > 0 )
+ return GLUI_TRANSLATION_MOUSE_UP_RIGHT;
+
+
+ return GLUI_TRANSLATION_MOUSE_NONE;
+}
+
+
+/*********************************** GLUI_Translation::set_x() ******/
+
+void GLUI_Translation::set_x( float val )
+{
+ set_one_val( val, 0 );
+}
+
+
+/*********************************** GLUI_Translation::set_y() ******/
+
+void GLUI_Translation::set_y( float val )
+{
+ if ( trans_type == GLUI_TRANSLATION_XY )
+ set_one_val( val, 1 );
+ else
+ set_one_val( val, 0 );
+}
+
+
+/*********************************** GLUI_Translation::set_z() ******/
+
+void GLUI_Translation::set_z( float val )
+{
+ set_one_val( val, 0 );
+}
+
+
+/******************************* GLUI_Translation::set_one_val() ****/
+
+void GLUI_Translation::set_one_val( float val, int index )
+{
+ float *fp;
+
+ float_array_val[index] = val; /* set value in array */
+
+ /*** The code below is like output_live, except it only operates on
+ a single member of the float array (given by 'index') instead of
+ outputting the entire array ****/
+
+ if ( ptr_val == NULL OR NOT live_inited )
+ return;
+
+ fp = (float*) ptr_val;
+ fp[index] = float_array_val[index];
+ last_live_float_array[index] = float_array_val[index];
+
+ /** Update the main gfx window? **/
+ if ( this->glui != NULL ) {
+ this->glui->post_update_main_gfx();
+ }
+}
Index: external/trimesh/gluit/glui_img_checkbox_1_dis.c
--- external/trimesh/gluit/glui_img_checkbox_1_dis.c (revision 0)
+++ external/trimesh/gluit/glui_img_checkbox_1_dis.c (revision 0)
@@ -0,0 +1,38 @@
+
+
+int glui_img_checkbox_1_dis[] = { 13, 13, /* width, height */
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 128,128,128, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 255,255,255, 128,128,128, 64, 64, 64, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 255,255,255, 128,128,128,
+ 64, 64, 64, 192,192,192, 192,192,192, 192,192,192, 64, 64, 64,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 255,255,255, 128,128,128, 64, 64, 64, 192,192,192,
+ 192,192,192, 64, 64, 64, 64, 64, 64, 64, 64, 64, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 255,255,255,
+ 128,128,128, 64, 64, 64, 192,192,192, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 255,255,255, 128,128,128, 64, 64, 64,
+ 192,192,192, 64, 64, 64, 64, 64, 64, 192,192,192, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 192,192,192, 192,192,192, 192,192,192,
+ 255,255,255, 128,128,128, 64, 64, 64, 192,192,192, 64, 64, 64,
+ 192,192,192, 192,192,192, 192,192,192, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 192,192,192, 192,192,192, 255,255,255, 128,128,128,
+ 64, 64, 64, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 64, 64, 64, 64, 64, 64, 192,192,192,
+ 192,192,192, 255,255,255, 128,128,128, 64, 64, 64, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 64, 64, 64, 192,192,192, 192,192,192, 255,255,255,
+ 128,128,128, 64, 64, 64, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 255,255,255, 128,128,128, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 192,192,192,
+ 255,255,255, 128,128,128, 128,128,128, 128,128,128, 128,128,128,
+ 128,128,128, 128,128,128, 128,128,128, 128,128,128, 128,128,128,
+ 128,128,128, 128,128,128, 128,128,128, 255,255,255,
+};
Index: external/trimesh/gluit/glui_radio.cc
--- external/trimesh/gluit/glui_radio.cc (revision 0)
+++ external/trimesh/gluit/glui_radio.cc (revision 0)
@@ -0,0 +1,341 @@
+/****************************************************************************
+
+ GLUI User Interface Toolkit
+ ---------------------------
+
+ glui_radio.cpp - GLUI_RadioGroup and GLUI_RadioButton control classes
+
+
+ --------------------------------------------------
+
+ Copyright (c) 1998 Paul Rademacher
+
+ This program is freely distributable without licensing fees and is
+ provided without guarantee or warrantee expressed or implied. This
+ program is -not- in the public domain.
+
+*****************************************************************************/
+
+#include "glui.h"
+#include "glui_stdinc.h"
+
+/****************************** GLUI_RadioGroup::draw() **********/
+
+void GLUI_RadioGroup::draw( int x, int y )
+{
+ if ( NOT can_draw() )
+ return;
+
+ //draw_group(false);
+}
+
+
+/********************* GLUI_RadioGroup::draw_group(int translate) **********/
+
+void GLUI_RadioGroup::draw_group( int translate )
+{
+ GLUI_RadioButton *button;
+ int state = 0, orig;
+
+ if ( NOT can_draw() )
+ return;
+
+ orig = set_to_glut_window();
+
+ if ( translate )
+ state = glui->set_front_draw_buffer();
+
+ this->int_val = int_val;
+
+ glMatrixMode(GL_MODELVIEW );
+
+ button = (GLUI_RadioButton*) first_child();
+ while( button != NULL ) {
+
+ if ( translate ) {
+ glPushMatrix();
+ button->translate_to_origin();
+ }
+
+ if ( button->int_val )
+ button->draw_checked();
+ else
+ button->draw_unchecked();
+
+ if ( translate )
+ glPopMatrix();
+
+ button = (GLUI_RadioButton*) button->next();
+ }
+
+ if ( translate )
+ glui->restore_draw_buffer(state);
+
+ restore_window(orig);
+}
+
+
+/****************************** GLUI_RadioGroup::set_name() **********/
+
+void GLUI_RadioGroup::set_name( char *text )
+{
+ strncpy(name,text,sizeof(GLUI_String));
+
+ if ( glui )
+ glui->refresh();
+}
+
+
+/********************************* GLUI_RadioGroup::set_selected() **********/
+
+void GLUI_RadioGroup::set_selected( int int_val )
+{
+ GLUI_RadioButton *button;
+
+ this->int_val = int_val;
+
+ button = (GLUI_RadioButton*) first_child();
+ while( button != NULL ) {
+ if ( int_val == -1 ) { /*** All buttons in group are deselected ***/
+ button->set_int_val(0);
+ }
+ else if ( int_val == button->user_id ) { /*** This is selected button ***/
+ button->set_int_val(1);
+ }
+ else { /*** This is NOT selected button ***/
+ button->set_int_val(0);
+
+ }
+
+ button = (GLUI_RadioButton*) button->next();
+ }
+}
+
+
+/************************ GLUI_RadioButton::mouse_down_handler() **********/
+
+int GLUI_RadioButton::mouse_down_handler( int local_x, int local_y )
+{
+ if ( NOT group )
+ return false;
+
+ orig_value = group->int_val;
+
+ currently_inside = true;
+
+ group->set_selected( this->user_id );
+ group->draw_group( true );
+
+ return false;
+}
+
+
+/*************************** GLUI_RadioButton::mouse_up_handler() **********/
+
+int GLUI_RadioButton::mouse_up_handler( int local_x, int local_y,
+ int inside )
+{
+ if ( NOT group )
+ return false;
+
+ if ( NOT inside ) {
+ group->set_selected( orig_value );
+ group->draw_group( true );
+ }
+ else {
+ /** Now we update the radio button group. We tell the group
+ handler to set the currently-selected item to this button, which
+ is reference by its user_id/ordinal number within group **/
+
+ group->set_selected( this->user_id );
+ group->draw_group( true );
+
+ /*** Now update the linked variable, and call the callback,
+ but ONLY if the value of the radio group actually changed ***/
+ if ( group->int_val != orig_value ) {
+ group->output_live(true); /** Output live and update gfx ***/
+
+ group->execute_callback();
+ }
+ }
+
+ return false;
+}
+
+
+/********************** GLUI_RadioButton::mouse_held_down_handler() ******/
+
+int GLUI_RadioButton::mouse_held_down_handler( int local_x, int local_y,
+ int inside)
+{
+ if ( NOT inside AND currently_inside == true ) {
+ group->set_selected( orig_value );
+ group->draw_group( true );
+ }
+ else if ( inside AND currently_inside == false ) {
+ group->set_selected( this->user_id );
+ group->draw_group( true );
+ }
+
+ currently_inside = inside;
+
+ return false;
+}
+
+
+/****************************** GLUI_RadioButton::draw() **********/
+
+void GLUI_RadioButton::draw( int x, int y )
+{
+ int orig;
+
+ orig = set_to_glut_window();
+
+ if ( NOT group OR NOT can_draw() )
+ return;
+
+ /*** See if we're the currently-selected button. If so, draw ***/
+ if ( group->int_val == this->user_id ) {
+ if ( enabled )
+ glui->std_bitmaps.draw( GLUI_STDBITMAP_RADIOBUTTON_ON, 0, 0 );
+ else
+ glui->std_bitmaps.draw( GLUI_STDBITMAP_RADIOBUTTON_ON_DIS, 0, 0 );
+ }
+ else {
+ if ( enabled )
+ glui->std_bitmaps.draw( GLUI_STDBITMAP_RADIOBUTTON_OFF, 0, 0 );
+ else
+ glui->std_bitmaps.draw( GLUI_STDBITMAP_RADIOBUTTON_OFF_DIS, 0, 0 );
+ }
+
+ draw_active_area();
+
+ draw_name( text_x_offset, 10 );
+
+ restore_window(orig);
+}
+
+
+/************************************ GLUI_RadioButton::draw_checked() ******/
+
+void GLUI_RadioButton::draw_checked( void )
+{
+ int orig;
+
+ if ( NOT can_draw() )
+ return;
+
+ orig = set_to_glut_window();
+ if ( enabled )
+ glui->std_bitmaps.draw( GLUI_STDBITMAP_RADIOBUTTON_ON, 0, 0 );
+ else
+ glui->std_bitmaps.draw( GLUI_STDBITMAP_RADIOBUTTON_ON_DIS, 0, 0 );
+ draw_active_area();
+ restore_window(orig);
+}
+
+
+/*********************************** GLUI_RadioButton::draw_unchecked() ******/
+
+void GLUI_RadioButton::draw_unchecked( void )
+{
+ int orig;
+
+ if ( NOT can_draw() )
+ return;
+
+ orig = set_to_glut_window();
+ if ( enabled )
+ glui->std_bitmaps.draw( GLUI_STDBITMAP_RADIOBUTTON_OFF, 0, 0 );
+ else
+ glui->std_bitmaps.draw( GLUI_STDBITMAP_RADIOBUTTON_OFF_DIS, 0, 0 );
+ draw_active_area();
+
+ restore_window(orig);
+}
+
+
+/**************************************** GLUI_RadioButton::draw_O() ********/
+
+void GLUI_RadioButton::draw_O( void )
+{
+ int i, j, orig;
+
+ if ( NOT can_draw() )
+ return;
+
+ orig = set_to_glut_window();
+
+ glBegin( GL_POINTS );
+ for(i=3; i<=GLUI_RADIOBUTTON_SIZE-3; i++ )
+ for(j=3; j<=GLUI_RADIOBUTTON_SIZE-3; j++ )
+ glVertex2i(i,j);
+ glEnd();
+
+ restore_window(orig);
+}
+
+
+/******************************** GLUI_RadioButton::update_size() **********/
+
+void GLUI_RadioButton::update_size( void )
+{
+ int text_size;
+
+ if ( NOT glui )
+ return;
+
+ text_size = _glutBitmapWidthString( glui->font, name );
+
+ /* if ( w < text_x_offset + text_size + 6 ) */
+ w = text_x_offset + text_size + 6 ;
+}
+
+
+/************************* GLUI_RadioButton::draw_active_area() **************/
+
+void GLUI_RadioButton::draw_active_area( void )
+{
+ int text_width, left, right, orig;
+
+ if ( NOT can_draw() )
+ return;
+
+ orig = set_to_glut_window();
+
+ text_width = _glutBitmapWidthString( glui->font, name );
+ left = text_x_offset-3;
+ right = left + 7 + text_width;
+
+ if ( active ) {
+ glEnable( GL_LINE_STIPPLE );
+ glLineStipple( 1, 0x5555 );
+ glColor3f( 0., 0., 0. );
+ } else {
+ glColor3ub( glui->bkgd_color.r, glui->bkgd_color.g, glui->bkgd_color.b );
+ }
+
+ glBegin( GL_LINE_LOOP );
+ glVertex2i(left,0); glVertex2i( right,0);
+ glVertex2i(right,h+1); glVertex2i( left,h+1);
+ glEnd();
+
+ glDisable( GL_LINE_STIPPLE );
+
+ restore_window(orig);
+}
+
+
+/********************************* GLUI_RadioGroup::set_int_val() **********/
+
+void GLUI_RadioGroup::set_int_val( int new_val )
+{
+ if ( new_val == int_val )
+ return;
+
+ set_selected( new_val );
+ draw_group( true );
+
+ output_live(true);
+
+}
Index: external/trimesh/gluit/glui_bitmaps.cc
--- external/trimesh/gluit/glui_bitmaps.cc (revision 0)
+++ external/trimesh/gluit/glui_bitmaps.cc (revision 0)
@@ -0,0 +1,104 @@
+/****************************************************************************
+
+ GLUI User Interface Toolkit
+ ---------------------------
+
+ glui_bitmaps.cpp
+
+
+ --------------------------------------------------
+
+ Copyright (c) 1998 Paul Rademacher
+
+ This program is freely distributable without licensing fees and is
+ provided without guarantee or warrantee expressed or implied. This
+ program is -not- in the public domain.
+
+*****************************************************************************/
+
+#include "glui.h"
+#include "glui_stdinc.h"
+
+int *bitmap_arrays[] = {
+ glui_img_checkbox_0,
+ glui_img_checkbox_1,
+ glui_img_radiobutton_0,
+ glui_img_radiobutton_1,
+ glui_img_uparrow,
+ glui_img_downarrow,
+ glui_img_leftarrow,
+ glui_img_rightarrow,
+ glui_img_spinup_0,
+ glui_img_spinup_1,
+ glui_img_spindown_0,
+ glui_img_spindown_1,
+ glui_img_checkbox_0_dis,
+ glui_img_checkbox_1_dis,
+ glui_img_radiobutton_0_dis,
+ glui_img_radiobutton_1_dis,
+ glui_img_spinup_dis,
+ glui_img_spindown_dis,
+ glui_img_listbox_up,
+ glui_img_listbox_down,
+ glui_img_listbox_up_dis,
+};
+
+
+/************************************ GLUI_Bitmap::load_from_array() ********/
+
+void GLUI_Bitmap::load_from_array( int *array )
+{
+ int i;
+
+ w = 0;
+ h = 0;
+
+ if ( array == NULL )
+ return;
+
+ w = array[0];
+ h = array[1];
+
+ pixels = (unsigned char*) malloc( sizeof(unsigned char) * w * h * 3);
+
+ for( i = 0; i<w*h*3; i++ )
+ pixels[i] = (unsigned char) array[i+2];
+}
+
+
+/*********************************** GLUI_StdBitmaps::draw() *****************/
+
+void GLUI_StdBitmaps::draw( int bitmap_num, int x, int y )
+{
+ // int i;
+
+ if ( bitmaps[bitmap_num].pixels != NULL ) {
+ glRasterPos2f( (float)x+.5, (float)y + (float)bitmaps[bitmap_num].h + .5);
+ glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
+
+ glDrawPixels( bitmaps[bitmap_num].w, bitmaps[bitmap_num].h,
+ GL_RGB, GL_UNSIGNED_BYTE, bitmaps[bitmap_num].pixels );
+
+ /* printf( "%d %d %d %d %d %d %d\n",
+ bitmaps[bitmap_num].w, bitmaps[bitmap_num].h, 0, 0, 0, 0,
+ bitmaps[bitmap_num].pixels );
+
+ for( i=0; i<bitmaps[bitmap_num].w*bitmaps[bitmap_num].h*3; i++ ) {
+ printf( "%d ", bitmaps[bitmap_num].pixels[i] );
+ }
+ printf( "\n" );
+ */
+ /* for( i=0; i<bitmaps[bitmap_num].w; i++ ) {
+ for( j=0; j<bitmaps[bitmap_num].h; j++ ) {
+ if ( bitmaps[bitmap_num].pixels[(i+j*bitmaps[bitmap_num].w)*3]
+ > 128 )
+ putchar( '#' );
+ else
+ putchar( ' ' );
+ }
+ putchar( '\n' );
+ }
+ fflush( stdout );
+ */
+ }
+}
Index: external/trimesh/gluit/glui_rollout.cc
--- external/trimesh/gluit/glui_rollout.cc (revision 0)
+++ external/trimesh/gluit/glui_rollout.cc (revision 0)
@@ -0,0 +1,286 @@
+/****************************************************************************
+
+ GLUI User Interface Toolkit
+ ---------------------------
+
+ glui_panel.cpp - GLUI_Panel control class
+
+
+ --------------------------------------------------
+
+ Copyright (c) 1998 Paul Rademacher
+
+ This program is freely distributable without licensing fees and is
+ provided without guarantee or warrantee expressed or implied. This
+ program is -not- in the public domain.
+
+*****************************************************************************/
+
+#include "glui.h"
+#include "glui_stdinc.h"
+
+/****************************** GLUI_Rollout::open() **********/
+
+void GLUI_Rollout::open( void )
+{
+ int orig;
+
+ if ( NOT glui )
+ return;
+
+ if ( is_open )
+ return;
+
+ is_open = true;
+
+ orig = set_to_glut_window();
+
+ child_head = collapsed_node.child_head;
+ child_tail = collapsed_node.child_tail;
+
+ collapsed_node.child_head = NULL;
+ collapsed_node.child_tail = NULL;
+
+ if ( child_head != NULL ) {
+ ((GLUI_Control*) child_head)->unhide_internal( true );
+ }
+
+ glui->refresh();
+
+ restore_window(orig);
+}
+
+
+/****************************** GLUI_Rollout::close() **********/
+
+void GLUI_Rollout::close( void )
+{
+ int orig;
+
+ if ( NOT glui )
+ return;
+
+ if ( NOT is_open )
+ return;
+
+ orig = set_to_glut_window();
+
+ if ( child_head != NULL ) {
+ ((GLUI_Control*) child_head)->hide_internal( true );
+ }
+
+ collapsed_node.child_head = first_child();
+ collapsed_node.child_tail = last_child();
+
+ child_head = NULL;
+ child_tail = NULL;
+
+ restore_window(orig);
+
+ this->h = GLUI_DEFAULT_CONTROL_HEIGHT + 7;
+
+ is_open = false;
+
+ glui->refresh();
+}
+
+
+/**************************** GLUI_Rollout::mouse_down_handler() **********/
+
+
+int GLUI_Rollout::mouse_down_handler( int local_x, int local_y )
+{
+ if ( local_y - y_abs > 18 ) {
+ initially_inside = currently_inside = false;
+ return false;
+ }
+
+ currently_inside = true;
+ initially_inside = true;
+
+ draw_pressed();
+
+ return false;
+}
+
+
+/**************************** GLUI_Rollout::mouse_down_handler() **********/
+
+int GLUI_Rollout::mouse_up_handler( int local_x, int local_y, int inside )
+{
+ draw_unpressed();
+
+ if ( currently_inside ) {
+ if ( is_open )
+ close();
+ else
+ open();
+ }
+
+ initially_inside = false;
+
+ return false;
+}
+
+
+/********************************* GLUI_Rollout::draw() ***********/
+
+void GLUI_Rollout::draw( int x, int y )
+{
+ int orig, left, right, top, bottom;
+
+ if ( NOT can_draw() )
+ return;
+
+ orig = set_to_glut_window();
+
+ left = 5;
+ right = w-left;
+ top = 3;
+ bottom = 3+16;
+
+ if ( is_open )
+ draw_emboss_box( 0, w, top+3, h );
+ else
+ draw_emboss_box( 0, w, top+3, h-7 );
+
+ glui->draw_raised_box( left, top, w-left*2, 16 );
+
+ if ( glui )
+ glColor3ub(glui->bkgd_color.r,glui->bkgd_color.g,glui->bkgd_color.b);
+ glDisable( GL_CULL_FACE );
+ glBegin( GL_QUADS );
+ glVertex2i( left+1, top+1 ); glVertex2i( right-1, top+1 );
+ glVertex2i( right-1, bottom-1 ); glVertex2i( left+1, bottom-1 );
+ glEnd();
+
+ draw_name( left+8, top+11 );
+
+ if ( active )
+ /*draw_active_box( left+4, left+string_width( name.string )+12, */
+ draw_active_box( left+4, right-17,
+ top+2, bottom-2 );
+
+
+ /** Draw '+' or '-' **/
+
+ glBegin( GL_LINES );
+ if ( is_open ) {
+ if ( enabled ) glColor3f( 0.0, 0.0, 0.0 );
+ else glColor3f( 0.5, 0.5, 0.5 );
+ glVertex2i(right-14,(top+bottom)/2); glVertex2i(right-5,(top+bottom)/2);
+
+ glColor3f( 1.0, 1.0, 1.0 );
+ glVertex2i(right-14,1+(top+bottom)/2);glVertex2i(right-5,1+(top+bottom)/2);
+ }
+ else
+ {
+ glColor3f( 1.0, 1.0, 1.0 );
+ glVertex2i(right-9,top+3); glVertex2i(right-9,bottom-4);
+ glVertex2i(right-14,(top+bottom)/2); glVertex2i(right-5,(top+bottom)/2);
+
+ if ( enabled ) glColor3f( 0.0, 0.0, 0.0 );
+ else glColor3f( 0.5, 0.5, 0.5 );
+ glVertex2i(right-14,-1+(top+bottom)/2);
+ glVertex2i(right-5,-1+(top+bottom)/2);
+ glVertex2i(right-10,top+3);
+ glVertex2i(right-10,bottom-4);
+ }
+ glEnd();
+
+ glLineWidth( 1.0 );
+
+ restore_window(orig);
+}
+
+
+/***************************** GLUI_Rollout::update_size() **********/
+
+void GLUI_Rollout::update_size( void )
+{
+ int text_size;
+
+ if ( NOT glui )
+ return;
+
+ text_size = string_width(name);
+
+ if ( w < text_size + 36 )
+ w = text_size + 36;
+}
+
+
+/**************************** GLUI_Rollout::draw_pressed() ***********/
+
+void GLUI_Rollout::draw_pressed( void )
+{
+ int state, orig;
+ int left, right, top, bottom;
+
+ left = 5;
+ right = w-left;
+ top = 3;
+ bottom = 3+16;
+
+ if ( NOT can_draw() )
+ return;
+
+ orig = set_to_glut_window();
+ state = glui->set_front_draw_buffer();
+
+ glColor3f( 0.0, 0.0, 0.0 );
+ glPushMatrix();
+ translate_to_origin();
+
+ glBegin( GL_LINE_LOOP );
+ glVertex2i( left, top ); glVertex2i( right, top );
+ glVertex2i( right, bottom ); glVertex2i( left,bottom );
+ glEnd();
+
+ glBegin( GL_LINE_LOOP );
+ glVertex2i( left+1, top+1 ); glVertex2i( right-1, top+1 );
+ glVertex2i( right-1, bottom-1 ); glVertex2i( left+1,bottom-1 );
+ glEnd();
+
+ glPopMatrix();
+
+ glui->restore_draw_buffer(state);
+ restore_window(orig);
+
+}
+
+
+/**************************** GLUI_Rollout::draw_unpressed() ***********/
+
+void GLUI_Rollout::draw_unpressed( void )
+{
+ if ( NOT can_draw() )
+ return;
+
+ translate_and_draw_front();
+}
+
+
+/**************************** GLUI_Rollout::mouse_held_down_handler() ****/
+
+int GLUI_Rollout::mouse_held_down_handler(
+ int local_x, int local_y,
+ int new_inside )
+{
+ if ( NOT initially_inside )
+ return false;
+
+ if ( local_y - y_abs> 18 )
+ new_inside = false;
+
+ if ( NOT new_inside AND currently_inside == true ) {
+ draw_unpressed();
+ }
+ else if ( new_inside AND currently_inside == false ) {
+ draw_pressed();
+ }
+
+ currently_inside = new_inside;
+
+ return false;
+}
Index: external/trimesh/gluit/glui_arcball.cc
--- external/trimesh/gluit/glui_arcball.cc (revision 0)
+++ external/trimesh/gluit/glui_arcball.cc (revision 0)
@@ -0,0 +1,223 @@
+/**********************************************************************
+
+ arcball.cpp
+
+
+ --------------------------------------------------
+
+ Copyright (c) 1998 Paul Rademacher
+
+ This program is freely distributable without licensing fees and is
+ provided without guarantee or warrantee expressed or implied. This
+ program is -not- in the public domain.
+
+**********************************************************************/
+
+
+#include "glui_arcball.h"
+#include <stdio.h>
+
+
+/**************************************** Arcball::Arcball() ****/
+/* Default (void) constructor for Arcball */
+
+Arcball::Arcball( void )
+{
+ rot_ptr = &rot;
+
+ init();
+}
+
+
+/**************************************** Arcball::Arcball() ****/
+/* Takes as argument a mat4 to use instead of the internal rot */
+
+Arcball::Arcball( mat4 *mtx )
+{
+ rot_ptr = mtx;
+}
+
+
+/**************************************** Arcball::Arcball() ****/
+/* A constructor that accepts the screen center and arcball radius*/
+
+Arcball::Arcball( vec2 _center, float _radius )
+{
+ rot_ptr = &rot;
+
+ init();
+ set_params( _center, _radius );
+}
+
+
+/************************************** Arcball::set_params() ****/
+
+void Arcball::set_params( vec2 _center, float _radius )
+{
+ center = _center;
+ radius = _radius;
+}
+
+
+/*************************************** Arcball::init() **********/
+
+void Arcball::init( void )
+{
+ center.set( 0.0, 0.0 );
+ radius = 1.0;
+ q_now = quat_identity();
+ *rot_ptr = identity3D();
+ q_increment = quat_identity();
+ rot_increment = identity3D();
+ is_mouse_down = false;
+ is_spinning = false;
+ damp_factor = 0.0;
+ zero_increment = true;
+}
+
+
+/*********************************** Arcball::mouse_to_sphere() ****/
+
+vec3 Arcball::mouse_to_sphere( vec2 p )
+{
+ float mag;
+ vec2 v2 = (p - center) / radius;
+ vec3 v3( v2[0], v2[1], 0.0 );
+
+ mag = v2*v2;
+
+ if ( mag > 1.0 ) {
+ v3.normalize();
+ }
+ else {
+ v3[VZ] = sqrt( 1.0 - mag );
+ }
+
+ /* Now we add constraints - X takes precedence over Y */
+ if ( constraint_x ) {
+ v3 = constrain_vector( v3, vec3( 1.0, 0.0, 0.0 ));
+ } else if ( constraint_y ) {
+ v3 = constrain_vector( v3, vec3( 0.0, 1.0, 0.0 ));
+ }
+
+ return v3;
+}
+
+
+/************************************ Arcball::constrain_vector() ****/
+
+vec3 Arcball::constrain_vector( vec3 vector, vec3 axis )
+{
+ return (vector-(vector*axis)*axis).normalize();
+}
+
+/************************************ Arcball::mouse_down() **********/
+
+void Arcball::mouse_down( int x, int y )
+{
+ down_pt.set( (float)x, (float) y );
+ is_mouse_down = true;
+
+ q_increment = quat_identity();
+ rot_increment = identity3D();
+ zero_increment = true;
+}
+
+
+/************************************ Arcball::mouse_up() **********/
+
+void Arcball::mouse_up( void )
+{
+ q_now = q_drag * q_now;
+ is_mouse_down = false;
+}
+
+
+/********************************** Arcball::mouse_motion() **********/
+
+void Arcball::mouse_motion( int x, int y, int shift, int ctrl, int alt )
+{
+ /* Set the X constraint if CONTROL key is pressed, Y if ALT key */
+ set_constraints( ctrl != 0, alt != 0 );
+
+ vec2 new_pt( (float)x, (float) y );
+ vec3 v0 = mouse_to_sphere( down_pt );
+ vec3 v1 = mouse_to_sphere( new_pt );
+
+ vec3 cross = v0^v1;
+
+ q_drag.set( cross, v0 * v1 );
+
+ // *rot_ptr = (q_drag * q_now).to_mat4();
+ mat4 temp = q_drag.to_mat4();
+ *rot_ptr = (*rot_ptr) * temp;
+
+ down_pt = new_pt;
+
+ /* We keep a copy of the current incremental rotation (= q_drag) */
+ q_increment = q_drag;
+ rot_increment = q_increment.to_mat4();
+
+ set_constraints( false, false );
+
+ if ( q_increment.s < .999999 ) {
+ is_spinning = true;
+
+ zero_increment = false;
+ }
+ else {
+ is_spinning = false;
+ zero_increment = true;
+ }
+}
+
+
+/********************************** Arcball::mouse_motion() **********/
+
+void Arcball::mouse_motion( int x, int y )
+{
+ mouse_motion( x, y, 0, 0, 0 );
+}
+
+
+/***************************** Arcball::set_constraints() **********/
+
+void Arcball::set_constraints( Bool _constraint_x, Bool _constraint_y )
+{
+ constraint_x = _constraint_x;
+ constraint_y = _constraint_y;
+}
+
+/***************************** Arcball::idle() *********************/
+
+void Arcball::idle( void )
+{
+ if ( is_mouse_down ) {
+ is_spinning = false;
+ zero_increment = true;
+ }
+
+ if ( damp_factor < 1.0 ) {
+ q_increment.scale_angle( 1.0 - damp_factor );
+ }
+
+ rot_increment = q_increment.to_mat4();
+
+ if ( q_increment.s >= .999999 ) {
+ is_spinning = false;
+ zero_increment = true;
+ }
+}
+
+
+/************************ Arcball::set_damping() *********************/
+
+void Arcball::set_damping( float d )
+{
+ damp_factor = d;
+}
+
+
+
+
+
Index: external/trimesh/gluit/glui_img_radiobutton_1_dis.c
--- external/trimesh/gluit/glui_img_radiobutton_1_dis.c (revision 0)
+++ external/trimesh/gluit/glui_img_radiobutton_1_dis.c (revision 0)
@@ -0,0 +1,44 @@
+
+
+int glui_img_radiobutton_1_dis[] = { 14, 14, /* width, height */
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 255,255,255,
+ 255,255,255, 255,255,255, 255,255,255, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 255,255,255, 255,255,255, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 255,255,255, 255,255,255, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 128,128,128,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 255,255,255, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 128,128,128, 64, 64, 64,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 255,255,255, 192,192,192, 192,192,192,
+ 192,192,192, 128,128,128, 64, 64, 64, 192,192,192, 192,192,192,
+ 192,192,192, 64, 64, 64, 64, 64, 64, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 255,255,255, 192,192,192, 192,192,192,
+ 128,128,128, 64, 64, 64, 192,192,192, 192,192,192, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 192,192,192, 192,192,192,
+ 192,192,192, 255,255,255, 192,192,192, 192,192,192, 128,128,128,
+ 64, 64, 64, 192,192,192, 192,192,192, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 192,192,192, 192,192,192, 192,192,192,
+ 255,255,255, 192,192,192, 192,192,192, 128,128,128, 64, 64, 64,
+ 192,192,192, 192,192,192, 192,192,192, 64, 64, 64, 64, 64, 64,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 255,255,255,
+ 192,192,192, 192,192,192, 192,192,192, 128,128,128, 64, 64, 64,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 255,255,255, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 128,128,128, 64, 64, 64, 64, 64, 64,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 64, 64, 64,
+ 64, 64, 64, 255,255,255, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 128,128,128, 128,128,128, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 128,128,128, 128,128,128,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 128,128,128, 128,128,128,
+ 128,128,128, 128,128,128, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192, 192,192,192, 192,192,192, 192,192,192, 192,192,192,
+ 192,192,192,
+};
Index: external/trimesh/gluit/freeglut_stroke_mono_roman.c
--- external/trimesh/gluit/freeglut_stroke_mono_roman.c (revision 0)
+++ external/trimesh/gluit/freeglut_stroke_mono_roman.c (revision 0)
@@ -0,0 +1,2821 @@
+
+/* This file has been automatically generated by the genstroke utility. */
+
+#include "freeglut_internal.h"
+
+/* char: 0x20 */
+
+static const SFG_StrokeStrip ch32st[] =
+{
+ { 0, NULL }
+};
+
+static const SFG_StrokeChar ch32 = {104.762f,0,ch32st};
+
+/* char: 0x21 */
+
+static const SFG_StrokeVertex ch33st0[] =
+{
+ {52.381f,100.0f},
+ {52.381f,33.3333f}
+};
+
+static const SFG_StrokeVertex ch33st1[] =
+{
+ {52.381f,9.5238f},
+ {47.6191f,4.7619f},
+ {52.381f,0.0f},
+ {57.1429f,4.7619f},
+ {52.381f,9.5238f}
+};
+
+static const SFG_StrokeStrip ch33st[] =
+{
+ {2,ch33st0},
+ {5,ch33st1}
+};
+
+static const SFG_StrokeChar ch33 = {104.762f,2,ch33st};
+
+/* char: 0x22 */
+
+static const SFG_StrokeVertex ch34st0[] =
+{
+ {33.3334f,100.0f},
+ {33.3334f,66.6667f}
+};
+
+static const SFG_StrokeVertex ch34st1[] =
+{
+ {71.4286f,100.0f},
+ {71.4286f,66.6667f}
+};
+
+static const SFG_StrokeStrip ch34st[] =
+{
+ {2,ch34st0},
+ {2,ch34st1}
+};
+
+static const SFG_StrokeChar ch34 = {104.762f,2,ch34st};
+
+/* char: 0x23 */
+
+static const SFG_StrokeVertex ch35st0[] =
+{
+ {54.7619f,119.048f},
+ {21.4286f,-33.3333f}
+};
+
+static const SFG_StrokeVertex ch35st1[] =
+{
+ {83.3334f,119.048f},
+ {50.0f,-33.3333f}
+};
+
+static const SFG_StrokeVertex ch35st2[] =
+{
+ {21.4286f,57.1429f},
+ {88.0952f,57.1429f}
+};
+
+static const SFG_StrokeVertex ch35st3[] =
+{
+ {16.6667f,28.5714f},
+ {83.3334f,28.5714f}
+};
+
+static const SFG_StrokeStrip ch35st[] =
+{
+ {2,ch35st0},
+ {2,ch35st1},
+ {2,ch35st2},
+ {2,ch35st3}
+};
+
+static const SFG_StrokeChar ch35 = {104.762f,4,ch35st};
+
+/* char: 0x24 */
+
+static const SFG_StrokeVertex ch36st0[] =
+{
+ {42.8571f,119.048f},
+ {42.8571f,-19.0476f}
+};
+
+static const SFG_StrokeVertex ch36st1[] =
+{
+ {61.9047f,119.048f},
+ {61.9047f,-19.0476f}
+};
+
+static const SFG_StrokeVertex ch36st2[] =
+{
+ {85.7143f,85.7143f},
+ {76.1905f,95.2381f},
+ {61.9047f,100.0f},
+ {42.8571f,100.0f},
+ {28.5714f,95.2381f},
+ {19.0476f,85.7143f},
+ {19.0476f,76.1905f},
+ {23.8095f,66.6667f},
+ {28.5714f,61.9048f},
+ {38.0952f,57.1429f},
+ {66.6666f,47.619f},
+ {76.1905f,42.8571f},
+ {80.9524f,38.0952f},
+ {85.7143f,28.5714f},
+ {85.7143f,14.2857f},
+ {76.1905f,4.7619f},
+ {61.9047f,0.0f},
+ {42.8571f,0.0f},
+ {28.5714f,4.7619f},
+ {19.0476f,14.2857f}
+};
+
+static const SFG_StrokeStrip ch36st[] =
+{
+ {2,ch36st0},
+ {2,ch36st1},
+ {20,ch36st2}
+};
+
+static const SFG_StrokeChar ch36 = {104.762f,3,ch36st};
+
+/* char: 0x25 */
+
+static const SFG_StrokeVertex ch37st0[] =
+{
+ {95.2381f,100.0f},
+ {9.5238f,0.0f}
+};
+
+static const SFG_StrokeVertex ch37st1[] =
+{
+ {33.3333f,100.0f},
+ {42.8571f,90.4762f},
+ {42.8571f,80.9524f},
+ {38.0952f,71.4286f},
+ {28.5714f,66.6667f},
+ {19.0476f,66.6667f},
+ {9.5238f,76.1905f},
+ {9.5238f,85.7143f},
+ {14.2857f,95.2381f},
+ {23.8095f,100.0f},
+ {33.3333f,100.0f},
+ {42.8571f,95.2381f},
+ {57.1428f,90.4762f},
+ {71.4286f,90.4762f},
+ {85.7143f,95.2381f},
+ {95.2381f,100.0f}
+};
+
+static const SFG_StrokeVertex ch37st2[] =
+{
+ {76.1905f,33.3333f},
+ {66.6667f,28.5714f},
+ {61.9048f,19.0476f},
+ {61.9048f,9.5238f},
+ {71.4286f,0.0f},
+ {80.9524f,0.0f},
+ {90.4762f,4.7619f},
+ {95.2381f,14.2857f},
+ {95.2381f,23.8095f},
+ {85.7143f,33.3333f},
+ {76.1905f,33.3333f}
+};
+
+static const SFG_StrokeStrip ch37st[] =
+{
+ {2,ch37st0},
+ {16,ch37st1},
+ {11,ch37st2}
+};
+
+static const SFG_StrokeChar ch37 = {104.762f,3,ch37st};
+
+/* char: 0x26 */
+
+static const SFG_StrokeVertex ch38st0[] =
+{
+ {100.0f,57.1429f},
+ {100.0f,61.9048f},
+ {95.2381f,66.6667f},
+ {90.4762f,66.6667f},
+ {85.7143f,61.9048f},
+ {80.9524f,52.381f},
+ {71.4286f,28.5714f},
+ {61.9048f,14.2857f},
+ {52.3809f,4.7619f},
+ {42.8571f,0.0f},
+ {23.8095f,0.0f},
+ {14.2857f,4.7619f},
+ {9.5238f,9.5238f},
+ {4.7619f,19.0476f},
+ {4.7619f,28.5714f},
+ {9.5238f,38.0952f},
+ {14.2857f,42.8571f},
+ {47.619f,61.9048f},
+ {52.3809f,66.6667f},
+ {57.1429f,76.1905f},
+ {57.1429f,85.7143f},
+ {52.3809f,95.2381f},
+ {42.8571f,100.0f},
+ {33.3333f,95.2381f},
+ {28.5714f,85.7143f},
+ {28.5714f,76.1905f},
+ {33.3333f,61.9048f},
+ {42.8571f,47.619f},
+ {66.6667f,14.2857f},
+ {76.1905f,4.7619f},
+ {85.7143f,0.0f},
+ {95.2381f,0.0f},
+ {100.0f,4.7619f},
+ {100.0f,9.5238f}
+};
+
+static const SFG_StrokeStrip ch38st[] =
+{
+ {34,ch38st0}
+};
+
+static const SFG_StrokeChar ch38 = {104.762f,1,ch38st};
+
+/* char: 0x27 */
+
+static const SFG_StrokeVertex ch39st0[] =
+{
+ {52.381f,100.0f},
+ {52.381f,66.6667f}
+};
+
+static const SFG_StrokeStrip ch39st[] =
+{
+ {2,ch39st0}
+};
+
+static const SFG_StrokeChar ch39 = {104.762f,1,ch39st};
+
+/* char: 0x28 */
+
+static const SFG_StrokeVertex ch40st0[] =
+{
+ {69.0476f,119.048f},
+ {59.5238f,109.524f},
+ {50.0f,95.2381f},
+ {40.4762f,76.1905f},
+ {35.7143f,52.381f},
+ {35.7143f,33.3333f},
+ {40.4762f,9.5238f},
+ {50.0f,-9.5238f},
+ {59.5238f,-23.8095f},
+ {69.0476f,-33.3333f}
+};
+
+static const SFG_StrokeStrip ch40st[] =
+{
+ {10,ch40st0}
+};
+
+static const SFG_StrokeChar ch40 = {104.762f,1,ch40st};
+
+/* char: 0x29 */
+
+static const SFG_StrokeVertex ch41st0[] =
+{
+ {35.7143f,119.048f},
+ {45.2381f,109.524f},
+ {54.7619f,95.2381f},
+ {64.2857f,76.1905f},
+ {69.0476f,52.381f},
+ {69.0476f,33.3333f},
+ {64.2857f,9.5238f},
+ {54.7619f,-9.5238f},
+ {45.2381f,-23.8095f},
+ {35.7143f,-33.3333f}
+};
+
+static const SFG_StrokeStrip ch41st[] =
+{
+ {10,ch41st0}
+};
+
+static const SFG_StrokeChar ch41 = {104.762f,1,ch41st};
+
+/* char: 0x2a */
+
+static const SFG_StrokeVertex ch42st0[] =
+{
+ {52.381f,71.4286f},
+ {52.381f,14.2857f}
+};
+
+static const SFG_StrokeVertex ch42st1[] =
+{
+ {28.5715f,57.1429f},
+ {76.1905f,28.5714f}
+};
+
+static const SFG_StrokeVertex ch42st2[] =
+{
+ {76.1905f,57.1429f},
+ {28.5715f,28.5714f}
+};
+
+static const SFG_StrokeStrip ch42st[] =
+{
+ {2,ch42st0},
+ {2,ch42st1},
+ {2,ch42st2}
+};
+
+static const SFG_StrokeChar ch42 = {104.762f,3,ch42st};
+
+/* char: 0x2b */
+
+static const SFG_StrokeVertex ch43st0[] =
+{
+ {52.3809f,85.7143f},
+ {52.3809f,0.0f}
+};
+
+static const SFG_StrokeVertex ch43st1[] =
+{
+ {9.5238f,42.8571f},
+ {95.2381f,42.8571f}
+};
+
+static const SFG_StrokeStrip ch43st[] =
+{
+ {2,ch43st0},
+ {2,ch43st1}
+};
+
+static const SFG_StrokeChar ch43 = {104.762f,2,ch43st};
+
+/* char: 0x2c */
+
+static const SFG_StrokeVertex ch44st0[] =
+{
+ {57.1429f,4.7619f},
+ {52.381f,0.0f},
+ {47.6191f,4.7619f},
+ {52.381f,9.5238f},
+ {57.1429f,4.7619f},
+ {57.1429f,-4.7619f},
+ {52.381f,-14.2857f},
+ {47.6191f,-19.0476f}
+};
+
+static const SFG_StrokeStrip ch44st[] =
+{
+ {8,ch44st0}
+};
+
+static const SFG_StrokeChar ch44 = {104.762f,1,ch44st};
+
+/* char: 0x2d */
+
+static const SFG_StrokeVertex ch45st0[] =
+{
+ {9.5238f,42.8571f},
+ {95.2381f,42.8571f}
+};
+
+static const SFG_StrokeStrip ch45st[] =
+{
+ {2,ch45st0}
+};
+
+static const SFG_StrokeChar ch45 = {104.762f,1,ch45st};
+
+/* char: 0x2e */
+
+static const SFG_StrokeVertex ch46st0[] =
+{
+ {52.381f,9.5238f},
+ {47.6191f,4.7619f},
+ {52.381f,0.0f},
+ {57.1429f,4.7619f},
+ {52.381f,9.5238f}
+};
+
+static const SFG_StrokeStrip ch46st[] =
+{
+ {5,ch46st0}
+};
+
+static const SFG_StrokeChar ch46 = {104.762f,1,ch46st};
+
+/* char: 0x2f */
+
+static const SFG_StrokeVertex ch47st0[] =
+{
+ {19.0476f,-14.2857f},
+ {85.7143f,100.0f}
+};
+
+static const SFG_StrokeStrip ch47st[] =
+{
+ {2,ch47st0}
+};
+
+static const SFG_StrokeChar ch47 = {104.762f,1,ch47st};
+
+/* char: 0x30 */
+
+static const SFG_StrokeVertex ch48st0[] =
+{
+ {47.619f,100.0f},
+ {33.3333f,95.2381f},
+ {23.8095f,80.9524f},
+ {19.0476f,57.1429f},
+ {19.0476f,42.8571f},
+ {23.8095f,19.0476f},
+ {33.3333f,4.7619f},
+ {47.619f,0.0f},
+ {57.1428f,0.0f},
+ {71.4286f,4.7619f},
+ {80.9524f,19.0476f},
+ {85.7143f,42.8571f},
+ {85.7143f,57.1429f},
+ {80.9524f,80.9524f},
+ {71.4286f,95.2381f},
+ {57.1428f,100.0f},
+ {47.619f,100.0f}
+};
+
+static const SFG_StrokeStrip ch48st[] =
+{
+ {17,ch48st0}
+};
+
+static const SFG_StrokeChar ch48 = {104.762f,1,ch48st};
+
+/* char: 0x31 */
+
+static const SFG_StrokeVertex ch49st0[] =
+{
+ {40.4762f,80.9524f},
+ {50.0f,85.7143f},
+ {64.2857f,100.0f},
+ {64.2857f,0.0f}
+};
+
+static const SFG_StrokeStrip ch49st[] =
+{
+ {4,ch49st0}
+};
+
+static const SFG_StrokeChar ch49 = {104.762f,1,ch49st};
+
+/* char: 0x32 */
+
+static const SFG_StrokeVertex ch50st0[] =
+{
+ {23.8095f,76.1905f},
+ {23.8095f,80.9524f},
+ {28.5714f,90.4762f},
+ {33.3333f,95.2381f},
+ {42.8571f,100.0f},
+ {61.9047f,100.0f},
+ {71.4286f,95.2381f},
+ {76.1905f,90.4762f},
+ {80.9524f,80.9524f},
+ {80.9524f,71.4286f},
+ {76.1905f,61.9048f},
+ {66.6666f,47.619f},
+ {19.0476f,0.0f},
+ {85.7143f,0.0f}
+};
+
+static const SFG_StrokeStrip ch50st[] =
+{
+ {14,ch50st0}
+};
+
+static const SFG_StrokeChar ch50 = {104.762f,1,ch50st};
+
+/* char: 0x33 */
+
+static const SFG_StrokeVertex ch51st0[] =
+{
+ {28.5714f,100.0f},
+ {80.9524f,100.0f},
+ {52.3809f,61.9048f},
+ {66.6666f,61.9048f},
+ {76.1905f,57.1429f},
+ {80.9524f,52.381f},
+ {85.7143f,38.0952f},
+ {85.7143f,28.5714f},
+ {80.9524f,14.2857f},
+ {71.4286f,4.7619f},
+ {57.1428f,0.0f},
+ {42.8571f,0.0f},
+ {28.5714f,4.7619f},
+ {23.8095f,9.5238f},
+ {19.0476f,19.0476f}
+};
+
+static const SFG_StrokeStrip ch51st[] =
+{
+ {15,ch51st0}
+};
+
+static const SFG_StrokeChar ch51 = {104.762f,1,ch51st};
+
+/* char: 0x34 */
+
+static const SFG_StrokeVertex ch52st0[] =
+{
+ {64.2857f,100.0f},
+ {16.6667f,33.3333f},
+ {88.0952f,33.3333f}
+};
+
+static const SFG_StrokeVertex ch52st1[] =
+{
+ {64.2857f,100.0f},
+ {64.2857f,0.0f}
+};
+
+static const SFG_StrokeStrip ch52st[] =
+{
+ {3,ch52st0},
+ {2,ch52st1}
+};
+
+static const SFG_StrokeChar ch52 = {104.762f,2,ch52st};
+
+/* char: 0x35 */
+
+static const SFG_StrokeVertex ch53st0[] =
+{
+ {76.1905f,100.0f},
+ {28.5714f,100.0f},
+ {23.8095f,57.1429f},
+ {28.5714f,61.9048f},
+ {42.8571f,66.6667f},
+ {57.1428f,66.6667f},
+ {71.4286f,61.9048f},
+ {80.9524f,52.381f},
+ {85.7143f,38.0952f},
+ {85.7143f,28.5714f},
+ {80.9524f,14.2857f},
+ {71.4286f,4.7619f},
+ {57.1428f,0.0f},
+ {42.8571f,0.0f},
+ {28.5714f,4.7619f},
+ {23.8095f,9.5238f},
+ {19.0476f,19.0476f}
+};
+
+static const SFG_StrokeStrip ch53st[] =
+{
+ {17,ch53st0}
+};
+
+static const SFG_StrokeChar ch53 = {104.762f,1,ch53st};
+
+/* char: 0x36 */
+
+static const SFG_StrokeVertex ch54st0[] =
+{
+ {78.5714f,85.7143f},
+ {73.8096f,95.2381f},
+ {59.5238f,100.0f},
+ {50.0f,100.0f},
+ {35.7143f,95.2381f},
+ {26.1905f,80.9524f},
+ {21.4286f,57.1429f},
+ {21.4286f,33.3333f},
+ {26.1905f,14.2857f},
+ {35.7143f,4.7619f},
+ {50.0f,0.0f},
+ {54.7619f,0.0f},
+ {69.0476f,4.7619f},
+ {78.5714f,14.2857f},
+ {83.3334f,28.5714f},
+ {83.3334f,33.3333f},
+ {78.5714f,47.619f},
+ {69.0476f,57.1429f},
+ {54.7619f,61.9048f},
+ {50.0f,61.9048f},
+ {35.7143f,57.1429f},
+ {26.1905f,47.619f},
+ {21.4286f,33.3333f}
+};
+
+static const SFG_StrokeStrip ch54st[] =
+{
+ {23,ch54st0}
+};
+
+static const SFG_StrokeChar ch54 = {104.762f,1,ch54st};
+
+/* char: 0x37 */
+
+static const SFG_StrokeVertex ch55st0[] =
+{
+ {85.7143f,100.0f},
+ {38.0952f,0.0f}
+};
+
+static const SFG_StrokeVertex ch55st1[] =
+{
+ {19.0476f,100.0f},
+ {85.7143f,100.0f}
+};
+
+static const SFG_StrokeStrip ch55st[] =
+{
+ {2,ch55st0},
+ {2,ch55st1}
+};
+
+static const SFG_StrokeChar ch55 = {104.762f,2,ch55st};
+
+/* char: 0x38 */
+
+static const SFG_StrokeVertex ch56st0[] =
+{
+ {42.8571f,100.0f},
+ {28.5714f,95.2381f},
+ {23.8095f,85.7143f},
+ {23.8095f,76.1905f},
+ {28.5714f,66.6667f},
+ {38.0952f,61.9048f},
+ {57.1428f,57.1429f},
+ {71.4286f,52.381f},
+ {80.9524f,42.8571f},
+ {85.7143f,33.3333f},
+ {85.7143f,19.0476f},
+ {80.9524f,9.5238f},
+ {76.1905f,4.7619f},
+ {61.9047f,0.0f},
+ {42.8571f,0.0f},
+ {28.5714f,4.7619f},
+ {23.8095f,9.5238f},
+ {19.0476f,19.0476f},
+ {19.0476f,33.3333f},
+ {23.8095f,42.8571f},
+ {33.3333f,52.381f},
+ {47.619f,57.1429f},
+ {66.6666f,61.9048f},
+ {76.1905f,66.6667f},
+ {80.9524f,76.1905f},
+ {80.9524f,85.7143f},
+ {76.1905f,95.2381f},
+ {61.9047f,100.0f},
+ {42.8571f,100.0f}
+};
+
+static const SFG_StrokeStrip ch56st[] =
+{
+ {29,ch56st0}
+};
+
+static const SFG_StrokeChar ch56 = {104.762f,1,ch56st};
+
+/* char: 0x39 */
+
+static const SFG_StrokeVertex ch57st0[] =
+{
+ {83.3334f,66.6667f},
+ {78.5714f,52.381f},
+ {69.0476f,42.8571f},
+ {54.7619f,38.0952f},
+ {50.0f,38.0952f},
+ {35.7143f,42.8571f},
+ {26.1905f,52.381f},
+ {21.4286f,66.6667f},
+ {21.4286f,71.4286f},
+ {26.1905f,85.7143f},
+ {35.7143f,95.2381f},
+ {50.0f,100.0f},
+ {54.7619f,100.0f},
+ {69.0476f,95.2381f},
+ {78.5714f,85.7143f},
+ {83.3334f,66.6667f},
+ {83.3334f,42.8571f},
+ {78.5714f,19.0476f},
+ {69.0476f,4.7619f},
+ {54.7619f,0.0f},
+ {45.2381f,0.0f},
+ {30.9524f,4.7619f},
+ {26.1905f,14.2857f}
+};
+
+static const SFG_StrokeStrip ch57st[] =
+{
+ {23,ch57st0}
+};
+
+static const SFG_StrokeChar ch57 = {104.762f,1,ch57st};
+
+/* char: 0x3a */
+
+static const SFG_StrokeVertex ch58st0[] =
+{
+ {52.381f,66.6667f},
+ {47.6191f,61.9048f},
+ {52.381f,57.1429f},
+ {57.1429f,61.9048f},
+ {52.381f,66.6667f}
+};
+
+static const SFG_StrokeVertex ch58st1[] =
+{
+ {52.381f,9.5238f},
+ {47.6191f,4.7619f},
+ {52.381f,0.0f},
+ {57.1429f,4.7619f},
+ {52.381f,9.5238f}
+};
+
+static const SFG_StrokeStrip ch58st[] =
+{
+ {5,ch58st0},
+ {5,ch58st1}
+};
+
+static const SFG_StrokeChar ch58 = {104.762f,2,ch58st};
+
+/* char: 0x3b */
+
+static const SFG_StrokeVertex ch59st0[] =
+{
+ {52.381f,66.6667f},
+ {47.6191f,61.9048f},
+ {52.381f,57.1429f},
+ {57.1429f,61.9048f},
+ {52.381f,66.6667f}
+};
+
+static const SFG_StrokeVertex ch59st1[] =
+{
+ {57.1429f,4.7619f},
+ {52.381f,0.0f},
+ {47.6191f,4.7619f},
+ {52.381f,9.5238f},
+ {57.1429f,4.7619f},
+ {57.1429f,-4.7619f},
+ {52.381f,-14.2857f},
+ {47.6191f,-19.0476f}
+};
+
+static const SFG_StrokeStrip ch59st[] =
+{
+ {5,ch59st0},
+ {8,ch59st1}
+};
+
+static const SFG_StrokeChar ch59 = {104.762f,2,ch59st};
+
+/* char: 0x3c */
+
+static const SFG_StrokeVertex ch60st0[] =
+{
+ {90.4762f,85.7143f},
+ {14.2857f,42.8571f},
+ {90.4762f,0.0f}
+};
+
+static const SFG_StrokeStrip ch60st[] =
+{
+ {3,ch60st0}
+};
+
+static const SFG_StrokeChar ch60 = {104.762f,1,ch60st};
+
+/* char: 0x3d */
+
+static const SFG_StrokeVertex ch61st0[] =
+{
+ {9.5238f,57.1429f},
+ {95.2381f,57.1429f}
+};
+
+static const SFG_StrokeVertex ch61st1[] =
+{
+ {9.5238f,28.5714f},
+ {95.2381f,28.5714f}
+};
+
+static const SFG_StrokeStrip ch61st[] =
+{
+ {2,ch61st0},
+ {2,ch61st1}
+};
+
+static const SFG_StrokeChar ch61 = {104.762f,2,ch61st};
+
+/* char: 0x3e */
+
+static const SFG_StrokeVertex ch62st0[] =
+{
+ {14.2857f,85.7143f},
+ {90.4762f,42.8571f},
+ {14.2857f,0.0f}
+};
+
+static const SFG_StrokeStrip ch62st[] =
+{
+ {3,ch62st0}
+};
+
+static const SFG_StrokeChar ch62 = {104.762f,1,ch62st};
+
+/* char: 0x3f */
+
+static const SFG_StrokeVertex ch63st0[] =
+{
+ {23.8095f,76.1905f},
+ {23.8095f,80.9524f},
+ {28.5714f,90.4762f},
+ {33.3333f,95.2381f},
+ {42.8571f,100.0f},
+ {61.9047f,100.0f},
+ {71.4285f,95.2381f},
+ {76.1905f,90.4762f},
+ {80.9524f,80.9524f},
+ {80.9524f,71.4286f},
+ {76.1905f,61.9048f},
+ {71.4285f,57.1429f},
+ {52.3809f,47.619f},
+ {52.3809f,33.3333f}
+};
+
+static const SFG_StrokeVertex ch63st1[] =
+{
+ {52.3809f,9.5238f},
+ {47.619f,4.7619f},
+ {52.3809f,0.0f},
+ {57.1428f,4.7619f},
+ {52.3809f,9.5238f}
+};
+
+static const SFG_StrokeStrip ch63st[] =
+{
+ {14,ch63st0},
+ {5,ch63st1}
+};
+
+static const SFG_StrokeChar ch63 = {104.762f,2,ch63st};
+
+/* char: 0x40 */
+
+static const SFG_StrokeVertex ch64st0[] =
+{
+ {64.2857f,52.381f},
+ {54.7619f,57.1429f},
+ {45.2381f,57.1429f},
+ {40.4762f,47.619f},
+ {40.4762f,42.8571f},
+ {45.2381f,33.3333f},
+ {54.7619f,33.3333f},
+ {64.2857f,38.0952f}
+};
+
+static const SFG_StrokeVertex ch64st1[] =
+{
+ {64.2857f,57.1429f},
+ {64.2857f,38.0952f},
+ {69.0476f,33.3333f},
+ {78.5714f,33.3333f},
+ {83.3334f,42.8571f},
+ {83.3334f,47.619f},
+ {78.5714f,61.9048f},
+ {69.0476f,71.4286f},
+ {54.7619f,76.1905f},
+ {50.0f,76.1905f},
+ {35.7143f,71.4286f},
+ {26.1905f,61.9048f},
+ {21.4286f,47.619f},
+ {21.4286f,42.8571f},
+ {26.1905f,28.5714f},
+ {35.7143f,19.0476f},
+ {50.0f,14.2857f},
+ {54.7619f,14.2857f},
+ {69.0476f,19.0476f}
+};
+
+static const SFG_StrokeStrip ch64st[] =
+{
+ {8,ch64st0},
+ {19,ch64st1}
+};
+
+static const SFG_StrokeChar ch64 = {104.762f,2,ch64st};
+
+/* char: 0x41 */
+
+static const SFG_StrokeVertex ch65st0[] =
+{
+ {52.3809f,100.0f},
+ {14.2857f,0.0f}
+};
+
+static const SFG_StrokeVertex ch65st1[] =
+{
+ {52.3809f,100.0f},
+ {90.4762f,0.0f}
+};
+
+static const SFG_StrokeVertex ch65st2[] =
+{
+ {28.5714f,33.3333f},
+ {76.1905f,33.3333f}
+};
+
+static const SFG_StrokeStrip ch65st[] =
+{
+ {2,ch65st0},
+ {2,ch65st1},
+ {2,ch65st2}
+};
+
+static const SFG_StrokeChar ch65 = {104.762f,3,ch65st};
+
+/* char: 0x42 */
+
+static const SFG_StrokeVertex ch66st0[] =
+{
+ {19.0476f,100.0f},
+ {19.0476f,0.0f}
+};
+
+static const SFG_StrokeVertex ch66st1[] =
+{
+ {19.0476f,100.0f},
+ {61.9047f,100.0f},
+ {76.1905f,95.2381f},
+ {80.9524f,90.4762f},
+ {85.7143f,80.9524f},
+ {85.7143f,71.4286f},
+ {80.9524f,61.9048f},
+ {76.1905f,57.1429f},
+ {61.9047f,52.381f}
+};
+
+static const SFG_StrokeVertex ch66st2[] =
+{
+ {19.0476f,52.381f},
+ {61.9047f,52.381f},
+ {76.1905f,47.619f},
+ {80.9524f,42.8571f},
+ {85.7143f,33.3333f},
+ {85.7143f,19.0476f},
+ {80.9524f,9.5238f},
+ {76.1905f,4.7619f},
+ {61.9047f,0.0f},
+ {19.0476f,0.0f}
+};
+
+static const SFG_StrokeStrip ch66st[] =
+{
+ {2,ch66st0},
+ {9,ch66st1},
+ {10,ch66st2}
+};
+
+static const SFG_StrokeChar ch66 = {104.762f,3,ch66st};
+
+/* char: 0x43 */
+
+static const SFG_StrokeVertex ch67st0[] =
+{
+ {88.0952f,76.1905f},
+ {83.3334f,85.7143f},
+ {73.8096f,95.2381f},
+ {64.2857f,100.0f},
+ {45.2381f,100.0f},
+ {35.7143f,95.2381f},
+ {26.1905f,85.7143f},
+ {21.4286f,76.1905f},
+ {16.6667f,61.9048f},
+ {16.6667f,38.0952f},
+ {21.4286f,23.8095f},
+ {26.1905f,14.2857f},
+ {35.7143f,4.7619f},
+ {45.2381f,0.0f},
+ {64.2857f,0.0f},
+ {73.8096f,4.7619f},
+ {83.3334f,14.2857f},
+ {88.0952f,23.8095f}
+};
+
+static const SFG_StrokeStrip ch67st[] =
+{
+ {18,ch67st0}
+};
+
+static const SFG_StrokeChar ch67 = {104.762f,1,ch67st};
+
+/* char: 0x44 */
+
+static const SFG_StrokeVertex ch68st0[] =
+{
+ {19.0476f,100.0f},
+ {19.0476f,0.0f}
+};
+
+static const SFG_StrokeVertex ch68st1[] =
+{
+ {19.0476f,100.0f},
+ {52.3809f,100.0f},
+ {66.6666f,95.2381f},
+ {76.1905f,85.7143f},
+ {80.9524f,76.1905f},
+ {85.7143f,61.9048f},
+ {85.7143f,38.0952f},
+ {80.9524f,23.8095f},
+ {76.1905f,14.2857f},
+ {66.6666f,4.7619f},
+ {52.3809f,0.0f},
+ {19.0476f,0.0f}
+};
+
+static const SFG_StrokeStrip ch68st[] =
+{
+ {2,ch68st0},
+ {12,ch68st1}
+};
+
+static const SFG_StrokeChar ch68 = {104.762f,2,ch68st};
+
+/* char: 0x45 */
+
+static const SFG_StrokeVertex ch69st0[] =
+{
+ {21.4286f,100.0f},
+ {21.4286f,0.0f}
+};
+
+static const SFG_StrokeVertex ch69st1[] =
+{
+ {21.4286f,100.0f},
+ {83.3334f,100.0f}
+};
+
+static const SFG_StrokeVertex ch69st2[] =
+{
+ {21.4286f,52.381f},
+ {59.5238f,52.381f}
+};
+
+static const SFG_StrokeVertex ch69st3[] =
+{
+ {21.4286f,0.0f},
+ {83.3334f,0.0f}
+};
+
+static const SFG_StrokeStrip ch69st[] =
+{
+ {2,ch69st0},
+ {2,ch69st1},
+ {2,ch69st2},
+ {2,ch69st3}
+};
+
+static const SFG_StrokeChar ch69 = {104.762f,4,ch69st};
+
+/* char: 0x46 */
+
+static const SFG_StrokeVertex ch70st0[] =
+{
+ {21.4286f,100.0f},
+ {21.4286f,0.0f}
+};
+
+static const SFG_StrokeVertex ch70st1[] =
+{
+ {21.4286f,100.0f},
+ {83.3334f,100.0f}
+};
+
+static const SFG_StrokeVertex ch70st2[] =
+{
+ {21.4286f,52.381f},
+ {59.5238f,52.381f}
+};
+
+static const SFG_StrokeStrip ch70st[] =
+{
+ {2,ch70st0},
+ {2,ch70st1},
+ {2,ch70st2}
+};
+
+static const SFG_StrokeChar ch70 = {104.762f,3,ch70st};
+
+/* char: 0x47 */
+
+static const SFG_StrokeVertex ch71st0[] =
+{
+ {88.0952f,76.1905f},
+ {83.3334f,85.7143f},
+ {73.8096f,95.2381f},
+ {64.2857f,100.0f},
+ {45.2381f,100.0f},
+ {35.7143f,95.2381f},
+ {26.1905f,85.7143f},
+ {21.4286f,76.1905f},
+ {16.6667f,61.9048f},
+ {16.6667f,38.0952f},
+ {21.4286f,23.8095f},
+ {26.1905f,14.2857f},
+ {35.7143f,4.7619f},
+ {45.2381f,0.0f},
+ {64.2857f,0.0f},
+ {73.8096f,4.7619f},
+ {83.3334f,14.2857f},
+ {88.0952f,23.8095f},
+ {88.0952f,38.0952f}
+};
+
+static const SFG_StrokeVertex ch71st1[] =
+{
+ {64.2857f,38.0952f},
+ {88.0952f,38.0952f}
+};
+
+static const SFG_StrokeStrip ch71st[] =
+{
+ {19,ch71st0},
+ {2,ch71st1}
+};
+
+static const SFG_StrokeChar ch71 = {104.762f,2,ch71st};
+
+/* char: 0x48 */
+
+static const SFG_StrokeVertex ch72st0[] =
+{
+ {19.0476f,100.0f},
+ {19.0476f,0.0f}
+};
+
+static const SFG_StrokeVertex ch72st1[] =
+{
+ {85.7143f,100.0f},
+ {85.7143f,0.0f}
+};
+
+static const SFG_StrokeVertex ch72st2[] =
+{
+ {19.0476f,52.381f},
+ {85.7143f,52.381f}
+};
+
+static const SFG_StrokeStrip ch72st[] =
+{
+ {2,ch72st0},
+ {2,ch72st1},
+ {2,ch72st2}
+};
+
+static const SFG_StrokeChar ch72 = {104.762f,3,ch72st};
+
+/* char: 0x49 */
+
+static const SFG_StrokeVertex ch73st0[] =
+{
+ {52.381f,100.0f},
+ {52.381f,0.0f}
+};
+
+static const SFG_StrokeStrip ch73st[] =
+{
+ {2,ch73st0}
+};
+
+static const SFG_StrokeChar ch73 = {104.762f,1,ch73st};
+
+/* char: 0x4a */
+
+static const SFG_StrokeVertex ch74st0[] =
+{
+ {76.1905f,100.0f},
+ {76.1905f,23.8095f},
+ {71.4286f,9.5238f},
+ {66.6667f,4.7619f},
+ {57.1429f,0.0f},
+ {47.6191f,0.0f},
+ {38.0953f,4.7619f},
+ {33.3334f,9.5238f},
+ {28.5715f,23.8095f},
+ {28.5715f,33.3333f}
+};
+
+static const SFG_StrokeStrip ch74st[] =
+{
+ {10,ch74st0}
+};
+
+static const SFG_StrokeChar ch74 = {104.762f,1,ch74st};
+
+/* char: 0x4b */
+
+static const SFG_StrokeVertex ch75st0[] =
+{
+ {19.0476f,100.0f},
+ {19.0476f,0.0f}
+};
+
+static const SFG_StrokeVertex ch75st1[] =
+{
+ {85.7143f,100.0f},
+ {19.0476f,33.3333f}
+};
+
+static const SFG_StrokeVertex ch75st2[] =
+{
+ {42.8571f,57.1429f},
+ {85.7143f,0.0f}
+};
+
+static const SFG_StrokeStrip ch75st[] =
+{
+ {2,ch75st0},
+ {2,ch75st1},
+ {2,ch75st2}
+};
+
+static const SFG_StrokeChar ch75 = {104.762f,3,ch75st};
+
+/* char: 0x4c */
+
+static const SFG_StrokeVertex ch76st0[] =
+{
+ {23.8095f,100.0f},
+ {23.8095f,0.0f}
+};
+
+static const SFG_StrokeVertex ch76st1[] =
+{
+ {23.8095f,0.0f},
+ {80.9524f,0.0f}
+};
+
+static const SFG_StrokeStrip ch76st[] =
+{
+ {2,ch76st0},
+ {2,ch76st1}
+};
+
+static const SFG_StrokeChar ch76 = {104.762f,2,ch76st};
+
+/* char: 0x4d */
+
+static const SFG_StrokeVertex ch77st0[] =
+{
+ {14.2857f,100.0f},
+ {14.2857f,0.0f}
+};
+
+static const SFG_StrokeVertex ch77st1[] =
+{
+ {14.2857f,100.0f},
+ {52.3809f,0.0f}
+};
+
+static const SFG_StrokeVertex ch77st2[] =
+{
+ {90.4762f,100.0f},
+ {52.3809f,0.0f}
+};
+
+static const SFG_StrokeVertex ch77st3[] =
+{
+ {90.4762f,100.0f},
+ {90.4762f,0.0f}
+};
+
+static const SFG_StrokeStrip ch77st[] =
+{
+ {2,ch77st0},
+ {2,ch77st1},
+ {2,ch77st2},
+ {2,ch77st3}
+};
+
+static const SFG_StrokeChar ch77 = {104.762f,4,ch77st};
+
+/* char: 0x4e */
+
+static const SFG_StrokeVertex ch78st0[] =
+{
+ {19.0476f,100.0f},
+ {19.0476f,0.0f}
+};
+
+static const SFG_StrokeVertex ch78st1[] =
+{
+ {19.0476f,100.0f},
+ {85.7143f,0.0f}
+};
+
+static const SFG_StrokeVertex ch78st2[] =
+{
+ {85.7143f,100.0f},
+ {85.7143f,0.0f}
+};
+
+static const SFG_StrokeStrip ch78st[] =
+{
+ {2,ch78st0},
+ {2,ch78st1},
+ {2,ch78st2}
+};
+
+static const SFG_StrokeChar ch78 = {104.762f,3,ch78st};
+
+/* char: 0x4f */
+
+static const SFG_StrokeVertex ch79st0[] =
+{
+ {42.8571f,100.0f},
+ {33.3333f,95.2381f},
+ {23.8095f,85.7143f},
+ {19.0476f,76.1905f},
+ {14.2857f,61.9048f},
+ {14.2857f,38.0952f},
+ {19.0476f,23.8095f},
+ {23.8095f,14.2857f},
+ {33.3333f,4.7619f},
+ {42.8571f,0.0f},
+ {61.9047f,0.0f},
+ {71.4286f,4.7619f},
+ {80.9524f,14.2857f},
+ {85.7143f,23.8095f},
+ {90.4762f,38.0952f},
+ {90.4762f,61.9048f},
+ {85.7143f,76.1905f},
+ {80.9524f,85.7143f},
+ {71.4286f,95.2381f},
+ {61.9047f,100.0f},
+ {42.8571f,100.0f}
+};
+
+static const SFG_StrokeStrip ch79st[] =
+{
+ {21,ch79st0}
+};
+
+static const SFG_StrokeChar ch79 = {104.762f,1,ch79st};
+
+/* char: 0x50 */
+
+static const SFG_StrokeVertex ch80st0[] =
+{
+ {19.0476f,100.0f},
+ {19.0476f,0.0f}
+};
+
+static const SFG_StrokeVertex ch80st1[] =
+{
+ {19.0476f,100.0f},
+ {61.9047f,100.0f},
+ {76.1905f,95.2381f},
+ {80.9524f,90.4762f},
+ {85.7143f,80.9524f},
+ {85.7143f,66.6667f},
+ {80.9524f,57.1429f},
+ {76.1905f,52.381f},
+ {61.9047f,47.619f},
+ {19.0476f,47.619f}
+};
+
+static const SFG_StrokeStrip ch80st[] =
+{
+ {2,ch80st0},
+ {10,ch80st1}
+};
+
+static const SFG_StrokeChar ch80 = {104.762f,2,ch80st};
+
+/* char: 0x51 */
+
+static const SFG_StrokeVertex ch81st0[] =
+{
+ {42.8571f,100.0f},
+ {33.3333f,95.2381f},
+ {23.8095f,85.7143f},
+ {19.0476f,76.1905f},
+ {14.2857f,61.9048f},
+ {14.2857f,38.0952f},
+ {19.0476f,23.8095f},
+ {23.8095f,14.2857f},
+ {33.3333f,4.7619f},
+ {42.8571f,0.0f},
+ {61.9047f,0.0f},
+ {71.4286f,4.7619f},
+ {80.9524f,14.2857f},
+ {85.7143f,23.8095f},
+ {90.4762f,38.0952f},
+ {90.4762f,61.9048f},
+ {85.7143f,76.1905f},
+ {80.9524f,85.7143f},
+ {71.4286f,95.2381f},
+ {61.9047f,100.0f},
+ {42.8571f,100.0f}
+};
+
+static const SFG_StrokeVertex ch81st1[] =
+{
+ {57.1428f,19.0476f},
+ {85.7143f,-9.5238f}
+};
+
+static const SFG_StrokeStrip ch81st[] =
+{
+ {21,ch81st0},
+ {2,ch81st1}
+};
+
+static const SFG_StrokeChar ch81 = {104.762f,2,ch81st};
+
+/* char: 0x52 */
+
+static const SFG_StrokeVertex ch82st0[] =
+{
+ {19.0476f,100.0f},
+ {19.0476f,0.0f}
+};
+
+static const SFG_StrokeVertex ch82st1[] =
+{
+ {19.0476f,100.0f},
+ {61.9047f,100.0f},
+ {76.1905f,95.2381f},
+ {80.9524f,90.4762f},
+ {85.7143f,80.9524f},
+ {85.7143f,71.4286f},
+ {80.9524f,61.9048f},
+ {76.1905f,57.1429f},
+ {61.9047f,52.381f},
+ {19.0476f,52.381f}
+};
+
+static const SFG_StrokeVertex ch82st2[] =
+{
+ {52.3809f,52.381f},
+ {85.7143f,0.0f}
+};
+
+static const SFG_StrokeStrip ch82st[] =
+{
+ {2,ch82st0},
+ {10,ch82st1},
+ {2,ch82st2}
+};
+
+static const SFG_StrokeChar ch82 = {104.762f,3,ch82st};
+
+/* char: 0x53 */
+
+static const SFG_StrokeVertex ch83st0[] =
+{
+ {85.7143f,85.7143f},
+ {76.1905f,95.2381f},
+ {61.9047f,100.0f},
+ {42.8571f,100.0f},
+ {28.5714f,95.2381f},
+ {19.0476f,85.7143f},
+ {19.0476f,76.1905f},
+ {23.8095f,66.6667f},
+ {28.5714f,61.9048f},
+ {38.0952f,57.1429f},
+ {66.6666f,47.619f},
+ {76.1905f,42.8571f},
+ {80.9524f,38.0952f},
+ {85.7143f,28.5714f},
+ {85.7143f,14.2857f},
+ {76.1905f,4.7619f},
+ {61.9047f,0.0f},
+ {42.8571f,0.0f},
+ {28.5714f,4.7619f},
+ {19.0476f,14.2857f}
+};
+
+static const SFG_StrokeStrip ch83st[] =
+{
+ {20,ch83st0}
+};
+
+static const SFG_StrokeChar ch83 = {104.762f,1,ch83st};
+
+/* char: 0x54 */
+
+static const SFG_StrokeVertex ch84st0[] =
+{
+ {52.3809f,100.0f},
+ {52.3809f,0.0f}
+};
+
+static const SFG_StrokeVertex ch84st1[] =
+{
+ {19.0476f,100.0f},
+ {85.7143f,100.0f}
+};
+
+static const SFG_StrokeStrip ch84st[] =
+{
+ {2,ch84st0},
+ {2,ch84st1}
+};
+
+static const SFG_StrokeChar ch84 = {104.762f,2,ch84st};
+
+/* char: 0x55 */
+
+static const SFG_StrokeVertex ch85st0[] =
+{
+ {19.0476f,100.0f},
+ {19.0476f,28.5714f},
+ {23.8095f,14.2857f},
+ {33.3333f,4.7619f},
+ {47.619f,0.0f},
+ {57.1428f,0.0f},
+ {71.4286f,4.7619f},
+ {80.9524f,14.2857f},
+ {85.7143f,28.5714f},
+ {85.7143f,100.0f}
+};
+
+static const SFG_StrokeStrip ch85st[] =
+{
+ {10,ch85st0}
+};
+
+static const SFG_StrokeChar ch85 = {104.762f,1,ch85st};
+
+/* char: 0x56 */
+
+static const SFG_StrokeVertex ch86st0[] =
+{
+ {14.2857f,100.0f},
+ {52.3809f,0.0f}
+};
+
+static const SFG_StrokeVertex ch86st1[] =
+{
+ {90.4762f,100.0f},
+ {52.3809f,0.0f}
+};
+
+static const SFG_StrokeStrip ch86st[] =
+{
+ {2,ch86st0},
+ {2,ch86st1}
+};
+
+static const SFG_StrokeChar ch86 = {104.762f,2,ch86st};
+
+/* char: 0x57 */
+
+static const SFG_StrokeVertex ch87st0[] =
+{
+ {4.7619f,100.0f},
+ {28.5714f,0.0f}
+};
+
+static const SFG_StrokeVertex ch87st1[] =
+{
+ {52.3809f,100.0f},
+ {28.5714f,0.0f}
+};
+
+static const SFG_StrokeVertex ch87st2[] =
+{
+ {52.3809f,100.0f},
+ {76.1905f,0.0f}
+};
+
+static const SFG_StrokeVertex ch87st3[] =
+{
+ {100.0f,100.0f},
+ {76.1905f,0.0f}
+};
+
+static const SFG_StrokeStrip ch87st[] =
+{
+ {2,ch87st0},
+ {2,ch87st1},
+ {2,ch87st2},
+ {2,ch87st3}
+};
+
+static const SFG_StrokeChar ch87 = {104.762f,4,ch87st};
+
+/* char: 0x58 */
+
+static const SFG_StrokeVertex ch88st0[] =
+{
+ {19.0476f,100.0f},
+ {85.7143f,0.0f}
+};
+
+static const SFG_StrokeVertex ch88st1[] =
+{
+ {85.7143f,100.0f},
+ {19.0476f,0.0f}
+};
+
+static const SFG_StrokeStrip ch88st[] =
+{
+ {2,ch88st0},
+ {2,ch88st1}
+};
+
+static const SFG_StrokeChar ch88 = {104.762f,2,ch88st};
+
+/* char: 0x59 */
+
+static const SFG_StrokeVertex ch89st0[] =
+{
+ {14.2857f,100.0f},
+ {52.3809f,52.381f},
+ {52.3809f,0.0f}
+};
+
+static const SFG_StrokeVertex ch89st1[] =
+{
+ {90.4762f,100.0f},
+ {52.3809f,52.381f}
+};
+
+static const SFG_StrokeStrip ch89st[] =
+{
+ {3,ch89st0},
+ {2,ch89st1}
+};
+
+static const SFG_StrokeChar ch89 = {104.762f,2,ch89st};
+
+/* char: 0x5a */
+
+static const SFG_StrokeVertex ch90st0[] =
+{
+ {85.7143f,100.0f},
+ {19.0476f,0.0f}
+};
+
+static const SFG_StrokeVertex ch90st1[] =
+{
+ {19.0476f,100.0f},
+ {85.7143f,100.0f}
+};
+
+static const SFG_StrokeVertex ch90st2[] =
+{
+ {19.0476f,0.0f},
+ {85.7143f,0.0f}
+};
+
+static const SFG_StrokeStrip ch90st[] =
+{
+ {2,ch90st0},
+ {2,ch90st1},
+ {2,ch90st2}
+};
+
+static const SFG_StrokeChar ch90 = {104.762f,3,ch90st};
+
+/* char: 0x5b */
+
+static const SFG_StrokeVertex ch91st0[] =
+{
+ {35.7143f,119.048f},
+ {35.7143f,-33.3333f}
+};
+
+static const SFG_StrokeVertex ch91st1[] =
+{
+ {40.4762f,119.048f},
+ {40.4762f,-33.3333f}
+};
+
+static const SFG_StrokeVertex ch91st2[] =
+{
+ {35.7143f,119.048f},
+ {69.0476f,119.048f}
+};
+
+static const SFG_StrokeVertex ch91st3[] =
+{
+ {35.7143f,-33.3333f},
+ {69.0476f,-33.3333f}
+};
+
+static const SFG_StrokeStrip ch91st[] =
+{
+ {2,ch91st0},
+ {2,ch91st1},
+ {2,ch91st2},
+ {2,ch91st3}
+};
+
+static const SFG_StrokeChar ch91 = {104.762f,4,ch91st};
+
+/* char: 0x5c */
+
+static const SFG_StrokeVertex ch92st0[] =
+{
+ {19.0476f,100.0f},
+ {85.7143f,-14.2857f}
+};
+
+static const SFG_StrokeStrip ch92st[] =
+{
+ {2,ch92st0}
+};
+
+static const SFG_StrokeChar ch92 = {104.762f,1,ch92st};
+
+/* char: 0x5d */
+
+static const SFG_StrokeVertex ch93st0[] =
+{
+ {64.2857f,119.048f},
+ {64.2857f,-33.3333f}
+};
+
+static const SFG_StrokeVertex ch93st1[] =
+{
+ {69.0476f,119.048f},
+ {69.0476f,-33.3333f}
+};
+
+static const SFG_StrokeVertex ch93st2[] =
+{
+ {35.7143f,119.048f},
+ {69.0476f,119.048f}
+};
+
+static const SFG_StrokeVertex ch93st3[] =
+{
+ {35.7143f,-33.3333f},
+ {69.0476f,-33.3333f}
+};
+
+static const SFG_StrokeStrip ch93st[] =
+{
+ {2,ch93st0},
+ {2,ch93st1},
+ {2,ch93st2},
+ {2,ch93st3}
+};
+
+static const SFG_StrokeChar ch93 = {104.762f,4,ch93st};
+
+/* char: 0x5e */
+
+static const SFG_StrokeVertex ch94st0[] =
+{
+ {52.3809f,109.524f},
+ {14.2857f,42.8571f}
+};
+
+static const SFG_StrokeVertex ch94st1[] =
+{
+ {52.3809f,109.524f},
+ {90.4762f,42.8571f}
+};
+
+static const SFG_StrokeStrip ch94st[] =
+{
+ {2,ch94st0},
+ {2,ch94st1}
+};
+
+static const SFG_StrokeChar ch94 = {104.762f,2,ch94st};
+
+/* char: 0x5f */
+
+static const SFG_StrokeVertex ch95st0[] =
+{
+ {0,-33.3333f},
+ {104.762f,-33.3333f},
+ {104.762f,-28.5714f},
+ {0,-28.5714f},
+ {0,-33.3333f}
+};
+
+static const SFG_StrokeStrip ch95st[] =
+{
+ {5,ch95st0}
+};
+
+static const SFG_StrokeChar ch95 = {104.762f,1,ch95st};
+
+/* char: 0x60 */
+
+static const SFG_StrokeVertex ch96st0[] =
+{
+ {42.8572f,100.0f},
+ {66.6667f,71.4286f}
+};
+
+static const SFG_StrokeVertex ch96st1[] =
+{
+ {42.8572f,100.0f},
+ {38.0953f,95.2381f},
+ {66.6667f,71.4286f}
+};
+
+static const SFG_StrokeStrip ch96st[] =
+{
+ {2,ch96st0},
+ {3,ch96st1}
+};
+
+static const SFG_StrokeChar ch96 = {104.762f,2,ch96st};
+
+/* char: 0x61 */
+
+static const SFG_StrokeVertex ch97st0[] =
+{
+ {80.9524f,66.6667f},
+ {80.9524f,0.0f}
+};
+
+static const SFG_StrokeVertex ch97st1[] =
+{
+ {80.9524f,52.381f},
+ {71.4285f,61.9048f},
+ {61.9047f,66.6667f},
+ {47.619f,66.6667f},
+ {38.0952f,61.9048f},
+ {28.5714f,52.381f},
+ {23.8095f,38.0952f},
+ {23.8095f,28.5714f},
+ {28.5714f,14.2857f},
+ {38.0952f,4.7619f},
+ {47.619f,0.0f},
+ {61.9047f,0.0f},
+ {71.4285f,4.7619f},
+ {80.9524f,14.2857f}
+};
+
+static const SFG_StrokeStrip ch97st[] =
+{
+ {2,ch97st0},
+ {14,ch97st1}
+};
+
+static const SFG_StrokeChar ch97 = {104.762f,2,ch97st};
+
+/* char: 0x62 */
+
+static const SFG_StrokeVertex ch98st0[] =
+{
+ {23.8095f,100.0f},
+ {23.8095f,0.0f}
+};
+
+static const SFG_StrokeVertex ch98st1[] =
+{
+ {23.8095f,52.381f},
+ {33.3333f,61.9048f},
+ {42.8571f,66.6667f},
+ {57.1428f,66.6667f},
+ {66.6666f,61.9048f},
+ {76.1905f,52.381f},
+ {80.9524f,38.0952f},
+ {80.9524f,28.5714f},
+ {76.1905f,14.2857f},
+ {66.6666f,4.7619f},
+ {57.1428f,0.0f},
+ {42.8571f,0.0f},
+ {33.3333f,4.7619f},
+ {23.8095f,14.2857f}
+};
+
+static const SFG_StrokeStrip ch98st[] =
+{
+ {2,ch98st0},
+ {14,ch98st1}
+};
+
+static const SFG_StrokeChar ch98 = {104.762f,2,ch98st};
+
+/* char: 0x63 */
+
+static const SFG_StrokeVertex ch99st0[] =
+{
+ {80.9524f,52.381f},
+ {71.4285f,61.9048f},
+ {61.9047f,66.6667f},
+ {47.619f,66.6667f},
+ {38.0952f,61.9048f},
+ {28.5714f,52.381f},
+ {23.8095f,38.0952f},
+ {23.8095f,28.5714f},
+ {28.5714f,14.2857f},
+ {38.0952f,4.7619f},
+ {47.619f,0.0f},
+ {61.9047f,0.0f},
+ {71.4285f,4.7619f},
+ {80.9524f,14.2857f}
+};
+
+static const SFG_StrokeStrip ch99st[] =
+{
+ {14,ch99st0}
+};
+
+static const SFG_StrokeChar ch99 = {104.762f,1,ch99st};
+
+/* char: 0x64 */
+
+static const SFG_StrokeVertex ch100st0[] =
+{
+ {80.9524f,100.0f},
+ {80.9524f,0.0f}
+};
+
+static const SFG_StrokeVertex ch100st1[] =
+{
+ {80.9524f,52.381f},
+ {71.4285f,61.9048f},
+ {61.9047f,66.6667f},
+ {47.619f,66.6667f},
+ {38.0952f,61.9048f},
+ {28.5714f,52.381f},
+ {23.8095f,38.0952f},
+ {23.8095f,28.5714f},
+ {28.5714f,14.2857f},
+ {38.0952f,4.7619f},
+ {47.619f,0.0f},
+ {61.9047f,0.0f},
+ {71.4285f,4.7619f},
+ {80.9524f,14.2857f}
+};
+
+static const SFG_StrokeStrip ch100st[] =
+{
+ {2,ch100st0},
+ {14,ch100st1}
+};
+
+static const SFG_StrokeChar ch100 = {104.762f,2,ch100st};
+
+/* char: 0x65 */
+
+static const SFG_StrokeVertex ch101st0[] =
+{
+ {23.8095f,38.0952f},
+ {80.9524f,38.0952f},
+ {80.9524f,47.619f},
+ {76.1905f,57.1429f},
+ {71.4285f,61.9048f},
+ {61.9047f,66.6667f},
+ {47.619f,66.6667f},
+ {38.0952f,61.9048f},
+ {28.5714f,52.381f},
+ {23.8095f,38.0952f},
+ {23.8095f,28.5714f},
+ {28.5714f,14.2857f},
+ {38.0952f,4.7619f},
+ {47.619f,0.0f},
+ {61.9047f,0.0f},
+ {71.4285f,4.7619f},
+ {80.9524f,14.2857f}
+};
+
+static const SFG_StrokeStrip ch101st[] =
+{
+ {17,ch101st0}
+};
+
+static const SFG_StrokeChar ch101 = {104.762f,1,ch101st};
+
+/* char: 0x66 */
+
+static const SFG_StrokeVertex ch102st0[] =
+{
+ {71.4286f,100.0f},
+ {61.9048f,100.0f},
+ {52.381f,95.2381f},
+ {47.6191f,80.9524f},
+ {47.6191f,0.0f}
+};
+
+static const SFG_StrokeVertex ch102st1[] =
+{
+ {33.3334f,66.6667f},
+ {66.6667f,66.6667f}
+};
+
+static const SFG_StrokeStrip ch102st[] =
+{
+ {5,ch102st0},
+ {2,ch102st1}
+};
+
+static const SFG_StrokeChar ch102 = {104.762f,2,ch102st};
+
+/* char: 0x67 */
+
+static const SFG_StrokeVertex ch103st0[] =
+{
+ {80.9524f,66.6667f},
+ {80.9524f,-9.5238f},
+ {76.1905f,-23.8095f},
+ {71.4285f,-28.5714f},
+ {61.9047f,-33.3333f},
+ {47.619f,-33.3333f},
+ {38.0952f,-28.5714f}
+};
+
+static const SFG_StrokeVertex ch103st1[] =
+{
+ {80.9524f,52.381f},
+ {71.4285f,61.9048f},
+ {61.9047f,66.6667f},
+ {47.619f,66.6667f},
+ {38.0952f,61.9048f},
+ {28.5714f,52.381f},
+ {23.8095f,38.0952f},
+ {23.8095f,28.5714f},
+ {28.5714f,14.2857f},
+ {38.0952f,4.7619f},
+ {47.619f,0.0f},
+ {61.9047f,0.0f},
+ {71.4285f,4.7619f},
+ {80.9524f,14.2857f}
+};
+
+static const SFG_StrokeStrip ch103st[] =
+{
+ {7,ch103st0},
+ {14,ch103st1}
+};
+
+static const SFG_StrokeChar ch103 = {104.762f,2,ch103st};
+
+/* char: 0x68 */
+
+static const SFG_StrokeVertex ch104st0[] =
+{
+ {26.1905f,100.0f},
+ {26.1905f,0.0f}
+};
+
+static const SFG_StrokeVertex ch104st1[] =
+{
+ {26.1905f,47.619f},
+ {40.4762f,61.9048f},
+ {50.0f,66.6667f},
+ {64.2857f,66.6667f},
+ {73.8095f,61.9048f},
+ {78.5715f,47.619f},
+ {78.5715f,0.0f}
+};
+
+static const SFG_StrokeStrip ch104st[] =
+{
+ {2,ch104st0},
+ {7,ch104st1}
+};
+
+static const SFG_StrokeChar ch104 = {104.762f,2,ch104st};
+
+/* char: 0x69 */
+
+static const SFG_StrokeVertex ch105st0[] =
+{
+ {47.6191f,100.0f},
+ {52.381f,95.2381f},
+ {57.1429f,100.0f},
+ {52.381f,104.762f},
+ {47.6191f,100.0f}
+};
+
+static const SFG_StrokeVertex ch105st1[] =
+{
+ {52.381f,66.6667f},
+ {52.381f,0.0f}
+};
+
+static const SFG_StrokeStrip ch105st[] =
+{
+ {5,ch105st0},
+ {2,ch105st1}
+};
+
+static const SFG_StrokeChar ch105 = {104.762f,2,ch105st};
+
+/* char: 0x6a */
+
+static const SFG_StrokeVertex ch106st0[] =
+{
+ {57.1429f,100.0f},
+ {61.9048f,95.2381f},
+ {66.6667f,100.0f},
+ {61.9048f,104.762f},
+ {57.1429f,100.0f}
+};
+
+static const SFG_StrokeVertex ch106st1[] =
+{
+ {61.9048f,66.6667f},
+ {61.9048f,-14.2857f},
+ {57.1429f,-28.5714f},
+ {47.6191f,-33.3333f},
+ {38.0953f,-33.3333f}
+};
+
+static const SFG_StrokeStrip ch106st[] =
+{
+ {5,ch106st0},
+ {5,ch106st1}
+};
+
+static const SFG_StrokeChar ch106 = {104.762f,2,ch106st};
+
+/* char: 0x6b */
+
+static const SFG_StrokeVertex ch107st0[] =
+{
+ {26.1905f,100.0f},
+ {26.1905f,0.0f}
+};
+
+static const SFG_StrokeVertex ch107st1[] =
+{
+ {73.8095f,66.6667f},
+ {26.1905f,19.0476f}
+};
+
+static const SFG_StrokeVertex ch107st2[] =
+{
+ {45.2381f,38.0952f},
+ {78.5715f,0.0f}
+};
+
+static const SFG_StrokeStrip ch107st[] =
+{
+ {2,ch107st0},
+ {2,ch107st1},
+ {2,ch107st2}
+};
+
+static const SFG_StrokeChar ch107 = {104.762f,3,ch107st};
+
+/* char: 0x6c */
+
+static const SFG_StrokeVertex ch108st0[] =
+{
+ {52.381f,100.0f},
+ {52.381f,0.0f}
+};
+
+static const SFG_StrokeStrip ch108st[] =
+{
+ {2,ch108st0}
+};
+
+static const SFG_StrokeChar ch108 = {104.762f,1,ch108st};
+
+/* char: 0x6d */
+
+static const SFG_StrokeVertex ch109st0[] =
+{
+ {0,66.6667f},
+ {0,0.0f}
+};
+
+static const SFG_StrokeVertex ch109st1[] =
+{
+ {0,47.619f},
+ {14.2857f,61.9048f},
+ {23.8095f,66.6667f},
+ {38.0952f,66.6667f},
+ {47.619f,61.9048f},
+ {52.381f,47.619f},
+ {52.381f,0.0f}
+};
+
+static const SFG_StrokeVertex ch109st2[] =
+{
+ {52.381f,47.619f},
+ {66.6667f,61.9048f},
+ {76.1905f,66.6667f},
+ {90.4762f,66.6667f},
+ {100.0f,61.9048f},
+ {104.762f,47.619f},
+ {104.762f,0.0f}
+};
+
+static const SFG_StrokeStrip ch109st[] =
+{
+ {2,ch109st0},
+ {7,ch109st1},
+ {7,ch109st2}
+};
+
+static const SFG_StrokeChar ch109 = {104.762f,3,ch109st};
+
+/* char: 0x6e */
+
+static const SFG_StrokeVertex ch110st0[] =
+{
+ {26.1905f,66.6667f},
+ {26.1905f,0.0f}
+};
+
+static const SFG_StrokeVertex ch110st1[] =
+{
+ {26.1905f,47.619f},
+ {40.4762f,61.9048f},
+ {50.0f,66.6667f},
+ {64.2857f,66.6667f},
+ {73.8095f,61.9048f},
+ {78.5715f,47.619f},
+ {78.5715f,0.0f}
+};
+
+static const SFG_StrokeStrip ch110st[] =
+{
+ {2,ch110st0},
+ {7,ch110st1}
+};
+
+static const SFG_StrokeChar ch110 = {104.762f,2,ch110st};
+
+/* char: 0x6f */
+
+static const SFG_StrokeVertex ch111st0[] =
+{
+ {45.2381f,66.6667f},
+ {35.7143f,61.9048f},
+ {26.1905f,52.381f},
+ {21.4286f,38.0952f},
+ {21.4286f,28.5714f},
+ {26.1905f,14.2857f},
+ {35.7143f,4.7619f},
+ {45.2381f,0.0f},
+ {59.5238f,0.0f},
+ {69.0476f,4.7619f},
+ {78.5714f,14.2857f},
+ {83.3334f,28.5714f},
+ {83.3334f,38.0952f},
+ {78.5714f,52.381f},
+ {69.0476f,61.9048f},
+ {59.5238f,66.6667f},
+ {45.2381f,66.6667f}
+};
+
+static const SFG_StrokeStrip ch111st[] =
+{
+ {17,ch111st0}
+};
+
+static const SFG_StrokeChar ch111 = {104.762f,1,ch111st};
+
+/* char: 0x70 */
+
+static const SFG_StrokeVertex ch112st0[] =
+{
+ {23.8095f,66.6667f},
+ {23.8095f,-33.3333f}
+};
+
+static const SFG_StrokeVertex ch112st1[] =
+{
+ {23.8095f,52.381f},
+ {33.3333f,61.9048f},
+ {42.8571f,66.6667f},
+ {57.1428f,66.6667f},
+ {66.6666f,61.9048f},
+ {76.1905f,52.381f},
+ {80.9524f,38.0952f},
+ {80.9524f,28.5714f},
+ {76.1905f,14.2857f},
+ {66.6666f,4.7619f},
+ {57.1428f,0.0f},
+ {42.8571f,0.0f},
+ {33.3333f,4.7619f},
+ {23.8095f,14.2857f}
+};
+
+static const SFG_StrokeStrip ch112st[] =
+{
+ {2,ch112st0},
+ {14,ch112st1}
+};
+
+static const SFG_StrokeChar ch112 = {104.762f,2,ch112st};
+
+/* char: 0x71 */
+
+static const SFG_StrokeVertex ch113st0[] =
+{
+ {80.9524f,66.6667f},
+ {80.9524f,-33.3333f}
+};
+
+static const SFG_StrokeVertex ch113st1[] =
+{
+ {80.9524f,52.381f},
+ {71.4285f,61.9048f},
+ {61.9047f,66.6667f},
+ {47.619f,66.6667f},
+ {38.0952f,61.9048f},
+ {28.5714f,52.381f},
+ {23.8095f,38.0952f},
+ {23.8095f,28.5714f},
+ {28.5714f,14.2857f},
+ {38.0952f,4.7619f},
+ {47.619f,0.0f},
+ {61.9047f,0.0f},
+ {71.4285f,4.7619f},
+ {80.9524f,14.2857f}
+};
+
+static const SFG_StrokeStrip ch113st[] =
+{
+ {2,ch113st0},
+ {14,ch113st1}
+};
+
+static const SFG_StrokeChar ch113 = {104.762f,2,ch113st};
+
+/* char: 0x72 */
+
+static const SFG_StrokeVertex ch114st0[] =
+{
+ {33.3334f,66.6667f},
+ {33.3334f,0.0f}
+};
+
+static const SFG_StrokeVertex ch114st1[] =
+{
+ {33.3334f,38.0952f},
+ {38.0953f,52.381f},
+ {47.6191f,61.9048f},
+ {57.1429f,66.6667f},
+ {71.4286f,66.6667f}
+};
+
+static const SFG_StrokeStrip ch114st[] =
+{
+ {2,ch114st0},
+ {5,ch114st1}
+};
+
+static const SFG_StrokeChar ch114 = {104.762f,2,ch114st};
+
+/* char: 0x73 */
+
+static const SFG_StrokeVertex ch115st0[] =
+{
+ {78.5715f,52.381f},
+ {73.8095f,61.9048f},
+ {59.5238f,66.6667f},
+ {45.2381f,66.6667f},
+ {30.9524f,61.9048f},
+ {26.1905f,52.381f},
+ {30.9524f,42.8571f},
+ {40.4762f,38.0952f},
+ {64.2857f,33.3333f},
+ {73.8095f,28.5714f},
+ {78.5715f,19.0476f},
+ {78.5715f,14.2857f},
+ {73.8095f,4.7619f},
+ {59.5238f,0.0f},
+ {45.2381f,0.0f},
+ {30.9524f,4.7619f},
+ {26.1905f,14.2857f}
+};
+
+static const SFG_StrokeStrip ch115st[] =
+{
+ {17,ch115st0}
+};
+
+static const SFG_StrokeChar ch115 = {104.762f,1,ch115st};
+
+/* char: 0x74 */
+
+static const SFG_StrokeVertex ch116st0[] =
+{
+ {47.6191f,100.0f},
+ {47.6191f,19.0476f},
+ {52.381f,4.7619f},
+ {61.9048f,0.0f},
+ {71.4286f,0.0f}
+};
+
+static const SFG_StrokeVertex ch116st1[] =
+{
+ {33.3334f,66.6667f},
+ {66.6667f,66.6667f}
+};
+
+static const SFG_StrokeStrip ch116st[] =
+{
+ {5,ch116st0},
+ {2,ch116st1}
+};
+
+static const SFG_StrokeChar ch116 = {104.762f,2,ch116st};
+
+/* char: 0x75 */
+
+static const SFG_StrokeVertex ch117st0[] =
+{
+ {26.1905f,66.6667f},
+ {26.1905f,19.0476f},
+ {30.9524f,4.7619f},
+ {40.4762f,0.0f},
+ {54.7619f,0.0f},
+ {64.2857f,4.7619f},
+ {78.5715f,19.0476f}
+};
+
+static const SFG_StrokeVertex ch117st1[] =
+{
+ {78.5715f,66.6667f},
+ {78.5715f,0.0f}
+};
+
+static const SFG_StrokeStrip ch117st[] =
+{
+ {7,ch117st0},
+ {2,ch117st1}
+};
+
+static const SFG_StrokeChar ch117 = {104.762f,2,ch117st};
+
+/* char: 0x76 */
+
+static const SFG_StrokeVertex ch118st0[] =
+{
+ {23.8095f,66.6667f},
+ {52.3809f,0.0f}
+};
+
+static const SFG_StrokeVertex ch118st1[] =
+{
+ {80.9524f,66.6667f},
+ {52.3809f,0.0f}
+};
+
+static const SFG_StrokeStrip ch118st[] =
+{
+ {2,ch118st0},
+ {2,ch118st1}
+};
+
+static const SFG_StrokeChar ch118 = {104.762f,2,ch118st};
+
+/* char: 0x77 */
+
+static const SFG_StrokeVertex ch119st0[] =
+{
+ {14.2857f,66.6667f},
+ {33.3333f,0.0f}
+};
+
+static const SFG_StrokeVertex ch119st1[] =
+{
+ {52.3809f,66.6667f},
+ {33.3333f,0.0f}
+};
+
+static const SFG_StrokeVertex ch119st2[] =
+{
+ {52.3809f,66.6667f},
+ {71.4286f,0.0f}
+};
+
+static const SFG_StrokeVertex ch119st3[] =
+{
+ {90.4762f,66.6667f},
+ {71.4286f,0.0f}
+};
+
+static const SFG_StrokeStrip ch119st[] =
+{
+ {2,ch119st0},
+ {2,ch119st1},
+ {2,ch119st2},
+ {2,ch119st3}
+};
+
+static const SFG_StrokeChar ch119 = {104.762f,4,ch119st};
+
+/* char: 0x78 */
+
+static const SFG_StrokeVertex ch120st0[] =
+{
+ {26.1905f,66.6667f},
+ {78.5715f,0.0f}
+};
+
+static const SFG_StrokeVertex ch120st1[] =
+{
+ {78.5715f,66.6667f},
+ {26.1905f,0.0f}
+};
+
+static const SFG_StrokeStrip ch120st[] =
+{
+ {2,ch120st0},
+ {2,ch120st1}
+};
+
+static const SFG_StrokeChar ch120 = {104.762f,2,ch120st};
+
+/* char: 0x79 */
+
+static const SFG_StrokeVertex ch121st0[] =
+{
+ {26.1905f,66.6667f},
+ {54.7619f,0.0f}
+};
+
+static const SFG_StrokeVertex ch121st1[] =
+{
+ {83.3334f,66.6667f},
+ {54.7619f,0.0f},
+ {45.2381f,-19.0476f},
+ {35.7143f,-28.5714f},
+ {26.1905f,-33.3333f},
+ {21.4286f,-33.3333f}
+};
+
+static const SFG_StrokeStrip ch121st[] =
+{
+ {2,ch121st0},
+ {6,ch121st1}
+};
+
+static const SFG_StrokeChar ch121 = {104.762f,2,ch121st};
+
+/* char: 0x7a */
+
+static const SFG_StrokeVertex ch122st0[] =
+{
+ {78.5715f,66.6667f},
+ {26.1905f,0.0f}
+};
+
+static const SFG_StrokeVertex ch122st1[] =
+{
+ {26.1905f,66.6667f},
+ {78.5715f,66.6667f}
+};
+
+static const SFG_StrokeVertex ch122st2[] =
+{
+ {26.1905f,0.0f},
+ {78.5715f,0.0f}
+};
+
+static const SFG_StrokeStrip ch122st[] =
+{
+ {2,ch122st0},
+ {2,ch122st1},
+ {2,ch122st2}
+};
+
+static const SFG_StrokeChar ch122 = {104.762f,3,ch122st};
+
+/* char: 0x7b */
+
+static const SFG_StrokeVertex ch123st0[] =
+{
+ {64.2857f,119.048f},
+ {54.7619f,114.286f},
+ {50.0f,109.524f},
+ {45.2381f,100.0f},
+ {45.2381f,90.4762f},
+ {50.0f,80.9524f},
+ {54.7619f,76.1905f},
+ {59.5238f,66.6667f},
+ {59.5238f,57.1429f},
+ {50.0f,47.619f}
+};
+
+static const SFG_StrokeVertex ch123st1[] =
+{
+ {54.7619f,114.286f},
+ {50.0f,104.762f},
+ {50.0f,95.2381f},
+ {54.7619f,85.7143f},
+ {59.5238f,80.9524f},
+ {64.2857f,71.4286f},
+ {64.2857f,61.9048f},
+ {59.5238f,52.381f},
+ {40.4762f,42.8571f},
+ {59.5238f,33.3333f},
+ {64.2857f,23.8095f},
+ {64.2857f,14.2857f},
+ {59.5238f,4.7619f},
+ {54.7619f,0.0f},
+ {50.0f,-9.5238f},
+ {50.0f,-19.0476f},
+ {54.7619f,-28.5714f}
+};
+
+static const SFG_StrokeVertex ch123st2[] =
+{
+ {50.0f,38.0952f},
+ {59.5238f,28.5714f},
+ {59.5238f,19.0476f},
+ {54.7619f,9.5238f},
+ {50.0f,4.7619f},
+ {45.2381f,-4.7619f},
+ {45.2381f,-14.2857f},
+ {50.0f,-23.8095f},
+ {54.7619f,-28.5714f},
+ {64.2857f,-33.3333f}
+};
+
+static const SFG_StrokeStrip ch123st[] =
+{
+ {10,ch123st0},
+ {17,ch123st1},
+ {10,ch123st2}
+};
+
+static const SFG_StrokeChar ch123 = {104.762f,3,ch123st};
+
+/* char: 0x7c */
+
+static const SFG_StrokeVertex ch124st0[] =
+{
+ {52.381f,119.048f},
+ {52.381f,-33.3333f}
+};
+
+static const SFG_StrokeStrip ch124st[] =
+{
+ {2,ch124st0}
+};
+
+static const SFG_StrokeChar ch124 = {104.762f,1,ch124st};
+
+/* char: 0x7d */
+
+static const SFG_StrokeVertex ch125st0[] =
+{
+ {40.4762f,119.048f},
+ {50.0f,114.286f},
+ {54.7619f,109.524f},
+ {59.5238f,100.0f},
+ {59.5238f,90.4762f},
+ {54.7619f,80.9524f},
+ {50.0f,76.1905f},
+ {45.2381f,66.6667f},
+ {45.2381f,57.1429f},
+ {54.7619f,47.619f}
+};
+
+static const SFG_StrokeVertex ch125st1[] =
+{
+ {50.0f,114.286f},
+ {54.7619f,104.762f},
+ {54.7619f,95.2381f},
+ {50.0f,85.7143f},
+ {45.2381f,80.9524f},
+ {40.4762f,71.4286f},
+ {40.4762f,61.9048f},
+ {45.2381f,52.381f},
+ {64.2857f,42.8571f},
+ {45.2381f,33.3333f},
+ {40.4762f,23.8095f},
+ {40.4762f,14.2857f},
+ {45.2381f,4.7619f},
+ {50.0f,0.0f},
+ {54.7619f,-9.5238f},
+ {54.7619f,-19.0476f},
+ {50.0f,-28.5714f}
+};
+
+static const SFG_StrokeVertex ch125st2[] =
+{
+ {54.7619f,38.0952f},
+ {45.2381f,28.5714f},
+ {45.2381f,19.0476f},
+ {50.0f,9.5238f},
+ {54.7619f,4.7619f},
+ {59.5238f,-4.7619f},
+ {59.5238f,-14.2857f},
+ {54.7619f,-23.8095f},
+ {50.0f,-28.5714f},
+ {40.4762f,-33.3333f}
+};
+
+static const SFG_StrokeStrip ch125st[] =
+{
+ {10,ch125st0},
+ {17,ch125st1},
+ {10,ch125st2}
+};
+
+static const SFG_StrokeChar ch125 = {104.762f,3,ch125st};
+
+/* char: 0x7e */
+
+static const SFG_StrokeVertex ch126st0[] =
+{
+ {9.5238f,28.5714f},
+ {9.5238f,38.0952f},
+ {14.2857f,52.381f},
+ {23.8095f,57.1429f},
+ {33.3333f,57.1429f},
+ {42.8571f,52.381f},
+ {61.9048f,38.0952f},
+ {71.4286f,33.3333f},
+ {80.9524f,33.3333f},
+ {90.4762f,38.0952f},
+ {95.2381f,47.619f}
+};
+
+static const SFG_StrokeVertex ch126st1[] =
+{
+ {9.5238f,38.0952f},
+ {14.2857f,47.619f},
+ {23.8095f,52.381f},
+ {33.3333f,52.381f},
+ {42.8571f,47.619f},
+ {61.9048f,33.3333f},
+ {71.4286f,28.5714f},
+ {80.9524f,28.5714f},
+ {90.4762f,33.3333f},
+ {95.2381f,47.619f},
+ {95.2381f,57.1429f}
+};
+
+static const SFG_StrokeStrip ch126st[] =
+{
+ {11,ch126st0},
+ {11,ch126st1}
+};
+
+static const SFG_StrokeChar ch126 = {104.762f,2,ch126st};
+
+/* char: 0x7f */
+
+static const SFG_StrokeVertex ch127st0[] =
+{
+ {71.4286f,100.0f},
+ {33.3333f,-33.3333f}
+};
+
+static const SFG_StrokeVertex ch127st1[] =
+{
+ {47.619f,66.6667f},
+ {33.3333f,61.9048f},
+ {23.8095f,52.381f},
+ {19.0476f,38.0952f},
+ {19.0476f,23.8095f},
+ {23.8095f,14.2857f},
+ {33.3333f,4.7619f},
+ {47.619f,0.0f},
+ {57.1428f,0.0f},
+ {71.4286f,4.7619f},
+ {80.9524f,14.2857f},
+ {85.7143f,28.5714f},
+ {85.7143f,42.8571f},
+ {80.9524f,52.381f},
+ {71.4286f,61.9048f},
+ {57.1428f,66.6667f},
+ {47.619f,66.6667f}
+};
+
+static const SFG_StrokeStrip ch127st[] =
+{
+ {2,ch127st0},
+ {17,ch127st1}
+};
+
+static const SFG_StrokeChar ch127 = {104.762f,2,ch127st};
+
+static const SFG_StrokeChar *chars[] =
+{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ &ch32, &ch33, &ch34, &ch35, &ch36, &ch37, &ch38, &ch39,
+ &ch40, &ch41, &ch42, &ch43, &ch44, &ch45, &ch46, &ch47,
+ &ch48, &ch49, &ch50, &ch51, &ch52, &ch53, &ch54, &ch55,
+ &ch56, &ch57, &ch58, &ch59, &ch60, &ch61, &ch62, &ch63,
+ &ch64, &ch65, &ch66, &ch67, &ch68, &ch69, &ch70, &ch71,
+ &ch72, &ch73, &ch74, &ch75, &ch76, &ch77, &ch78, &ch79,
+ &ch80, &ch81, &ch82, &ch83, &ch84, &ch85, &ch86, &ch87,
+ &ch88, &ch89, &ch90, &ch91, &ch92, &ch93, &ch94, &ch95,
+ &ch96, &ch97, &ch98, &ch99, &ch100, &ch101, &ch102,
&ch103,
+ &ch104, &ch105, &ch106, &ch107, &ch108, &ch109, &ch110,
&ch111,
+ &ch112, &ch113, &ch114, &ch115, &ch116, &ch117, &ch118,
&ch119,
+ &ch120, &ch121, &ch122, &ch123, &ch124, &ch125, &ch126,
&ch127
+};
+
+const SFG_StrokeFont fgStrokeMonoRoman = {"MonoRoman",128,152.381f,chars};
Index: external/trimesh/gluit/freeglut_geometry.c
--- external/trimesh/gluit/freeglut_geometry.c (revision 0)
+++ external/trimesh/gluit/freeglut_geometry.c (revision 0)
@@ -0,0 +1,1147 @@
+/*
+ * freeglut_geometry.c
+ *
+ * Freeglut geometry rendering methods.
+ *
+ * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
+ * Written by Pawel W. Olszta, <olszta(a)sourceforge.net>
+ * Creation date: Fri Dec 3 1999
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <GL/freeglut.h>
+#include "freeglut_internal.h"
+
+/*
+ * TODO BEFORE THE STABLE RELEASE:
+ *
+ * Following functions have been contributed by Andreas Umbach.
+ *
+ * glutWireCube() -- looks OK
+ * glutSolidCube() -- OK
+ *
+ * Those functions have been implemented by John Fay.
+ *
+ * glutWireTorus() -- looks OK
+ * glutSolidTorus() -- looks OK
+ * glutWireDodecahedron() -- looks OK
+ * glutSolidDodecahedron() -- looks OK
+ * glutWireOctahedron() -- looks OK
+ * glutSolidOctahedron() -- looks OK
+ * glutWireTetrahedron() -- looks OK
+ * glutSolidTetrahedron() -- looks OK
+ * glutWireIcosahedron() -- looks OK
+ * glutSolidIcosahedron() -- looks OK
+ *
+ * The Following functions have been updated by Nigel Stewart, based
+ * on FreeGLUT 2.0.0 implementations:
+ *
+ * glutWireSphere() -- looks OK
+ * glutSolidSphere() -- looks OK
+ * glutWireCone() -- looks OK
+ * glutSolidCone() -- looks OK
+ */
+
+
+/* -- INTERFACE FUNCTIONS -------------------------------------------------- */
+
+/*
+ * Draws a wireframed cube. Code contributed by Andreas Umbach <marvin(a)dataway.ch>
+ */
+void FGAPIENTRY glutWireCube( GLdouble dSize )
+{
+ double size = dSize * 0.5;
+
+# define V(a,b,c) glVertex3d( a size, b size, c size );
+# define N(a,b,c) glNormal3d( a, b, c );
+
+ /*
+ * PWO: I dared to convert the code to use macros...
+ */
+ glBegin( GL_LINE_LOOP ); N( 1.0, 0.0, 0.0); V(+,-,+); V(+,-,-); V(+,+,-); V(+,+,+);
glEnd();
+ glBegin( GL_LINE_LOOP ); N( 0.0, 1.0, 0.0); V(+,+,+); V(+,+,-); V(-,+,-); V(-,+,+);
glEnd();
+ glBegin( GL_LINE_LOOP ); N( 0.0, 0.0, 1.0); V(+,+,+); V(-,+,+); V(-,-,+); V(+,-,+);
glEnd();
+ glBegin( GL_LINE_LOOP ); N(-1.0, 0.0, 0.0); V(-,-,+); V(-,+,+); V(-,+,-); V(-,-,-);
glEnd();
+ glBegin( GL_LINE_LOOP ); N( 0.0,-1.0, 0.0); V(-,-,+); V(-,-,-); V(+,-,-); V(+,-,+);
glEnd();
+ glBegin( GL_LINE_LOOP ); N( 0.0, 0.0,-1.0); V(-,-,-); V(-,+,-); V(+,+,-); V(+,-,-);
glEnd();
+
+# undef V
+# undef N
+}
+
+/*
+ * Draws a solid cube. Code contributed by Andreas Umbach <marvin(a)dataway.ch>
+ */
+void FGAPIENTRY glutSolidCube( GLdouble dSize )
+{
+ double size = dSize * 0.5;
+
+# define V(a,b,c) glVertex3d( a size, b size, c size );
+# define N(a,b,c) glNormal3d( a, b, c );
+
+ /*
+ * PWO: Again, I dared to convert the code to use macros...
+ */
+ glBegin( GL_QUADS );
+ N( 1.0, 0.0, 0.0); V(+,-,+); V(+,-,-); V(+,+,-); V(+,+,+);
+ N( 0.0, 1.0, 0.0); V(+,+,+); V(+,+,-); V(-,+,-); V(-,+,+);
+ N( 0.0, 0.0, 1.0); V(+,+,+); V(-,+,+); V(-,-,+); V(+,-,+);
+ N(-1.0, 0.0, 0.0); V(-,-,+); V(-,+,+); V(-,+,-); V(-,-,-);
+ N( 0.0,-1.0, 0.0); V(-,-,+); V(-,-,-); V(+,-,-); V(+,-,+);
+ N( 0.0, 0.0,-1.0); V(-,-,-); V(-,+,-); V(+,+,-); V(+,-,-);
+ glEnd();
+
+# undef V
+# undef N
+}
+
+/*
+ * Compute lookup table of cos and sin values forming a cirle
+ *
+ * Notes:
+ * It is the responsibility of the caller to free these tables
+ * The size of the table is (n+1) to form a connected loop
+ * The last entry is exactly the same as the first
+ * The sign of n can be flipped to get the reverse loop
+ */
+
+static void circleTable(double **sint,double **cost,const int n)
+{
+ int i;
+
+ /* Table size, the sign of n flips the circle direction */
+
+ const int size = abs(n);
+
+ /* Determine the angle between samples */
+
+ const double angle = 2*M_PI/(double)n;
+
+ /* Allocate memory for n samples, plus duplicate of first entry at the end */
+
+ *sint = (double *) calloc(sizeof(double), size+1);
+ *cost = (double *) calloc(sizeof(double), size+1);
+
+ /* Bail out if memory allocation fails, fgError never returns */
+
+ if (!(*sint) || !(*cost))
+ {
+ free(*sint);
+ free(*cost);
+ fgError("Failed to allocate memory in circleTable");
+ }
+
+ /* Compute cos and sin around the circle */
+
+ for (i=0; i<size; i++)
+ {
+ (*sint)[i] = sin(angle*i);
+ (*cost)[i] = cos(angle*i);
+ }
+
+ /* Last sample is duplicate of the first */
+
+ (*sint)[size] = (*sint)[0];
+ (*cost)[size] = (*cost)[0];
+}
+
+/*
+ * Draws a solid sphere
+ */
+void FGAPIENTRY glutSolidSphere(GLdouble radius, GLint slices, GLint stacks)
+{
+ int i,j;
+
+ /* Adjust z and radius as stacks are drawn. */
+
+ double z0,z1;
+ double r0,r1;
+
+ /* Pre-computed circle */
+
+ double *sint1,*cost1;
+ double *sint2,*cost2;
+ circleTable(&sint1,&cost1,-slices);
+ circleTable(&sint2,&cost2,stacks*2);
+
+ /* The top stack is covered with a triangle fan */
+
+ z0 = 1.0;
+ z1 = cost2[1];
+ r0 = 0.0;
+ r1 = sint2[1];
+
+ glBegin(GL_TRIANGLE_FAN);
+
+ glNormal3d(0,0,1);
+ glVertex3d(0,0,radius);
+
+ for (j=slices; j>=0; j--)
+ {
+ glNormal3d(cost1[j]*r1, sint1[j]*r1, z1 );
+ glVertex3d(cost1[j]*r1*radius, sint1[j]*r1*radius, z1*radius);
+ }
+
+ glEnd();
+
+ /* Cover each stack with a quad strip, except the top and bottom stacks */
+
+ for( i=1; i<stacks-1; i++ )
+ {
+ z0 = z1; z1 = cost2[i+1];
+ r0 = r1; r1 = sint2[i+1];
+
+ glBegin(GL_QUAD_STRIP);
+
+ for(j=0; j<=slices; j++)
+ {
+ glNormal3d(cost1[j]*r1, sint1[j]*r1, z1 );
+ glVertex3d(cost1[j]*r1*radius, sint1[j]*r1*radius, z1*radius);
+ glNormal3d(cost1[j]*r0, sint1[j]*r0, z0 );
+ glVertex3d(cost1[j]*r0*radius, sint1[j]*r0*radius, z0*radius);
+ }
+
+ glEnd();
+ }
+
+ /* The bottom stack is covered with a triangle fan */
+
+ z0 = z1;
+ r0 = r1;
+
+ glBegin(GL_TRIANGLE_FAN);
+
+ glNormal3d(0,0,-1);
+ glVertex3d(0,0,-radius);
+
+ for (j=0; j<=slices; j++)
+ {
+ glNormal3d(cost1[j]*r0, sint1[j]*r0, z0 );
+ glVertex3d(cost1[j]*r0*radius, sint1[j]*r0*radius, z0*radius);
+ }
+
+ glEnd();
+
+ /* Release sin and cos tables */
+
+ free(sint1);
+ free(cost1);
+ free(sint2);
+ free(cost2);
+}
+
+/*
+ * Draws a wire sphere
+ */
+void FGAPIENTRY glutWireSphere(GLdouble radius, GLint slices, GLint stacks)
+{
+ int i,j;
+
+ /* Adjust z and radius as stacks and slices are drawn. */
+
+ double r;
+ double x,y,z;
+
+ /* Pre-computed circle */
+
+ double *sint1,*cost1;
+ double *sint2,*cost2;
+ circleTable(&sint1,&cost1,-slices );
+ circleTable(&sint2,&cost2, stacks*2);
+
+ /* Draw a line loop for each stack */
+
+ for (i=1; i<stacks; i++)
+ {
+ z = cost2[i];
+ r = sint2[i];
+
+ glBegin(GL_LINE_LOOP);
+
+ for(j=0; j<=slices; j++)
+ {
+ x = cost1[j];
+ y = sint1[j];
+
+ glNormal3d(x,y,z);
+ glVertex3d(x*r*radius,y*r*radius,z*radius);
+ }
+
+ glEnd();
+ }
+
+ /* Draw a line loop for each slice */
+
+ for (i=0; i<slices; i++)
+ {
+ glBegin(GL_LINE_STRIP);
+
+ for(j=0; j<=stacks; j++)
+ {
+ x = cost1[i]*sint2[j];
+ y = sint1[i]*sint2[j];
+ z = cost2[j];
+
+ glNormal3d(x,y,z);
+ glVertex3d(x*radius,y*radius,z*radius);
+ }
+
+ glEnd();
+ }
+
+ /* Release sin and cos tables */
+
+ free(sint1);
+ free(cost1);
+ free(sint2);
+ free(cost2);
+}
+
+/*
+ * Draws a solid cone
+ */
+void FGAPIENTRY glutSolidCone( GLdouble base, GLdouble height, GLint slices, GLint stacks
)
+{
+ int i,j;
+
+ /* Step in z and radius as stacks are drawn. */
+
+ double z0,z1;
+ double r0,r1;
+
+ const double zStep = height/stacks;
+ const double rStep = base/stacks;
+
+ /* Scaling factors for vertex normals */
+
+ const double cosn = ( height / sqrt ( height * height + base * base ));
+ const double sinn = ( base / sqrt ( height * height + base * base ));
+
+ /* Pre-computed circle */
+
+ double *sint,*cost;
+ circleTable(&sint,&cost,-slices);
+
+ /* Cover the circular base with a triangle fan... */
+
+ z0 = 0.0;
+ z1 = zStep;
+
+ r0 = base;
+ r1 = r0 - rStep;
+
+ glBegin(GL_TRIANGLE_FAN);
+
+ glNormal3d(0.0,0.0,-1.0);
+ glVertex3d(0.0,0.0, z0 );
+
+ for (j=0; j<=slices; j++)
+ glVertex3d(cost[j]*r0, sint[j]*r0, z0);
+
+ glEnd();
+
+ /* Cover each stack with a quad strip, except the top stack */
+
+ for( i=0; i<stacks-1; i++ )
+ {
+ glBegin(GL_QUAD_STRIP);
+
+ for(j=0; j<=slices; j++)
+ {
+ glNormal3d(cost[j]*sinn, sint[j]*sinn, cosn);
+ glVertex3d(cost[j]*r0, sint[j]*r0, z0 );
+ glVertex3d(cost[j]*r1, sint[j]*r1, z1 );
+ }
+
+ z0 = z1; z1 += zStep;
+ r0 = r1; r1 -= rStep;
+
+ glEnd();
+ }
+
+ /* The top stack is covered with individual triangles */
+
+ glBegin(GL_TRIANGLES);
+
+ glNormal3d(cost[0]*sinn, sint[0]*sinn, cosn);
+
+ for (j=0; j<slices; j++)
+ {
+ glVertex3d(cost[j+0]*r0, sint[j+0]*r0, z0 );
+ glVertex3d(0, 0, height);
+ glNormal3d(cost[j+1]*sinn, sint[j+1]*sinn, cosn );
+ glVertex3d(cost[j+1]*r0, sint[j+1]*r0, z0 );
+ }
+
+ glEnd();
+
+ /* Release sin and cos tables */
+
+ free(sint);
+ free(cost);
+}
+
+/*
+ * Draws a wire cone
+ */
+void FGAPIENTRY glutWireCone( GLdouble base, GLdouble height, GLint slices, GLint
stacks)
+{
+ int i,j;
+
+ /* Step in z and radius as stacks are drawn. */
+
+ double z = 0.0;
+ double r = base;
+
+ const double zStep = height/stacks;
+ const double rStep = base/stacks;
+
+ /* Scaling factors for vertex normals */
+
+ const double cosn = ( height / sqrt ( height * height + base * base ));
+ const double sinn = ( base / sqrt ( height * height + base * base ));
+
+ /* Pre-computed circle */
+
+ double *sint,*cost;
+ circleTable(&sint,&cost,-slices);
+
+ /* Draw the stacks... */
+
+ for (i=0; i<stacks; i++)
+ {
+ glBegin(GL_LINE_LOOP);
+
+ for( j=0; j<slices; j++ )
+ {
+ glNormal3d(cost[j]*sinn, sint[j]*sinn, cosn);
+ glVertex3d(cost[j]*r, sint[j]*r, z );
+ }
+
+ glEnd();
+
+ z += zStep;
+ r -= rStep;
+ }
+
+ /* Draw the slices */
+
+ r = base;
+
+ glBegin(GL_LINES);
+
+ for (j=0; j<slices; j++)
+ {
+ glNormal3d(cost[j]*sinn, sint[j]*sinn, cosn );
+ glVertex3d(cost[j]*r, sint[j]*r, 0.0 );
+ glVertex3d(0.0, 0.0, height);
+ }
+
+ glEnd();
+
+ /* Release sin and cos tables */
+
+ free(sint);
+ free(cost);
+}
+
+
+/*
+ * Draws a solid cylinder
+ */
+void FGAPIENTRY glutSolidCylinder(GLdouble radius, GLdouble height, GLint slices, GLint
stacks)
+{
+ int i,j;
+
+ /* Step in z and radius as stacks are drawn. */
+
+ double z0,z1;
+ const double zStep = height/stacks;
+
+ /* Pre-computed circle */
+
+ double *sint,*cost;
+ circleTable(&sint,&cost,-slices);
+
+ /* Cover the base and top */
+
+ glBegin(GL_TRIANGLE_FAN);
+ glNormal3d(0.0, 0.0, -1.0 );
+ glVertex3d(0.0, 0.0, 0.0 );
+ for (j=0; j<=slices; j++)
+ glVertex3d(cost[j]*radius, sint[j]*radius, 0.0);
+ glEnd();
+
+ glBegin(GL_TRIANGLE_FAN);
+ glNormal3d(0.0, 0.0, 1.0 );
+ glVertex3d(0.0, 0.0, height);
+ for (j=slices; j>=0; j--)
+ glVertex3d(cost[j]*radius, sint[j]*radius, height);
+ glEnd();
+
+ /* Do the stacks */
+
+ z0 = 0.0;
+ z1 = zStep;
+
+ for (i=1; i<=stacks; i++)
+ {
+ if (i==stacks)
+ z1 = height;
+
+ glBegin(GL_QUAD_STRIP);
+ for (j=0; j<=slices; j++ )
+ {
+ glNormal3d(cost[j], sint[j], 0.0 );
+ glVertex3d(cost[j]*radius, sint[j]*radius, z0 );
+ glVertex3d(cost[j]*radius, sint[j]*radius, z1 );
+ }
+ glEnd();
+
+ z0 = z1; z1 += zStep;
+ }
+
+ /* Release sin and cos tables */
+
+ free(sint);
+ free(cost);
+}
+
+/*
+ * Draws a wire cylinder
+ */
+void FGAPIENTRY glutWireCylinder(GLdouble radius, GLdouble height, GLint slices, GLint
stacks)
+{
+ int i,j;
+
+ /* Step in z and radius as stacks are drawn. */
+
+ double z = 0.0;
+ const double zStep = height/stacks;
+
+ /* Pre-computed circle */
+
+ double *sint,*cost;
+ circleTable(&sint,&cost,-slices);
+
+ /* Draw the stacks... */
+
+ for (i=0; i<=stacks; i++)
+ {
+ if (i==stacks)
+ z = height;
+
+ glBegin(GL_LINE_LOOP);
+
+ for( j=0; j<slices; j++ )
+ {
+ glNormal3d(cost[j], sint[j], 0.0);
+ glVertex3d(cost[j]*radius, sint[j]*radius, z );
+ }
+
+ glEnd();
+
+ z += zStep;
+ }
+
+ /* Draw the slices */
+
+ glBegin(GL_LINES);
+
+ for (j=0; j<slices; j++)
+ {
+ glNormal3d(cost[j], sint[j], 0.0 );
+ glVertex3d(cost[j]*radius, sint[j]*radius, 0.0 );
+ glVertex3d(cost[j]*radius, sint[j]*radius, height);
+ }
+
+ glEnd();
+
+ /* Release sin and cos tables */
+
+ free(sint);
+ free(cost);
+}
+
+/*
+ * Draws a wire torus
+ */
+void FGAPIENTRY glutWireTorus( GLdouble dInnerRadius, GLdouble dOuterRadius, GLint
nSides, GLint nRings )
+{
+ double iradius = dInnerRadius, oradius = dOuterRadius, phi, psi, dpsi, dphi;
+ double *vertex, *normal;
+ int i, j;
+ double spsi, cpsi, sphi, cphi ;
+
+ /*
+ * Allocate the vertices array
+ */
+ vertex = (double *)calloc( sizeof(double), 3 * nSides * nRings );
+ normal = (double *)calloc( sizeof(double), 3 * nSides * nRings );
+
+ glPushMatrix();
+
+ dpsi = 2.0 * M_PI / (double)nRings ;
+ dphi = -2.0 * M_PI / (double)nSides ;
+ psi = 0.0;
+
+ for( j=0; j<nRings; j++ )
+ {
+ cpsi = cos ( psi ) ;
+ spsi = sin ( psi ) ;
+ phi = 0.0;
+
+ for( i=0; i<nSides; i++ )
+ {
+ int offset = 3 * ( j * nSides + i ) ;
+ cphi = cos ( phi ) ;
+ sphi = sin ( phi ) ;
+ *(vertex + offset + 0) = cpsi * ( oradius + cphi * iradius ) ;
+ *(vertex + offset + 1) = spsi * ( oradius + cphi * iradius ) ;
+ *(vertex + offset + 2) = sphi * iradius ;
+ *(normal + offset + 0) = cpsi * cphi ;
+ *(normal + offset + 1) = spsi * cphi ;
+ *(normal + offset + 2) = sphi ;
+ phi += dphi;
+ }
+
+ psi += dpsi;
+ }
+
+ for( i=0; i<nSides; i++ )
+ {
+ glBegin( GL_LINE_LOOP );
+
+ for( j=0; j<nRings; j++ )
+ {
+ int offset = 3 * ( j * nSides + i ) ;
+ glNormal3dv( normal + offset );
+ glVertex3dv( vertex + offset );
+ }
+
+ glEnd();
+ }
+
+ for( j=0; j<nRings; j++ )
+ {
+ glBegin(GL_LINE_LOOP);
+
+ for( i=0; i<nSides; i++ )
+ {
+ int offset = 3 * ( j * nSides + i ) ;
+ glNormal3dv( normal + offset );
+ glVertex3dv( vertex + offset );
+ }
+
+ glEnd();
+ }
+
+ free ( vertex ) ;
+ free ( normal ) ;
+ glPopMatrix();
+}
+
+/*
+ * Draws a solid torus
+ */
+void FGAPIENTRY glutSolidTorus( GLdouble dInnerRadius, GLdouble dOuterRadius, GLint
nSides, GLint nRings )
+{
+ double iradius = dInnerRadius, oradius = dOuterRadius, phi, psi, dpsi, dphi;
+ double *vertex, *normal;
+ int i, j;
+ double spsi, cpsi, sphi, cphi ;
+
+ /*
+ * Increment the number of sides and rings to allow for one more point than surface
+ */
+ nSides ++ ;
+ nRings ++ ;
+
+ /*
+ * Allocate the vertices array
+ */
+ vertex = (double *)calloc( sizeof(double), 3 * nSides * nRings );
+ normal = (double *)calloc( sizeof(double), 3 * nSides * nRings );
+
+ glPushMatrix();
+
+ dpsi = 2.0 * M_PI / (double)(nRings - 1) ;
+ dphi = -2.0 * M_PI / (double)(nSides - 1) ;
+ psi = 0.0;
+
+ for( j=0; j<nRings; j++ )
+ {
+ cpsi = cos ( psi ) ;
+ spsi = sin ( psi ) ;
+ phi = 0.0;
+
+ for( i=0; i<nSides; i++ )
+ {
+ int offset = 3 * ( j * nSides + i ) ;
+ cphi = cos ( phi ) ;
+ sphi = sin ( phi ) ;
+ *(vertex + offset + 0) = cpsi * ( oradius + cphi * iradius ) ;
+ *(vertex + offset + 1) = spsi * ( oradius + cphi * iradius ) ;
+ *(vertex + offset + 2) = sphi * iradius ;
+ *(normal + offset + 0) = cpsi * cphi ;
+ *(normal + offset + 1) = spsi * cphi ;
+ *(normal + offset + 2) = sphi ;
+ phi += dphi;
+ }
+
+ psi += dpsi;
+ }
+
+ glBegin( GL_QUADS );
+ for( i=0; i<nSides-1; i++ )
+ {
+ for( j=0; j<nRings-1; j++ )
+ {
+ int offset = 3 * ( j * nSides + i ) ;
+ glNormal3dv( normal + offset );
+ glVertex3dv( vertex + offset );
+ glNormal3dv( normal + offset + 3 );
+ glVertex3dv( vertex + offset + 3 );
+ glNormal3dv( normal + offset + 3 * nSides + 3 );
+ glVertex3dv( vertex + offset + 3 * nSides + 3 );
+ glNormal3dv( normal + offset + 3 * nSides );
+ glVertex3dv( vertex + offset + 3 * nSides );
+ }
+ }
+
+ glEnd();
+
+ free ( vertex ) ;
+ free ( normal ) ;
+ glPopMatrix();
+}
+
+/*
+ *
+ */
+void FGAPIENTRY glutWireDodecahedron( void )
+{
+ /* Magic Numbers: It is possible to create a dodecahedron by attaching two pentagons
to each face of
+ * of a cube. The coordinates of the points are:
+ * (+-x,0, z); (+-1, 1, 1); (0, z, x )
+ * where x = 0.61803398875 and z = 1.61803398875.
+ */
+ glBegin ( GL_LINE_LOOP ) ;
+ glNormal3d ( 0.0, 0.525731112119, 0.850650808354 ) ; glVertex3d ( 0.0,
1.61803398875, 0.61803398875 ) ; glVertex3d ( -1.0, 1.0, 1.0 ) ; glVertex3d (
-0.61803398875, 0.0, 1.61803398875 ) ; glVertex3d ( 0.61803398875, 0.0, 1.61803398875 )
; glVertex3d ( 1.0, 1.0, 1.0 ) ;
+ glEnd () ;
+ glBegin ( GL_LINE_LOOP ) ;
+ glNormal3d ( 0.0, 0.525731112119, -0.850650808354 ) ; glVertex3d ( 0.0,
1.61803398875, -0.61803398875 ) ; glVertex3d ( 1.0, 1.0, -1.0 ) ; glVertex3d (
0.61803398875, 0.0, -1.61803398875 ) ; glVertex3d ( -0.61803398875, 0.0, -1.61803398875 )
; glVertex3d ( -1.0, 1.0, -1.0 ) ;
+ glEnd () ;
+ glBegin ( GL_LINE_LOOP ) ;
+ glNormal3d ( 0.0, -0.525731112119, 0.850650808354 ) ; glVertex3d ( 0.0,
-1.61803398875, 0.61803398875 ) ; glVertex3d ( 1.0, -1.0, 1.0 ) ; glVertex3d (
0.61803398875, 0.0, 1.61803398875 ) ; glVertex3d ( -0.61803398875, 0.0, 1.61803398875 )
; glVertex3d ( -1.0, -1.0, 1.0 ) ;
+ glEnd () ;
+ glBegin ( GL_LINE_LOOP ) ;
+ glNormal3d ( 0.0, -0.525731112119, -0.850650808354 ) ; glVertex3d ( 0.0,
-1.61803398875, -0.61803398875 ) ; glVertex3d ( -1.0, -1.0, -1.0 ) ; glVertex3d (
-0.61803398875, 0.0, -1.61803398875 ) ; glVertex3d ( 0.61803398875, 0.0, -1.61803398875 )
; glVertex3d ( 1.0, -1.0, -1.0 ) ;
+ glEnd () ;
+
+ glBegin ( GL_LINE_LOOP ) ;
+ glNormal3d ( 0.850650808354, 0.0, 0.525731112119 ) ; glVertex3d ( 0.61803398875,
0.0, 1.61803398875 ) ; glVertex3d ( 1.0, -1.0, 1.0 ) ; glVertex3d ( 1.61803398875,
-0.61803398875, 0.0 ) ; glVertex3d ( 1.61803398875, 0.61803398875, 0.0 ) ; glVertex3d (
1.0, 1.0, 1.0 ) ;
+ glEnd () ;
+ glBegin ( GL_LINE_LOOP ) ;
+ glNormal3d ( -0.850650808354, 0.0, 0.525731112119 ) ; glVertex3d ( -0.61803398875,
0.0, 1.61803398875 ) ; glVertex3d ( -1.0, 1.0, 1.0 ) ; glVertex3d ( -1.61803398875,
0.61803398875, 0.0 ) ; glVertex3d ( -1.61803398875, -0.61803398875, 0.0 ) ; glVertex3d (
-1.0, -1.0, 1.0 ) ;
+ glEnd () ;
+ glBegin ( GL_LINE_LOOP ) ;
+ glNormal3d ( 0.850650808354, 0.0, -0.525731112119 ) ; glVertex3d ( 0.61803398875,
0.0, -1.61803398875 ) ; glVertex3d ( 1.0, 1.0, -1.0 ) ; glVertex3d ( 1.61803398875,
0.61803398875, 0.0 ) ; glVertex3d ( 1.61803398875, -0.61803398875, 0.0 ) ; glVertex3d (
1.0, -1.0, -1.0 ) ;
+ glEnd () ;
+ glBegin ( GL_LINE_LOOP ) ;
+ glNormal3d ( -0.850650808354, 0.0, -0.525731112119 ) ; glVertex3d ( -0.61803398875,
0.0, -1.61803398875 ) ; glVertex3d ( -1.0, -1.0, -1.0 ) ; glVertex3d ( -1.61803398875,
-0.61803398875, 0.0 ) ; glVertex3d ( -1.61803398875, 0.61803398875, 0.0 ) ; glVertex3d (
-1.0, 1.0, -1.0 ) ;
+ glEnd () ;
+
+ glBegin ( GL_LINE_LOOP ) ;
+ glNormal3d ( 0.525731112119, 0.850650808354, 0.0 ) ; glVertex3d ( 1.61803398875,
0.61803398875, 0.0 ) ; glVertex3d ( 1.0, 1.0, -1.0 ) ; glVertex3d ( 0.0,
1.61803398875, -0.61803398875 ) ; glVertex3d ( 0.0, 1.61803398875, 0.61803398875 ) ;
glVertex3d ( 1.0, 1.0, 1.0 ) ;
+ glEnd () ;
+ glBegin ( GL_LINE_LOOP ) ;
+ glNormal3d ( 0.525731112119, -0.850650808354, 0.0 ) ; glVertex3d ( 1.61803398875,
-0.61803398875, 0.0 ) ; glVertex3d ( 1.0, -1.0, 1.0 ) ; glVertex3d ( 0.0,
-1.61803398875, 0.61803398875 ) ; glVertex3d ( 0.0, -1.61803398875, -0.61803398875 ) ;
glVertex3d ( 1.0, -1.0, -1.0 ) ;
+ glEnd () ;
+ glBegin ( GL_LINE_LOOP ) ;
+ glNormal3d ( -0.525731112119, 0.850650808354, 0.0 ) ; glVertex3d ( -1.61803398875,
0.61803398875, 0.0 ) ; glVertex3d ( -1.0, 1.0, 1.0 ) ; glVertex3d ( 0.0,
1.61803398875, 0.61803398875 ) ; glVertex3d ( 0.0, 1.61803398875, -0.61803398875 ) ;
glVertex3d ( -1.0, 1.0, -1.0 ) ;
+ glEnd () ;
+ glBegin ( GL_LINE_LOOP ) ;
+ glNormal3d ( -0.525731112119, -0.850650808354, 0.0 ) ; glVertex3d ( -1.61803398875,
-0.61803398875, 0.0 ) ; glVertex3d ( -1.0, -1.0, -1.0 ) ; glVertex3d ( 0.0,
-1.61803398875, -0.61803398875 ) ; glVertex3d ( 0.0, -1.61803398875, 0.61803398875 ) ;
glVertex3d ( -1.0, -1.0, 1.0 ) ;
+ glEnd () ;
+}
+
+/*
+ *
+ */
+void FGAPIENTRY glutSolidDodecahedron( void )
+{
+ /* Magic Numbers: It is possible to create a dodecahedron by attaching two pentagons
to each face of
+ * of a cube. The coordinates of the points are:
+ * (+-x,0, z); (+-1, 1, 1); (0, z, x )
+ * where x = 0.61803398875 and z = 1.61803398875.
+ */
+ glBegin ( GL_POLYGON ) ;
+ glNormal3d ( 0.0, 0.525731112119, 0.850650808354 ) ; glVertex3d ( 0.0,
1.61803398875, 0.61803398875 ) ; glVertex3d ( -1.0, 1.0, 1.0 ) ; glVertex3d (
-0.61803398875, 0.0, 1.61803398875 ) ; glVertex3d ( 0.61803398875, 0.0, 1.61803398875 )
; glVertex3d ( 1.0, 1.0, 1.0 ) ;
+ glEnd () ;
+ glBegin ( GL_POLYGON ) ;
+ glNormal3d ( 0.0, 0.525731112119, -0.850650808354 ) ; glVertex3d ( 0.0,
1.61803398875, -0.61803398875 ) ; glVertex3d ( 1.0, 1.0, -1.0 ) ; glVertex3d (
0.61803398875, 0.0, -1.61803398875 ) ; glVertex3d ( -0.61803398875, 0.0, -1.61803398875 )
; glVertex3d ( -1.0, 1.0, -1.0 ) ;
+ glEnd () ;
+ glBegin ( GL_POLYGON ) ;
+ glNormal3d ( 0.0, -0.525731112119, 0.850650808354 ) ; glVertex3d ( 0.0,
-1.61803398875, 0.61803398875 ) ; glVertex3d ( 1.0, -1.0, 1.0 ) ; glVertex3d (
0.61803398875, 0.0, 1.61803398875 ) ; glVertex3d ( -0.61803398875, 0.0, 1.61803398875 )
; glVertex3d ( -1.0, -1.0, 1.0 ) ;
+ glEnd () ;
+ glBegin ( GL_POLYGON ) ;
+ glNormal3d ( 0.0, -0.525731112119, -0.850650808354 ) ; glVertex3d ( 0.0,
-1.61803398875, -0.61803398875 ) ; glVertex3d ( -1.0, -1.0, -1.0 ) ; glVertex3d (
-0.61803398875, 0.0, -1.61803398875 ) ; glVertex3d ( 0.61803398875, 0.0, -1.61803398875 )
; glVertex3d ( 1.0, -1.0, -1.0 ) ;
+ glEnd () ;
+
+ glBegin ( GL_POLYGON ) ;
+ glNormal3d ( 0.850650808354, 0.0, 0.525731112119 ) ; glVertex3d ( 0.61803398875,
0.0, 1.61803398875 ) ; glVertex3d ( 1.0, -1.0, 1.0 ) ; glVertex3d ( 1.61803398875,
-0.61803398875, 0.0 ) ; glVertex3d ( 1.61803398875, 0.61803398875, 0.0 ) ; glVertex3d (
1.0, 1.0, 1.0 ) ;
+ glEnd () ;
+ glBegin ( GL_POLYGON ) ;
+ glNormal3d ( -0.850650808354, 0.0, 0.525731112119 ) ; glVertex3d ( -0.61803398875,
0.0, 1.61803398875 ) ; glVertex3d ( -1.0, 1.0, 1.0 ) ; glVertex3d ( -1.61803398875,
0.61803398875, 0.0 ) ; glVertex3d ( -1.61803398875, -0.61803398875, 0.0 ) ; glVertex3d (
-1.0, -1.0, 1.0 ) ;
+ glEnd () ;
+ glBegin ( GL_POLYGON ) ;
+ glNormal3d ( 0.850650808354, 0.0, -0.525731112119 ) ; glVertex3d ( 0.61803398875,
0.0, -1.61803398875 ) ; glVertex3d ( 1.0, 1.0, -1.0 ) ; glVertex3d ( 1.61803398875,
0.61803398875, 0.0 ) ; glVertex3d ( 1.61803398875, -0.61803398875, 0.0 ) ; glVertex3d (
1.0, -1.0, -1.0 ) ;
+ glEnd () ;
+ glBegin ( GL_POLYGON ) ;
+ glNormal3d ( -0.850650808354, 0.0, -0.525731112119 ) ; glVertex3d ( -0.61803398875,
0.0, -1.61803398875 ) ; glVertex3d ( -1.0, -1.0, -1.0 ) ; glVertex3d ( -1.61803398875,
-0.61803398875, 0.0 ) ; glVertex3d ( -1.61803398875, 0.61803398875, 0.0 ) ; glVertex3d (
-1.0, 1.0, -1.0 ) ;
+ glEnd () ;
+
+ glBegin ( GL_POLYGON ) ;
+ glNormal3d ( 0.525731112119, 0.850650808354, 0.0 ) ; glVertex3d ( 1.61803398875,
0.61803398875, 0.0 ) ; glVertex3d ( 1.0, 1.0, -1.0 ) ; glVertex3d ( 0.0,
1.61803398875, -0.61803398875 ) ; glVertex3d ( 0.0, 1.61803398875, 0.61803398875 ) ;
glVertex3d ( 1.0, 1.0, 1.0 ) ;
+ glEnd () ;
+ glBegin ( GL_POLYGON ) ;
+ glNormal3d ( 0.525731112119, -0.850650808354, 0.0 ) ; glVertex3d ( 1.61803398875,
-0.61803398875, 0.0 ) ; glVertex3d ( 1.0, -1.0, 1.0 ) ; glVertex3d ( 0.0,
-1.61803398875, 0.61803398875 ) ; glVertex3d ( 0.0, -1.61803398875, -0.61803398875 ) ;
glVertex3d ( 1.0, -1.0, -1.0 ) ;
+ glEnd () ;
+ glBegin ( GL_POLYGON ) ;
+ glNormal3d ( -0.525731112119, 0.850650808354, 0.0 ) ; glVertex3d ( -1.61803398875,
0.61803398875, 0.0 ) ; glVertex3d ( -1.0, 1.0, 1.0 ) ; glVertex3d ( 0.0,
1.61803398875, 0.61803398875 ) ; glVertex3d ( 0.0, 1.61803398875, -0.61803398875 ) ;
glVertex3d ( -1.0, 1.0, -1.0 ) ;
+ glEnd () ;
+ glBegin ( GL_POLYGON ) ;
+ glNormal3d ( -0.525731112119, -0.850650808354, 0.0 ) ; glVertex3d ( -1.61803398875,
-0.61803398875, 0.0 ) ; glVertex3d ( -1.0, -1.0, -1.0 ) ; glVertex3d ( 0.0,
-1.61803398875, -0.61803398875 ) ; glVertex3d ( 0.0, -1.61803398875, 0.61803398875 ) ;
glVertex3d ( -1.0, -1.0, 1.0 ) ;
+ glEnd () ;
+}
+
+/*
+ *
+ */
+void FGAPIENTRY glutWireOctahedron( void )
+{
+#define RADIUS 1.0f
+ glBegin( GL_LINE_LOOP );
+ glNormal3d( 0.577350269189, 0.577350269189, 0.577350269189); glVertex3d( RADIUS, 0.0,
0.0 ); glVertex3d( 0.0, RADIUS, 0.0 ); glVertex3d( 0.0, 0.0, RADIUS );
+ glNormal3d( 0.577350269189, 0.577350269189,-0.577350269189); glVertex3d( RADIUS, 0.0,
0.0 ); glVertex3d( 0.0, RADIUS, 0.0 ); glVertex3d( 0.0, 0.0,-RADIUS );
+ glNormal3d( 0.577350269189,-0.577350269189, 0.577350269189); glVertex3d( RADIUS, 0.0,
0.0 ); glVertex3d( 0.0,-RADIUS, 0.0 ); glVertex3d( 0.0, 0.0, RADIUS );
+ glNormal3d( 0.577350269189,-0.577350269189,-0.577350269189); glVertex3d( RADIUS, 0.0,
0.0 ); glVertex3d( 0.0,-RADIUS, 0.0 ); glVertex3d( 0.0, 0.0,-RADIUS );
+ glNormal3d(-0.577350269189, 0.577350269189, 0.577350269189); glVertex3d(-RADIUS, 0.0,
0.0 ); glVertex3d( 0.0, RADIUS, 0.0 ); glVertex3d( 0.0, 0.0, RADIUS );
+ glNormal3d(-0.577350269189, 0.577350269189,-0.577350269189); glVertex3d(-RADIUS, 0.0,
0.0 ); glVertex3d( 0.0, RADIUS, 0.0 ); glVertex3d( 0.0, 0.0,-RADIUS );
+ glNormal3d(-0.577350269189,-0.577350269189, 0.577350269189); glVertex3d(-RADIUS, 0.0,
0.0 ); glVertex3d( 0.0,-RADIUS, 0.0 ); glVertex3d( 0.0, 0.0, RADIUS );
+ glNormal3d(-0.577350269189,-0.577350269189,-0.577350269189); glVertex3d(-RADIUS, 0.0,
0.0 ); glVertex3d( 0.0,-RADIUS, 0.0 ); glVertex3d( 0.0, 0.0,-RADIUS );
+ glEnd();
+#undef RADIUS
+}
+
+/*
+ *
+ */
+void FGAPIENTRY glutSolidOctahedron( void )
+{
+#define RADIUS 1.0f
+ glBegin( GL_TRIANGLES );
+ glNormal3d( 0.577350269189, 0.577350269189, 0.577350269189); glVertex3d( RADIUS, 0.0,
0.0 ); glVertex3d( 0.0, RADIUS, 0.0 ); glVertex3d( 0.0, 0.0, RADIUS );
+ glNormal3d( 0.577350269189, 0.577350269189,-0.577350269189); glVertex3d( RADIUS, 0.0,
0.0 ); glVertex3d( 0.0, RADIUS, 0.0 ); glVertex3d( 0.0, 0.0,-RADIUS );
+ glNormal3d( 0.577350269189,-0.577350269189, 0.577350269189); glVertex3d( RADIUS, 0.0,
0.0 ); glVertex3d( 0.0,-RADIUS, 0.0 ); glVertex3d( 0.0, 0.0, RADIUS );
+ glNormal3d( 0.577350269189,-0.577350269189,-0.577350269189); glVertex3d( RADIUS, 0.0,
0.0 ); glVertex3d( 0.0,-RADIUS, 0.0 ); glVertex3d( 0.0, 0.0,-RADIUS );
+ glNormal3d(-0.577350269189, 0.577350269189, 0.577350269189); glVertex3d(-RADIUS, 0.0,
0.0 ); glVertex3d( 0.0, RADIUS, 0.0 ); glVertex3d( 0.0, 0.0, RADIUS );
+ glNormal3d(-0.577350269189, 0.577350269189,-0.577350269189); glVertex3d(-RADIUS, 0.0,
0.0 ); glVertex3d( 0.0, RADIUS, 0.0 ); glVertex3d( 0.0, 0.0,-RADIUS );
+ glNormal3d(-0.577350269189,-0.577350269189, 0.577350269189); glVertex3d(-RADIUS, 0.0,
0.0 ); glVertex3d( 0.0,-RADIUS, 0.0 ); glVertex3d( 0.0, 0.0, RADIUS );
+ glNormal3d(-0.577350269189,-0.577350269189,-0.577350269189); glVertex3d(-RADIUS, 0.0,
0.0 ); glVertex3d( 0.0,-RADIUS, 0.0 ); glVertex3d( 0.0, 0.0,-RADIUS );
+ glEnd();
+#undef RADIUS
+}
+
+/*
+ *
+ */
+void FGAPIENTRY glutWireTetrahedron( void )
+{
+ /* Magic Numbers: r0 = ( 1, 0, 0 )
+ * r1 = ( -1/3, 2 sqrt(2) / 3, 0 )
+ * r2 = ( -1/3, -sqrt(2) / 3, sqrt(6) / 3 )
+ * r3 = ( -1/3, -sqrt(2) / 3, -sqrt(6) / 3 )
+ * |r0| = |r1| = |r2| = |r3| = 1
+ * Distance between any two points is 2 sqrt(6) / 3
+ *
+ * Normals: The unit normals are simply the negative of the coordinates of the point
not on the surface.
+ */
+
+ double r0[3] = { 1.0, 0.0, 0.0 } ;
+ double r1[3] = { -0.333333333333, 0.942809041582, 0.0 } ;
+ double r2[3] = { -0.333333333333, -0.471404520791, 0.816496580928 } ;
+ double r3[3] = { -0.333333333333, -0.471404520791, -0.816496580928 } ;
+
+ glBegin( GL_LINE_LOOP ) ;
+ glNormal3d ( -1.0, 0.0, 0.0 ) ; glVertex3dv ( r1 )
; glVertex3dv ( r3 ) ; glVertex3dv ( r2 ) ;
+ glNormal3d ( 0.333333333333, -0.942809041582, 0.0 ) ; glVertex3dv ( r0 )
; glVertex3dv ( r2 ) ; glVertex3dv ( r3 ) ;
+ glNormal3d ( 0.333333333333, 0.471404520791, -0.816496580928 ) ; glVertex3dv ( r0 )
; glVertex3dv ( r3 ) ; glVertex3dv ( r1 ) ;
+ glNormal3d ( 0.333333333333, 0.471404520791, 0.816496580928 ) ; glVertex3dv ( r0 )
; glVertex3dv ( r1 ) ; glVertex3dv ( r2 ) ;
+ glEnd() ;
+}
+
+/*
+ *
+ */
+void FGAPIENTRY glutSolidTetrahedron( void )
+{
+ /* Magic Numbers: r0 = ( 1, 0, 0 )
+ * r1 = ( -1/3, 2 sqrt(2) / 3, 0 )
+ * r2 = ( -1/3, -sqrt(2) / 3, sqrt(6) / 3 )
+ * r3 = ( -1/3, -sqrt(2) / 3, -sqrt(6) / 3 )
+ * |r0| = |r1| = |r2| = |r3| = 1
+ * Distance between any two points is 2 sqrt(6) / 3
+ *
+ * Normals: The unit normals are simply the negative of the coordinates of the point
not on the surface.
+ */
+
+ double r0[3] = { 1.0, 0.0, 0.0 } ;
+ double r1[3] = { -0.333333333333, 0.942809041582, 0.0 } ;
+ double r2[3] = { -0.333333333333, -0.471404520791, 0.816496580928 } ;
+ double r3[3] = { -0.333333333333, -0.471404520791, -0.816496580928 } ;
+
+ glBegin( GL_TRIANGLES ) ;
+ glNormal3d ( -1.0, 0.0, 0.0 ) ; glVertex3dv ( r1 )
; glVertex3dv ( r3 ) ; glVertex3dv ( r2 ) ;
+ glNormal3d ( 0.333333333333, -0.942809041582, 0.0 ) ; glVertex3dv ( r0 )
; glVertex3dv ( r2 ) ; glVertex3dv ( r3 ) ;
+ glNormal3d ( 0.333333333333, 0.471404520791, -0.816496580928 ) ; glVertex3dv ( r0 )
; glVertex3dv ( r3 ) ; glVertex3dv ( r1 ) ;
+ glNormal3d ( 0.333333333333, 0.471404520791, 0.816496580928 ) ; glVertex3dv ( r0 )
; glVertex3dv ( r1 ) ; glVertex3dv ( r2 ) ;
+ glEnd() ;
+}
+
+/*
+ *
+ */
+double icos_r[12][3] = { { 1.0, 0.0, 0.0 },
+ { 0.447213595500, 0.894427191000, 0.0 }, { 0.447213595500, 0.276393202252,
0.850650808354 }, { 0.447213595500, -0.723606797748, 0.525731112119 }, { 0.447213595500,
-0.723606797748, -0.525731112119 }, { 0.447213595500, 0.276393202252, -0.850650808354
},
+ { -0.447213595500, -0.894427191000, 0.0 }, { -0.447213595500, -0.276393202252,
0.850650808354 }, { -0.447213595500, 0.723606797748, 0.525731112119 }, { -0.447213595500,
0.723606797748, -0.525731112119 }, { -0.447213595500, -0.276393202252, -0.850650808354
},
+ { -1.0, 0.0, 0.0 } } ;
+int icos_v [20][3] = { { 0, 1, 2 }, { 0, 2, 3 }, { 0, 3, 4 }, { 0, 4, 5 }, { 0, 5, 1 },
+ { 1, 8, 2 }, { 2, 7, 3 }, { 3, 6, 4 }, { 4, 10, 5 }, { 5, 9, 1 },
+ { 1, 9, 8 }, { 2, 8, 7 }, { 3, 7, 6 }, { 4, 6, 10 }, { 5, 10, 9
},
+ { 11, 9, 10 }, { 11, 8, 9 }, { 11, 7, 8 }, { 11, 6, 7 }, { 11, 10,
6 } } ;
+
+void FGAPIENTRY glutWireIcosahedron( void )
+{
+ int i ;
+ for ( i = 0; i < 20; i++ )
+ {
+ double normal[3] ;
+ normal[0] = ( icos_r[icos_v[i][1]][1] - icos_r[icos_v[i][0]][1] ) * (
icos_r[icos_v[i][2]][2] - icos_r[icos_v[i][0]][2] ) - ( icos_r[icos_v[i][1]][2] -
icos_r[icos_v[i][0]][2] ) * ( icos_r[icos_v[i][2]][1] - icos_r[icos_v[i][0]][1] ) ;
+ normal[1] = ( icos_r[icos_v[i][1]][2] - icos_r[icos_v[i][0]][2] ) * (
icos_r[icos_v[i][2]][0] - icos_r[icos_v[i][0]][0] ) - ( icos_r[icos_v[i][1]][0] -
icos_r[icos_v[i][0]][0] ) * ( icos_r[icos_v[i][2]][2] - icos_r[icos_v[i][0]][2] ) ;
+ normal[2] = ( icos_r[icos_v[i][1]][0] - icos_r[icos_v[i][0]][0] ) * (
icos_r[icos_v[i][2]][1] - icos_r[icos_v[i][0]][1] ) - ( icos_r[icos_v[i][1]][1] -
icos_r[icos_v[i][0]][1] ) * ( icos_r[icos_v[i][2]][0] - icos_r[icos_v[i][0]][0] ) ;
+ glBegin ( GL_LINE_LOOP ) ;
+ glNormal3dv ( normal ) ;
+ glVertex3dv ( icos_r[icos_v[i][0]] ) ;
+ glVertex3dv ( icos_r[icos_v[i][1]] ) ;
+ glVertex3dv ( icos_r[icos_v[i][2]] ) ;
+ glEnd () ;
+ }
+}
+
+/*
+ *
+ */
+void FGAPIENTRY glutSolidIcosahedron( void )
+{
+ int i ;
+
+ glBegin ( GL_TRIANGLES ) ;
+ for ( i = 0; i < 20; i++ )
+ {
+ double normal[3] ;
+ normal[0] = ( icos_r[icos_v[i][1]][1] - icos_r[icos_v[i][0]][1] ) * (
icos_r[icos_v[i][2]][2] - icos_r[icos_v[i][0]][2] ) - ( icos_r[icos_v[i][1]][2] -
icos_r[icos_v[i][0]][2] ) * ( icos_r[icos_v[i][2]][1] - icos_r[icos_v[i][0]][1] ) ;
+ normal[1] = ( icos_r[icos_v[i][1]][2] - icos_r[icos_v[i][0]][2] ) * (
icos_r[icos_v[i][2]][0] - icos_r[icos_v[i][0]][0] ) - ( icos_r[icos_v[i][1]][0] -
icos_r[icos_v[i][0]][0] ) * ( icos_r[icos_v[i][2]][2] - icos_r[icos_v[i][0]][2] ) ;
+ normal[2] = ( icos_r[icos_v[i][1]][0] - icos_r[icos_v[i][0]][0] ) * (
icos_r[icos_v[i][2]][1] - icos_r[icos_v[i][0]][1] ) - ( icos_r[icos_v[i][1]][1] -
icos_r[icos_v[i][0]][1] ) * ( icos_r[icos_v[i][2]][0] - icos_r[icos_v[i][0]][0] ) ;
+ glNormal3dv ( normal ) ;
+ glVertex3dv ( icos_r[icos_v[i][0]] ) ;
+ glVertex3dv ( icos_r[icos_v[i][1]] ) ;
+ glVertex3dv ( icos_r[icos_v[i][2]] ) ;
+ }
+
+ glEnd () ;
+}
+
+/*
+ *
+ */
+double rdod_r[14][3] = { { 0.0, 0.0, 1.0 },
+ { 0.707106781187, 0.000000000000, 0.5 }, { 0.000000000000, 0.707106781187, 0.5 },
{ -0.707106781187, 0.000000000000, 0.5 }, { 0.000000000000, -0.707106781187, 0.5 },
+ { 0.707106781187, 0.707106781187, 0.0 }, { -0.707106781187, 0.707106781187, 0.0 },
{ -0.707106781187, -0.707106781187, 0.0 }, { 0.707106781187, -0.707106781187, 0.0 },
+ { 0.707106781187, 0.000000000000, -0.5 }, { 0.000000000000, 0.707106781187, -0.5 },
{ -0.707106781187, 0.000000000000, -0.5 }, { 0.000000000000, -0.707106781187, -0.5 },
+ { 0.0, 0.0, -1.0 } } ;
+int rdod_v [12][4] = { { 0, 1, 5, 2 }, { 0, 2, 6, 3 }, { 0, 3, 7, 4 }, { 0, 4,
8, 1 },
+ { 5, 10, 6, 2 }, { 6, 11, 7, 3 }, { 7, 12, 8, 4 }, { 8, 9,
5, 1 },
+ { 5, 9, 13, 10 }, { 6, 10, 13, 11 }, { 7, 11, 13, 12 }, { 8, 12,
13, 9 } } ;
+double rdod_n[12][3] = {
+ { 0.353553390594, 0.353553390594, 0.5 }, { -0.353553390594, 0.353553390594, 0.5 },
{ -0.353553390594, -0.353553390594, 0.5 }, { 0.353553390594, -0.353553390594, 0.5 },
+ { 0.000000000000, 1.000000000000, 0.0 }, { -1.000000000000, 0.000000000000, 0.0 },
{ 0.000000000000, -1.000000000000, 0.0 }, { 1.000000000000, 0.000000000000, 0.0 },
+ { 0.353553390594, 0.353553390594, -0.5 }, { -0.353553390594, 0.353553390594, -0.5 },
{ -0.353553390594, -0.353553390594, -0.5 }, { 0.353553390594, -0.353553390594, -0.5 }
+ } ;
+
+void FGAPIENTRY glutWireRhombicDodecahedron( void )
+{
+ int i ;
+ for ( i = 0; i < 12; i++ )
+ {
+ glBegin ( GL_LINE_LOOP ) ;
+ glNormal3dv ( rdod_n[i] ) ;
+ glVertex3dv ( rdod_r[rdod_v[i][0]] ) ;
+ glVertex3dv ( rdod_r[rdod_v[i][1]] ) ;
+ glVertex3dv ( rdod_r[rdod_v[i][2]] ) ;
+ glVertex3dv ( rdod_r[rdod_v[i][3]] ) ;
+ glEnd () ;
+ }
+}
+
+/*
+ *
+ */
+void FGAPIENTRY glutSolidRhombicDodecahedron( void )
+{
+ int i ;
+
+ glBegin ( GL_QUADS ) ;
+ for ( i = 0; i < 12; i++ )
+ {
+ glNormal3dv ( rdod_n[i] ) ;
+ glVertex3dv ( rdod_r[rdod_v[i][0]] ) ;
+ glVertex3dv ( rdod_r[rdod_v[i][1]] ) ;
+ glVertex3dv ( rdod_r[rdod_v[i][2]] ) ;
+ glVertex3dv ( rdod_r[rdod_v[i][3]] ) ;
+ }
+
+ glEnd () ;
+}
+
+#define NUM_FACES 4
+
+static GLdouble tetrahedron_v[4][3] = /* Vertices */
+{
+ { -0.5, -0.288675134595, -0.144337567297 },
+ { 0.5, -0.288675134595, -0.144337567297 },
+ { 0.0, 0.577350269189, -0.144337567297 },
+ { 0.0, 0.0, 0.672159013631 }
+} ;
+
+static GLint tetrahedron_i[4][3] = /* Vertex indices */
+{
+ { 0, 1, 2 }, { 0, 2, 3 }, { 0, 3, 1 }, { 1, 3, 2 }
+} ;
+
+static GLdouble tetrahedron_n[4][3] = /* Normals */
+{
+ { 0.0, 0.0, -1.0 },
+ { -0.816496580928, 0.471404520791, 0.333333333333 },
+ { 0.0, -0.942809041582, 0.333333333333 },
+ { 0.816496580928, 0.471404520791, 0.333333333333 }
+} ;
+
+void FGAPIENTRY glutWireSierpinskiSponge ( int num_levels, GLdouble offset[3], GLdouble
scale )
+{
+ int i, j ;
+
+ if ( num_levels == 0 )
+ {
+
+ for ( i = 0 ; i < NUM_FACES ; i++ )
+ {
+ glBegin ( GL_LINE_LOOP ) ;
+ glNormal3dv ( tetrahedron_n[i] ) ;
+ for ( j = 0; j < 3; j++ )
+ {
+ double x = offset[0] + scale * tetrahedron_v[tetrahedron_i[i][j]][0] ;
+ double y = offset[1] + scale * tetrahedron_v[tetrahedron_i[i][j]][1] ;
+ double z = offset[2] + scale * tetrahedron_v[tetrahedron_i[i][j]][2] ;
+ glVertex3d ( x, y, z ) ;
+ }
+
+ glEnd () ;
+ }
+ }
+ else
+ {
+ GLdouble local_offset[3] ; /* Use a local variable to avoid buildup of roundoff
errors */
+ num_levels -- ;
+ scale /= 2.0 ;
+ local_offset[0] = offset[0] + scale * tetrahedron_v[0][0] ;
+ local_offset[1] = offset[1] + scale * tetrahedron_v[0][1] ;
+ local_offset[2] = offset[2] + scale * tetrahedron_v[0][2] ;
+ glutWireSierpinskiSponge ( num_levels, local_offset, scale ) ;
+ local_offset[0] += scale ;
+ glutWireSierpinskiSponge ( num_levels, local_offset, scale ) ;
+ local_offset[0] -= 0.5 * scale ;
+ local_offset[1] += 0.866025403784 * scale ;
+ glutWireSierpinskiSponge ( num_levels, local_offset, scale ) ;
+ local_offset[1] -= 0.577350269189 * scale ;
+ local_offset[2] += 0.816496580928 * scale ;
+ glutWireSierpinskiSponge ( num_levels, local_offset, scale ) ;
+ }
+}
+
+void FGAPIENTRY glutSolidSierpinskiSponge ( int num_levels, GLdouble offset[3], GLdouble
scale )
+{
+ int i, j ;
+
+ if ( num_levels == 0 )
+ {
+ glBegin ( GL_TRIANGLES ) ;
+
+ for ( i = 0 ; i < NUM_FACES ; i++ )
+ {
+ glNormal3dv ( tetrahedron_n[i] ) ;
+ for ( j = 0; j < 3; j++ )
+ {
+ double x = offset[0] + scale * tetrahedron_v[tetrahedron_i[i][j]][0] ;
+ double y = offset[1] + scale * tetrahedron_v[tetrahedron_i[i][j]][1] ;
+ double z = offset[2] + scale * tetrahedron_v[tetrahedron_i[i][j]][2] ;
+ glVertex3d ( x, y, z ) ;
+ }
+ }
+
+ glEnd () ;
+ }
+ else
+ {
+ GLdouble local_offset[3] ; /* Use a local variable to avoid buildup of roundoff
errors */
+ num_levels -- ;
+ scale /= 2.0 ;
+ local_offset[0] = offset[0] + scale * tetrahedron_v[0][0] ;
+ local_offset[1] = offset[1] + scale * tetrahedron_v[0][1] ;
+ local_offset[2] = offset[2] + scale * tetrahedron_v[0][2] ;
+ glutSolidSierpinskiSponge ( num_levels, local_offset, scale ) ;
+ local_offset[0] += scale ;
+ glutSolidSierpinskiSponge ( num_levels, local_offset, scale ) ;
+ local_offset[0] -= 0.5 * scale ;
+ local_offset[1] += 0.866025403784 * scale ;
+ glutSolidSierpinskiSponge ( num_levels, local_offset, scale ) ;
+ local_offset[1] -= 0.577350269189 * scale ;
+ local_offset[2] += 0.816496580928 * scale ;
+ glutSolidSierpinskiSponge ( num_levels, local_offset, scale ) ;
+ }
+}
+
+#undef NUM_FACES
+
+/*** END OF FILE ***/
Index: external/trimesh/gluit/freeglut_teapot.c
--- external/trimesh/gluit/freeglut_teapot.c (revision 0)
+++ external/trimesh/gluit/freeglut_teapot.c (revision 0)
@@ -0,0 +1,207 @@
+/*
+ * freeglut_teapot.c
+ *
+ * Teapot(tm) rendering code.
+ *
+ * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
+ * Written by Pawel W. Olszta, <olszta(a)sourceforge.net>
+ * Creation date: Fri Dec 24 1999
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Original teapot code copyright follows:
+ */
+
+/*
+ * (c) Copyright 1993, Silicon Graphics, Inc.
+ *
+ * ALL RIGHTS RESERVED
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notice appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Silicon
+ * Graphics, Inc. not be used in advertising or publicity
+ * pertaining to distribution of the software without specific,
+ * written prior permission.
+ *
+ * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU
+ * "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR
+ * OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. IN NO
+ * EVENT SHALL SILICON GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE
+ * ELSE FOR ANY DIRECT, SPECIAL, INCIDENTAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER,
+ * INCLUDING WITHOUT LIMITATION, LOSS OF PROFIT, LOSS OF USE,
+ * SAVINGS OR REVENUE, OR THE CLAIMS OF THIRD PARTIES, WHETHER OR
+ * NOT SILICON GRAPHICS, INC. HAS BEEN ADVISED OF THE POSSIBILITY
+ * OF SUCH LOSS, HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * ARISING OUT OF OR IN CONNECTION WITH THE POSSESSION, USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ * US Government Users Restricted Rights
+ *
+ * Use, duplication, or disclosure by the Government is subject to
+ * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
+ * (c)(1)(ii) of the Rights in Technical Data and Computer
+ * Software clause at DFARS 252.227-7013 and/or in similar or
+ * successor clauses in the FAR or the DOD or NASA FAR
+ * Supplement. Unpublished-- rights reserved under the copyright
+ * laws of the United States. Contractor/manufacturer is Silicon
+ * Graphics, Inc., 2011 N. Shoreline Blvd., Mountain View, CA
+ * 94039-7311.
+ *
+ * OpenGL(TM) is a trademark of Silicon Graphics, Inc.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <GL/freeglut.h>
+#include "freeglut_internal.h"
+
+#include "freeglut_teapot_data.h"
+
+/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
+
+
+static void teapot( GLint grid, GLdouble scale, GLenum type )
+{
+#if TARGET_HOST_WINCE
+ int i, numV=sizeof(strip_vertices)/4, numI=sizeof(strip_normals)/4;
+#else
+ double p[4][4][3], q[4][4][3], r[4][4][3], s[4][4][3];
+ long i, j, k, l;
+#endif
+
+ glPushAttrib( GL_ENABLE_BIT | GL_EVAL_BIT );
+ glEnable( GL_AUTO_NORMAL );
+ glEnable( GL_NORMALIZE );
+ glEnable( GL_MAP2_VERTEX_3 );
+ glEnable( GL_MAP2_TEXTURE_COORD_2 );
+
+ glPushMatrix();
+ glRotated( 270.0, 1.0, 0.0, 0.0 );
+ glScaled( 0.5 * scale, 0.5 * scale, 0.5 * scale );
+ glTranslated( 0.0, 0.0, -1.5 );
+
+#if TARGET_HOST_WINCE
+ glRotated( 90.0, 1.0, 0.0, 0.0 );
+ glBegin( GL_TRIANGLE_STRIP );
+
+ for( i = 0; i < numV-1; i++ )
+ {
+ int vidx = strip_vertices[i],
+ nidx = strip_normals[i];
+
+ if( vidx != -1 )
+ {
+ glNormal3fv( normals[nidx] );
+ glVertex3fv( vertices[vidx] );
+ }
+ else
+ {
+ glEnd();
+ glBegin( GL_TRIANGLE_STRIP );
+ }
+ }
+
+ glEnd();
+#else
+ for (i = 0; i < 10; i++) {
+ for (j = 0; j < 4; j++) {
+ for (k = 0; k < 4; k++) {
+ for (l = 0; l < 3; l++) {
+ p[j][k][l] = cpdata[patchdata[i][j * 4 + k]][l];
+ q[j][k][l] = cpdata[patchdata[i][j * 4 + (3 - k)]][l];
+ if (l == 1)
+ q[j][k][l] *= -1.0;
+ if (i < 6) {
+ r[j][k][l] =
+ cpdata[patchdata[i][j * 4 + (3 - k)]][l];
+ if (l == 0)
+ r[j][k][l] *= -1.0;
+ s[j][k][l] = cpdata[patchdata[i][j * 4 + k]][l];
+ if (l == 0)
+ s[j][k][l] *= -1.0;
+ if (l == 1)
+ s[j][k][l] *= -1.0;
+ }
+ }
+ }
+ }
+
+ glMap2d(GL_MAP2_TEXTURE_COORD_2, 0.0, 1.0, 2, 2, 0.0, 1.0, 4, 2,
+ &tex[0][0][0]);
+ glMap2d(GL_MAP2_VERTEX_3, 0.0, 1.0, 3, 4, 0.0, 1.0, 12, 4,
+ &p[0][0][0]);
+ glMapGrid2d(grid, 0.0, 1.0, grid, 0.0, 1.0);
+ glEvalMesh2(type, 0, grid, 0, grid);
+ glMap2d(GL_MAP2_VERTEX_3, 0.0, 1.0, 3, 4, 0.0, 1.0, 12, 4,
+ &q[0][0][0]);
+ glEvalMesh2(type, 0, grid, 0, grid);
+ if (i < 6) {
+ glMap2d(GL_MAP2_VERTEX_3, 0.0, 1.0, 3, 4, 0.0, 1.0, 12, 4,
+ &r[0][0][0]);
+ glEvalMesh2(type, 0, grid, 0, grid);
+ glMap2d(GL_MAP2_VERTEX_3, 0.0, 1.0, 3, 4, 0.0, 1.0, 12, 4,
+ &s[0][0][0]);
+ glEvalMesh2(type, 0, grid, 0, grid);
+ }
+ }
+#endif /* TARGET_HOST_WINCE */
+
+ glPopMatrix();
+ glPopAttrib();
+}
+
+
+/* -- INTERFACE FUNCTIONS -------------------------------------------------- */
+
+/*
+ * Renders a beautiful wired teapot...
+ */
+void FGAPIENTRY glutWireTeapot( GLdouble size )
+{
+ /*
+ * We will use the general teapot rendering code
+ */
+ teapot( 10, size, GL_LINE );
+}
+
+/*
+ * Renders a beautiful filled teapot...
+ */
+void FGAPIENTRY glutSolidTeapot( GLdouble size )
+{
+ /*
+ * We will use the general teapot rendering code
+ */
+ teapot( 7, size, GL_FILL );
+}
+
+/*** END OF FILE ***/
+
+
+
+
+
Index: external/trimesh/Makedefs.SunOS
--- external/trimesh/Makedefs.SunOS (revision 0)
+++ external/trimesh/Makedefs.SunOS (revision 0)
@@ -0,0 +1,50 @@
+# Tested for gcc 3.3.2
+CC = gcc
+CXX = g++
+AR = ar
+
+ifdef DEBUG
+ COPTS += -ggdb3
+ COPTS += -Wall -W -Wno-unused -Wno-sign-compare -Wno-unknown-pragmas
+ CXXOPTS = $(COPTS)
+else
+ COPTS += -O3 -ffast-math -fomit-frame-pointer -funroll-loops
+ COPTS += -Wall -W -Wno-unused -Wno-sign-compare -Wno-unknown-pragmas
+ CXXOPTS = $(COPTS)
+ LDOPTS = -s
+endif
+
+CFLAGS = $(INCLUDES) $(DEFINES) $(COPTS)
+CXXFLAGS = $(INCLUDES) $(DEFINES) $(CXXOPTS)
+LDFLAGS = $(LIBDIR) $(LDOPTS)
+
+LIBS = -lm
+GLLIBS = -lgluit -lGL -lGLU -lX11 -lXmu
+
+$(OBJDIR)/%.o: %.c
+ @ echo "Compiling $<"
+ @ rm -f "$(@:.o=.d)" && env DEPENDENCIES_OUTPUT="$(@:.o=.d)
$@" $(CC) $(CFLAGS) -c $< -o $@
+
+$(OBJDIR)/%.o: %.cc
+ @ echo "Compiling $<"
+ @ rm -f "$(@:.o=.d)" && env DEPENDENCIES_OUTPUT="$(@:.o=.d)
$@" $(CXX) $(CXXFLAGS) -c $< -o $@
+
+define LINK
+ @ echo "Linking $@"
+ @ rm -f $@
+ @ $(CXX) $(CXXFLAGS) $^ $(LDFLAGS) $(LIBS) -o $@
+endef
+
+define STATICLIB
+ @ echo "Creating library $@"
+ @ rm -f $@
+ @ $(AR) -rcs $@ $^
+endef
+
+define SHAREDLIB
+ @ echo "Creating library $@"
+ @ rm -f $@
+ @ $(CXX) $(CXXFLAGS) -shared $^ -o $@
+endef
+
+-include $(OBJDIR)/*.d
Index: external/trimesh/utilsrc/mesh_shade.cc
--- external/trimesh/utilsrc/mesh_shade.cc (revision 0)
+++ external/trimesh/utilsrc/mesh_shade.cc (revision 0)
@@ -0,0 +1,507 @@
+/*
+Szymon Rusinkiewicz
+Princeton University
+
+mesh_shade.cc
+Apply procedural shaders to a mesh
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <cmath>
+#include <float.h>
+#include <algorithm>
+#include "TriMesh.h"
+#include "TriMesh_algo.h"
+#include "KDtree.h"
+#include "lineqn.h"
+using namespace std;
+
+#define BIGNUM 3.3e33
+
+#ifdef WIN32
+# ifndef strncasecmp
+# define strncasecmp strnicmp
+# endif
+#endif
+
+#ifdef DARWIN
+#define isfinite( x ) ( x <= FLT_MAX )
+#endif
+
+// Quick 'n dirty portable random number generator
+static inline float tinyrnd()
+{
+ static unsigned trand = 0;
+ trand = 1664525u * trand + 1013904223u;
+ return (float) trand / 4294967296.0f;
+}
+
+
+// Apply a solid color to the mesh
+void solidcolor(TriMesh *mesh, const char *col)
+{
+ unsigned c;
+ sscanf(col, "%x", &c);
+ int r = (c >> 16) & 0xff;
+ int g = (c >> 8) & 0xff;
+ int b = c & 0xff;
+ Color cc = Color(r,g,b);
+ int nv = mesh->vertices.size();
+ for (int i = 0; i < nv; i++)
+ mesh->colors[i] = cc;
+}
+
+
+// Color based on normals
+void colorbynormals(TriMesh *mesh)
+{
+ mesh->need_normals();
+ int nv = mesh->vertices.size();
+ for (int i = 0; i < nv; i++) {
+ mesh->colors[i] = Color(0.5f, 0.5f, 0.5f) +
+ 0.5f * mesh->normals[i];
+ }
+}
+
+
+// Compute a "feature size" for the mesh: computed as 1% of
+// the reciprocal of the 10-th percentile curvature
+float feature_size(TriMesh *mesh)
+{
+ mesh->need_curvatures();
+ int nv = mesh->curv1.size();
+ int nsamp = min(nv, 500);
+
+ vector<float> samples;
+ samples.reserve(nsamp * 2);
+
+ for (int i = 0; i < nsamp; i++) {
+ // Quick 'n dirty portable random number generator
+ static unsigned randq = 0;
+ randq = unsigned(1664525) * randq + unsigned(1013904223);
+
+ int ind = int(tinyrnd() * nv);
+ samples.push_back(fabs(mesh->curv1[ind]));
+ samples.push_back(fabs(mesh->curv2[ind]));
+ }
+ const float frac = 0.1f;
+ const float mult = 0.01f;
+ int which = int(frac * samples.size());
+ nth_element(samples.begin(), samples.begin() + which, samples.end());
+ float f = mult / samples[which];
+ if (!isfinite(f)) {
+ mesh->need_bsphere();
+ f = mesh->bsphere.r;
+ }
+
+ fprintf(stderr, "Feature size = %f\n", f);
+ return f;
+}
+
+
+// Color based on curvature
+void colorbycurv(TriMesh *mesh, const char *scale, const char *smooth)
+{
+ mesh->need_curvatures();
+ float smoothsigma = atof(smooth);
+ if (smoothsigma > 0.0f) {
+ smoothsigma *= mesh->feature_size();
+ diffuse_curv(mesh, smoothsigma);
+ }
+ float cscale = 10.0f * atof(scale) * feature_size(mesh);
+ TriMesh::dprintf("Using scale = %f\n", cscale);
+ cscale = sqr(cscale);
+
+ int nv = mesh->vertices.size();
+#pragma omp parallel for
+ for (int i = 0; i < nv; i++) {
+ float H = 0.5f * (mesh->curv1[i] + mesh->curv2[i]);
+ float K = mesh->curv1[i] * mesh->curv2[i];
+ float h = 4.0f / 3.0f * fabs(atan2(H*H-K,H*H*sgn(H)));
+ float s = M_2_PI * atan((2.0f*H*H-K)*cscale);
+ mesh->colors[i] = Color::hsv(h,s,1.0);
+ }
+}
+
+
+// Color based on curvature. Similar to above, but uses a grayscale mapping.
+void gcolorbycurv(TriMesh *mesh, const char *scale, const char *smooth)
+{
+ mesh->need_curvatures();
+ float smoothsigma = atof(smooth);
+ if (smoothsigma > 0.0f) {
+ smoothsigma *= mesh->feature_size();
+ diffuse_curv(mesh, smoothsigma);
+ }
+ float cscale = 10.0f * atof(scale) * feature_size(mesh);
+ TriMesh::dprintf("Using scale = %f\n", cscale);
+
+ int nv = mesh->vertices.size();
+#pragma omp parallel for
+ for (int i = 0; i < nv; i++) {
+ float H = 0.5f * (mesh->curv1[i] + mesh->curv2[i]);
+ mesh->colors[i] = Color(float((atan(H*cscale) + M_PI_2) / M_PI));
+ }
+}
+
+
+// Accessibility shading
+void acc(TriMesh *mesh, const char *maxsize_, const char *offset_)
+{
+ mesh->need_normals();
+ float fs = feature_size(mesh);
+ float maxsize = atof(maxsize_) * fs;
+ float offset = atof(offset_) * fs;
+ TriMesh::dprintf("Using maxsize = %f, offset = %f\n", maxsize, offset);
+
+ KDtree *kd = new KDtree(mesh->vertices);
+ int nv = mesh->vertices.size();
+#pragma omp parallel for
+ for (int i = 0; i < nv; i++) {
+ const vec &n = mesh->normals[i];
+ point p = mesh->vertices[i] + offset * n;
+ float tmin = 0, tmax = maxsize;
+ for (int iter = 0; iter < 8; iter++) {
+ float tmid = 0.5f * (tmin + tmax);
+ point q = p + tmid * n;
+ const float *qq = kd->closest_to_pt(q, sqr(tmid));
+ if (qq)
+ tmax = tmid;
+ else
+ tmin = tmid;
+ }
+ mesh->colors[i] = Color(0.5f * (tmin + tmax));
+ }
+ delete kd;
+}
+
+
+// Color by distance to bdy
+void bdyshade(TriMesh *mesh, const char *nedges_)
+{
+ int nedges = atoi(nedges_) + 1;
+ int nv = mesh->vertices.size();
+ mesh->need_neighbors();
+ mesh->flags.resize(nv);
+ for (int i = 0; i < nv; i++)
+ mesh->flags[i] = mesh->is_bdy(i) ? 0 : nedges;
+ for (int iter = 1; iter < nedges; iter++) {
+ for (int i = 0; i < nv; i++) {
+ for (int j = 0; j < mesh->neighbors[i].size(); j++) {
+ int n = mesh->neighbors[i][j];
+ if (mesh->flags[n] + 1 < mesh->flags[i])
+ mesh->flags[i] = mesh->flags[n] + 1;
+ }
+ }
+ }
+#pragma omp parallel for
+ for (int i = 0; i < nv; i++) {
+ float c = (float) mesh->flags[i] / nedges;
+ mesh->colors[i] = Color(1.0f, c, c);
+ }
+}
+
+
+// Helper for dist2mesh:
+// Find closest point to p on segment from v0 to v1
+point closest_on_segment(const point &v0, const point &v1, const point &p)
+{
+ vec v01 = v1 - v0;
+ float d = (p - v0) DOT v01;
+ d /= len2(v01);
+ if (d < 0.0f)
+ d = 0.0f;
+ else if (d > 1.0f)
+ d = 1.0f;
+ return v0 + d * v01;
+}
+
+
+// Helper for dist2mesh:
+// Find closest point to p on face i of mesh
+point closest_on_face(const TriMesh *mesh, int i, const point &p)
+{
+ const TriMesh::Face &f = mesh->faces[i];
+ const point &v0 = mesh->vertices[f[0]];
+ const point &v1 = mesh->vertices[f[1]];
+ const point &v2 = mesh->vertices[f[2]];
+ vec a = v1 - v0, b = v2 - v0, p1 = p - v0, n = a CROSS b;
+
+ float A[3][3] = { { a[0], b[0], n[0] },
+ { a[1], b[1], n[1] },
+ { a[2], b[2], n[2] } };
+ float x[3] = { p1[0], p1[1], p1[2] };
+ int indx[3];
+ ludcmp<float,3>(A, indx);
+ lubksb<float,3>(A, indx, x);
+
+ if (x[0] >= 0.0f && x[1] >= 0.0f && x[0] + x[1] <= 1.0f)
+ return v0 + x[0] * a + x[1] * b;
+
+ point c01 = closest_on_segment(v0, v1, p);
+ point c12 = closest_on_segment(v1, v2, p);
+ point c20 = closest_on_segment(v2, v0, p);
+ float d01 = dist2(c01, p);
+ float d12 = dist2(c12, p);
+ float d20 = dist2(c20, p);
+ if (d01 < d12) {
+ if (d01 < d20) return c01; else return c20;
+ } else {
+ if (d12 < d20) return c12; else return c20;
+ }
+}
+
+
+// Helper for dist2mesh:
+// Find (good approximation to) closest point on mesh to p.
+// Finds closest vertex, then checks all faces that touch it.
+bool find_closest_pt(const TriMesh *mesh, const KDtree *kd, const point &p,
+ float maxdist2, point &pmatch)
+{
+ const float *match = kd->closest_to_pt(p, maxdist2);
+ if (!match)
+ return false;
+ int ind = (match - (const float *) &(mesh->vertices[0][0])) / 3;
+ if (ind < 0 || ind >= mesh->vertices.size())
+ return false;
+
+ const vector<int> &a = mesh->adjacentfaces[ind];
+ if (a.empty()) {
+ pmatch = mesh->vertices[ind];
+ return true;
+ }
+
+ float closest_dist2 = BIGNUM;
+ for (int i = 0; i < a.size(); i++) {
+ point c = closest_on_face(mesh, a[i], p);
+ float this_dist2 = dist2(c, p);
+ if (this_dist2 < closest_dist2) {
+ closest_dist2 = this_dist2;
+ pmatch = c;
+ }
+ }
+ return (closest_dist2 != BIGNUM);
+}
+
+
+// Color by distance to another mesh
+void dist2mesh(TriMesh *mesh, const char *filename, const char *maxdist_)
+{
+ TriMesh *othermesh = TriMesh::read(filename);
+ if (!othermesh) {
+ fprintf(stderr, "Couldn't read %s\n", filename);
+ exit(1);
+ }
+ othermesh->need_adjacentfaces();
+ KDtree *kd = new KDtree(othermesh->vertices);
+
+ float fs = feature_size(mesh);
+ float maxdist = atof(maxdist_) * fs;
+ TriMesh::dprintf("Using maxdist = %f\n", maxdist);
+ float maxdist2 = sqr(maxdist);
+
+ int nv = mesh->vertices.size();
+#pragma omp parallel for
+ for (int i = 0; i < nv; i++) {
+ const point &p = mesh->vertices[i];
+ point pmatch;
+ float d = maxdist;
+ if (find_closest_pt(othermesh, kd, p, maxdist2, pmatch))
+ d = dist(p, pmatch);
+ d /= maxdist;
+ float H = 4.0f * (1.0f - d);
+ float S = 0.7f + 0.3f * d;
+ float V = 0.7f + 0.3f * d;
+ mesh->colors[i] = Color::hsv(H,S,V);
+ }
+ delete kd;
+ delete othermesh;
+}
+
+
+// Color by distance to given vertex
+void findvert(TriMesh *mesh, const char *v_, const char *nedges_)
+{
+ int v = atoi(v_);
+ int nedges = atoi(nedges_) + 1;
+ int nv = mesh->vertices.size();
+ mesh->need_neighbors();
+ mesh->flags.resize(nv);
+ for (int i = 0; i < nv; i++)
+ mesh->flags[i] = (i == v) ? 0 : nedges;
+ for (int iter = 1; iter < nedges; iter++) {
+ for (int i = 0; i < nv; i++) {
+ for (int j = 0; j < mesh->neighbors[i].size(); j++) {
+ int n = mesh->neighbors[i][j];
+ if (mesh->flags[n] + 1 < mesh->flags[i])
+ mesh->flags[i] = mesh->flags[n] + 1;
+ }
+ }
+ }
+#pragma omp parallel for
+ for (int i = 0; i < nv; i++) {
+ float c = (float) mesh->flags[i] / nedges;
+ mesh->colors[i] = Color(1.0f, c, c);
+ }
+}
+
+
+// Adjust colors
+void remapcolor(TriMesh *mesh, const char *scale_, const char *off_,
+ const char *gamma_)
+{
+ float scale = atof(scale_);
+ float off = atof(off_);
+ float gamma = 1.0f / atof(gamma_);
+ int nv = mesh->vertices.size();
+#pragma omp parallel for
+ for (int i = 0; i < nv; i++) {
+ Color &c = mesh->colors[i];
+ c[0] = pow(c[0] * scale + off, gamma);
+ c[1] = pow(c[1] * scale + off, gamma);
+ c[2] = pow(c[2] * scale + off, gamma);
+ }
+}
+
+
+// Color based on depth in direction (x,y,z)
+// To find range, eliminates percentage p of points
+void colorbydepth(TriMesh *mesh, const char *x_, const char *y_,
+ const char *z_, const char *p_)
+{
+ vec dir(atof(x_), atof(y_), atof(z_));
+ float p = atof(p_);
+
+ int nv = mesh->vertices.size();
+ vector<float> depths(nv);
+#pragma omp parallel for
+ for (int i = 0; i < nv; i++)
+ depths[i] = mesh->vertices[i] DOT dir;
+
+ float mind, maxd;
+ if (p > 0.0f) {
+ int which = int(p * nv);
+ nth_element(depths.begin(), depths.begin() + which, depths.end());
+ mind = depths[which];
+
+ which = nv - 1 - which;
+ nth_element(depths.begin(), depths.begin() + which, depths.end());
+ maxd = depths[which];
+ } else {
+ mind = *min_element(depths.begin(), depths.end());
+ maxd = *max_element(depths.begin(), depths.end());
+ }
+ float mult = 1.0f / (maxd - mind);
+ for (int i = 0; i < nv; i++) {
+ float d = mesh->vertices[i] DOT dir;
+ mesh->colors[i] = Color(mult * (d - mind));
+ }
+}
+
+
+void usage(const char *myname)
+{
+ fprintf(stderr, "Usage: %s model shader [options] outfile\n", myname);
+ fprintf(stderr, "Shaders:\n");
+ fprintf(stderr, " color rrggbb Solid color (specified in hex)\n");
+ fprintf(stderr, " normals Colored based on normals (r = nx, etc.)\n");
+ fprintf(stderr, " curv sc sm Colored based on curvature (args = scale,
smoothing)\n");
+ fprintf(stderr, " gcurv sc sm Grayscale based on curvature (args = scale,
smoothing)\n");
+ fprintf(stderr, " acc max off Accessibility (args = maximum size,
offset)\n");
+ fprintf(stderr, " bdy max Distance to boundary (arg = maximum # edges)\n");
+ fprintf(stderr, " dist m.ply max Distance to another mesh (args = mesh, max
distance)\n");
+ fprintf(stderr, " findvert v max Distance to vertex (args = vert #, max
distance)\n");
+ fprintf(stderr, " remap s o g Remap existing colors (args = scale, offset,
gamma)\n");
+ fprintf(stderr, " depth x y z p Color by depth in dir (x,y,z); clamp fraction
p\n");
+ exit(1);
+}
+
+int main(int argc, char *argv[])
+{
+ if (argc < 4)
+ usage(argv[0]);
+ const char *infilename = argv[1];
+
+ TriMesh *themesh = TriMesh::read(infilename);
+ if (!themesh)
+ usage(argv[0]);
+ themesh->colors.resize(themesh->vertices.size());
+
+ const char *shader = argv[2];
+ const char *outfilename = argv[3];
+ if (!strncasecmp(shader, "col", 3)) {
+ if (argc < 5) {
+ fprintf(stderr, "\n\"color\" needs one argument\n\n");
+ usage(argv[0]);
+ }
+ solidcolor(themesh, argv[3]);
+ outfilename = argv[4];
+ } else if (!strncasecmp(shader, "norm", 4)) {
+ colorbynormals(themesh);
+ } else if (!strncasecmp(shader, "curv", 4)) {
+ if (argc < 6) {
+ fprintf(stderr, "\n\"curv\" needs two arguments\n\n");
+ usage(argv[0]);
+ }
+ colorbycurv(themesh, argv[3], argv[4]);
+ outfilename = argv[5];
+ } else if (!strncasecmp(shader, "gcurv", 5)) {
+ if (argc < 6) {
+ fprintf(stderr, "\n\"gcurv\" needs two arguments\n\n");
+ usage(argv[0]);
+ }
+ gcolorbycurv(themesh, argv[3], argv[4]);
+ outfilename = argv[5];
+ } else if (!strncasecmp(shader, "acc", 3)) {
+ if (argc < 6) {
+ fprintf(stderr, "\n\"acc\" needs two arguments\n\n");
+ usage(argv[0]);
+ }
+ acc(themesh, argv[3], argv[4]);
+ outfilename = argv[5];
+ } else if (!strncasecmp(shader, "bdy", 3)) {
+ if (argc < 5) {
+ fprintf(stderr, "\n\"bdy\" needs one argument\n\n");
+ usage(argv[0]);
+ }
+ bdyshade(themesh, argv[3]);
+ outfilename = argv[4];
+ } else if (!strncasecmp(shader, "dist", 4)) {
+ if (argc < 6) {
+ fprintf(stderr, "\n\"dist\" needs two arguments\n\n");
+ usage(argv[0]);
+ }
+ dist2mesh(themesh, argv[3], argv[4]);
+ outfilename = argv[5];
+ } else if (!strncasecmp(shader, "findv", 5)) {
+ if (argc < 6) {
+ fprintf(stderr, "\n\"findvert\" needs two arguments\n\n");
+ usage(argv[0]);
+ }
+ findvert(themesh, argv[3], argv[4]);
+ outfilename = argv[5];
+ } else if (!strncasecmp(shader, "remap", 5)) {
+ if (argc < 7) {
+ fprintf(stderr, "\n\"remap\" needs three arguments\n\n");
+ usage(argv[0]);
+ }
+ remapcolor(themesh, argv[3], argv[4], argv[5]);
+ outfilename = argv[6];
+ } else if (!strncasecmp(shader, "depth", 5)) {
+ if (argc < 8) {
+ fprintf(stderr, "\n\"depth\" needs four arguments\n\n");
+ usage(argv[0]);
+ }
+ colorbydepth(themesh, argv[3], argv[4], argv[5], argv[6]);
+ outfilename = argv[7];
+ } else {
+ fprintf(stderr,"\nUnknown shader [%s]\n\n", shader);
+ usage(argv[0]);
+ }
+
+ themesh->write(outfilename);
+}
+
+
Index: external/trimesh/utilsrc/mesh_cc.cc
--- external/trimesh/utilsrc/mesh_cc.cc (revision 0)
+++ external/trimesh/utilsrc/mesh_cc.cc (revision 0)
@@ -0,0 +1,333 @@
+/*
+Szymon Rusinkiewicz
+Princeton University
+
+mesh_cc.cc
+Determine the connected components of a mesh, and possibly write
+out only selected components of the object.
+
+Does the same thing as "plycomps", part of the plytools package by Greg Turk.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "TriMesh.h"
+#include "TriMesh_algo.h"
+#include <vector>
+#include <stack>
+#include <algorithm>
+using namespace std;
+
+
+#define BIGNUM 2147483647
+#define NO_COMP -1
+#define FOR_EACH_ADJACENT_FACE(mesh,v,f) \
+ for (int f_ind = 0, f = mesh->adjacentfaces[v][0]; \
+ (f_ind < mesh->adjacentfaces[v].size()) && \
+ ((f = mesh->adjacentfaces[v][f_ind]) || 1); \
+ f_ind++)
+
+
+bool conn_vert = false; // Consider connectivity along vertices? (else edges)
+int nprint = 20; // Default # of CCs to print
+
+
+// Are two faces connected along an edge (or vertex)?
+bool connected(const TriMesh *in, int f1, int f2)
+{
+ int f10=in->faces[f1][0], f11=in->faces[f1][1], f12=in->faces[f1][2];
+ int f20=in->faces[f2][0], f21=in->faces[f2][1], f22=in->faces[f2][2];
+
+ if (conn_vert)
+ return f10 == f20 || f10 == f21 || f10 == f22 ||
+ f11 == f20 || f11 == f21 || f11 == f22 ||
+ f12 == f20 || f12 == f21 || f12 == f22;
+ else
+ return (f10 == f20 && (f11 == f22 || f12 == f21)) ||
+ (f10 == f21 && (f11 == f20 || f12 == f22)) ||
+ (f10 == f22 && (f11 == f21 || f12 == f20)) ||
+ (f11 == f20 && f12 == f22) ||
+ (f11 == f21 && f12 == f20) ||
+ (f11 == f22 && f12 == f21);
+}
+
+
+// Helper function for find_comps, below. Finds and marks all the faces
+// connected to f.
+void find_connected(const TriMesh *in,
+ vector<int> &comps, vector<int> &compsizes,
+ int f, int whichcomponent)
+{
+ stack<int> s;
+ s.push(f);
+ while (!s.empty()) {
+ int currface = s.top();
+ s.pop();
+ for (int i = 0; i < 3; i++) {
+ int vert = in->faces[currface][i];
+ FOR_EACH_ADJACENT_FACE(in, vert, adjface) {
+ if (comps[adjface] != NO_COMP ||
+ !connected(in, adjface, currface))
+ continue;
+ comps[adjface] = whichcomponent;
+ compsizes[whichcomponent]++;
+ s.push(adjface);
+ }
+ }
+ }
+}
+
+
+// Find the connected components of TriMesh "in".
+// Outputs:
+// comps is a vector that gives a mapping from each face to its
+// associated connected component.
+// compsizes holds the size of each connected component
+void find_comps(TriMesh *in, vector<int> &comps, vector<int>
&compsizes)
+{
+ if (in->vertices.empty())
+ return;
+ if (in->faces.empty())
+ return;
+ in->need_adjacentfaces();
+
+ int nf = in->faces.size();
+ comps.clear();
+ comps.reserve(nf);
+ comps.resize(nf, NO_COMP);
+ compsizes.clear();
+
+ for (int i = 0; i < nf; i++) {
+ if (comps[i] != NO_COMP)
+ continue;
+ int comp = compsizes.size();
+ comps[i] = comp;
+ compsizes.push_back(1);
+ find_connected(in, comps, compsizes, i, comp);
+ }
+}
+
+
+// Helper class for comparing two integers by finding the elements at those
+// indices within some array and comparing them
+template <class Array>
+class CompareArrayElements {
+private:
+ const Array &a;
+public:
+ CompareArrayElements(const Array &_a) : a(_a)
+ {}
+ bool operator () (int i1, int i2) const
+ {
+ return (a[i1] > a[i2]);
+ }
+};
+
+
+// Sorts the connected components from largest to smallest. Renumbers the
+// elements of compsizes to reflect this new numbering.
+void sort_comps(vector<int> &comps, vector<int> &compsizes)
+{
+ if (compsizes.size() < 1)
+ return;
+
+ int i;
+ vector<int> comp_pointers(compsizes.size());
+ for (i = 0; i < comp_pointers.size(); i++)
+ comp_pointers[i] = i;
+
+ sort(comp_pointers.begin(), comp_pointers.end(),
+ CompareArrayElements< vector<int> >(compsizes));
+
+ vector<int> remap_table(comp_pointers.size());
+ for (i = 0; i < comp_pointers.size(); i++)
+ remap_table[comp_pointers[i]] = i;
+ for (i = 0; i < comps.size(); i++)
+ comps[i] = remap_table[comps[i]];
+
+ vector<int> newcompsizes(compsizes.size());
+ for (i = 0; i < compsizes.size(); i++)
+ newcompsizes[i] = compsizes[comp_pointers[i]];
+ compsizes = newcompsizes;
+}
+
+
+// Print out the connected components that are bigger than morethan and
+// smaller than lessthan. The largest min(nprint, total) components are
+// printed out, unless morethan == 0 and lessthan != BIGNUM, in which case
+// the smallest min(nprint, total) components are printed
+void print_comps(const vector<int> &comps, const vector<int>
&compsizes,
+ int morethan, int lessthan, int total)
+{
+ printf("%lu connected components total.\n",
+ (unsigned long) compsizes.size());
+
+ if (compsizes.size() < 1 || total < 1)
+ return;
+ int numtoprint = min(min(nprint, total), (int)compsizes.size());
+
+ if (morethan == 0 && lessthan != BIGNUM) {
+ // Print numtoprint smallest components
+ for (int i = 0; i < numtoprint; i++)
+ printf(" Component #%d - %d faces\n", i+1,
compsizes[compsizes.size()-1-i]);
+ } else {
+ // Print numtoprint largest components
+ for (int i = 0; i < numtoprint; i++)
+ printf(" Component #%d - %d faces\n", i+1, compsizes[i]);
+ }
+ if (numtoprint != compsizes.size())
+ printf(" ...\n");
+}
+
+
+// Select a particular connected component, and delete all other vertices from
+// the mesh.
+void select_comp(TriMesh *in, const vector<int> &comps, int whichcc)
+{
+ int numfaces = in->faces.size();
+ vector<bool> toremove(numfaces, false);
+ for (int i = 0; i < in->faces.size(); i++) {
+ if (comps[i] != whichcc)
+ toremove[i] = true;
+ }
+
+ remove_faces(in, toremove);
+ remove_unused_vertices(in);
+}
+
+
+// Select the requested connected components (as given by the "morethan",
+// "lessthan", and "total" parameters), and delete all other vertices
from
+// the mesh.
+void select_comps_by_size(TriMesh *in, const vector<int> &comps,
+ const vector<int> &compsizes,
+ int morethan, int lessthan, int total)
+{
+ if (compsizes.size() < 1 || total < 1)
+ return;
+ if (compsizes.size() == 1 &&
+ (compsizes[0] > lessthan || compsizes[0] < morethan)) {
+ in->faces.clear();
+ in->vertices.clear();
+ return;
+ }
+
+ int keep_first = 0;
+ while (keep_first < compsizes.size() && compsizes[keep_first] > lessthan)
+ keep_first++;
+ int keep_last = compsizes.size()-1;
+ while (keep_last > -1 && compsizes[keep_last] < morethan)
+ keep_last--;
+ if (keep_last-keep_first+1 > total) {
+ if (morethan == 0 && lessthan != BIGNUM) {
+ // Keep the smallest components
+ keep_first = keep_last+1-total;
+ } else {
+ // Keep the largest components
+ keep_last = keep_first+total-1;
+ }
+ }
+
+ int numfaces = in->faces.size();
+ vector<bool> toremove(numfaces, false);
+ for (int i = 0; i < numfaces; i++) {
+ if (comps[i] < keep_first || comps[i] > keep_last)
+ toremove[i] = true;
+ }
+
+ remove_faces(in, toremove);
+ remove_unused_vertices(in);
+}
+
+
+void usage(const char *myname)
+{
+ fprintf(stderr, "Usage: %s [options] in.ply [out.ply]\n", myname);
+ fprintf(stderr, "Options:\n");
+ fprintf(stderr, " -v Base connectivity on vertices, not edges\n");
+ fprintf(stderr, " -a Print sizes of ALL the components\n");
+ fprintf(stderr, " -s Split components into separate files\n");
+ fprintf(stderr, " -m n Select components with >= n faces\n");
+ fprintf(stderr, " -l n Select components with <= n faces\n");
+ fprintf(stderr, " -t n Select the largest n components\n");
+ exit(1);
+}
+
+
+int main(int argc, char *argv[])
+{
+ // Parse command line
+ int morethan = 0;
+ int lessthan = BIGNUM;
+ int total = BIGNUM;
+ bool splitcc = false;
+ const char *infilename=NULL, *outfilename=NULL;
+
+ int c;
+ while ((c = getopt(argc, argv, "hvasm:l:t:")) != EOF) {
+ switch (c) {
+ case 'v': conn_vert = true; break;
+ case 'a': nprint = BIGNUM; break;
+ case 's': splitcc = true; break;
+ case 'm': morethan = atoi(optarg); break;
+ case 'l': lessthan = atoi(optarg); break;
+ case 't': total = atoi(optarg); break;
+ default: usage(argv[0]);
+ }
+ }
+ if (argc - optind < 1)
+ usage(argv[0]);
+ infilename = argv[optind];
+ if (argc - optind >= 2)
+ outfilename = argv[optind+1];
+
+ // Read input file
+ TriMesh *in = TriMesh::read(infilename);
+ if (!in) {
+ fprintf(stderr, "Couldn't read input %s\n", infilename);
+ exit(1);
+ }
+ bool had_tstrips = !in->tstrips.empty();
+ in->need_faces();
+ in->tstrips.clear();
+
+ // Find connected components
+ vector<int> comps;
+ vector<int> compsizes;
+ find_comps(in, comps, compsizes);
+ sort_comps(comps, compsizes);
+
+ // Print out the top few components
+ print_comps(comps, compsizes, morethan, lessthan, total);
+
+ // Exit here if just printing things out, and not saving anything
+ if (!outfilename)
+ exit(0);
+
+ // Get rid of the junk we don't want...
+ select_comps_by_size(in, comps, compsizes, morethan, lessthan, total);
+
+ if (splitcc) {
+ // Hack...
+ find_comps(in, comps, compsizes);
+ sort_comps(comps, compsizes);
+
+ // Split into separate files, if requested
+ for (int i = 0; i < compsizes.size(); i++) {
+ TriMesh *tmp = new TriMesh(*in);
+ select_comp(tmp, comps, i);
+ if (had_tstrips)
+ tmp->need_tstrips();
+ char filename[1024];
+ sprintf(filename, "cc%d-%s", i+1, outfilename);
+ tmp->write(filename);
+ delete tmp;
+ }
+ } else {
+ // Write the requested components to a file
+ if (had_tstrips)
+ in->need_tstrips();
+ in->write(outfilename);
+ }
+}
Index: external/trimesh/utilsrc/mesh_filter.cc
--- external/trimesh/utilsrc/mesh_filter.cc (revision 0)
+++ external/trimesh/utilsrc/mesh_filter.cc (revision 0)
@@ -0,0 +1,394 @@
+/*
+Szymon Rusinkiewicz
+Princeton University
+
+mesh_filter.cc
+Apply a variety of tranformations to a mesh
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "TriMesh.h"
+#include "TriMesh_algo.h"
+#include "XForm.h"
+using namespace std;
+
+#ifndef M_PI
+# define M_PI 3.14159265358979323846
+#endif
+
+
+// Is this argument a floatint-point number?
+static bool isanumber(const char *c)
+{
+ if (!c || !*c)
+ return false;
+ char *endptr;
+ strtod(c, &endptr);
+ return (endptr && *endptr == '\0');
+}
+
+
+// Is this argument an integer?
+static bool isanint(const char *c)
+{
+ if (!c || !*c)
+ return false;
+ char *endptr;
+ strtol(c, &endptr, 10);
+ return (endptr && *endptr == '\0');
+}
+
+
+// Transform the mesh by a matrix read from a file
+void apply_xform(TriMesh *mesh, const char *xffilename)
+{
+ xform xf;
+ if (!xf.read(xffilename))
+ fprintf(stderr, "Couldn't open %s\n", xffilename);
+ else
+ apply_xform(mesh, xf);
+}
+
+
+// Transform the mesh by inverse of a matrix read from a file
+void apply_ixform(TriMesh *mesh, const char *xffilename)
+{
+ xform xf;
+ if (!xf.read(xffilename)) {
+ fprintf(stderr, "Couldn't open %s\n", xffilename);
+ } else {
+ invert(xf);
+ apply_xform(mesh, xf);
+ }
+}
+
+
+// Clip mesh to the given bounding box file
+bool clip(TriMesh *mesh, const char *bboxfilename)
+{
+ FILE *f = fopen(bboxfilename, "r");
+ if (!f) {
+ fprintf(stderr, "Couldn't open %s\n", bboxfilename);
+ return false;
+ }
+
+ TriMesh::BBox b;
+ if (fscanf(f, "%f%f%f%f%f%f",
+ &b.min[0], &b.min[1], &b.min[2],
+ &b.max[0], &b.max[1], &b.max[2]) != 6) {
+ fclose(f);
+ fprintf(stderr, "Couldn't read %s\n", bboxfilename);
+ return false;
+ }
+ fclose(f);
+
+ if (b.min[0] > b.max[0]) swap(b.min[0], b.max[0]);
+ if (b.min[1] > b.max[1]) swap(b.min[1], b.max[1]);
+ if (b.min[2] > b.max[2]) swap(b.min[2], b.max[2]);
+
+ clip(mesh, b);
+ return true;
+}
+
+
+void usage(const char *myname)
+{
+ fprintf(stderr, "Usage: %s infile [options] [outfile]\n", myname);
+ fprintf(stderr, "Options:\n");
+ fprintf(stderr, " -color Add per-vertex color\n");
+ fprintf(stderr, " -nocolor Remove per-vertex color\n");
+ fprintf(stderr, " -conf Add per-vertex confidence\n");
+ fprintf(stderr, " -noconf Remove per-vertex confidence\n");
+ fprintf(stderr, " -tstrip Convert to use triangle strips\n");
+ fprintf(stderr, " -notstrip Unpack triangle strips to faces\n");
+ fprintf(stderr, " -nogrid Unpack range grid to faces\n");
+ fprintf(stderr, " -reorder Optimize order of vertices\n");
+ fprintf(stderr, " -orient Auto-orient faces within the mesh\n");
+ fprintf(stderr, " -faceflip Flip the order of vertices within each face\n");
+ fprintf(stderr, " -edgeflip Optimize triangle connectivity by flipping
edges\n");
+ fprintf(stderr, " -subdiv Subdivide faces (planar)\n");
+ fprintf(stderr, " -loop Perform Loop subdivision\n");
+ fprintf(stderr, " -fly Perform butterfly subdivision\n");
+ fprintf(stderr, " -smooth s Smooth surface with sigma=s*edgelength\n");
+ fprintf(stderr, " -bilat sd sr Bilateral surface smoothing with domain, range
sigmas\n");
+ fprintf(stderr, " -sharpen s Sharpen surface with sigma=s*edgelength\n");
+ fprintf(stderr, " -smoothnorm s Diffuse normals with sigma=s*edgelength\n");
+ fprintf(stderr, " -usmooth n Perform n iterations of simple umbrella
smoothing\n");
+ fprintf(stderr, " -lmsmooth n Perform n iterations of Taubin's lambda-mu
smoothing\n");
+ fprintf(stderr, " -inflate s Create offset surface s*edgelength away\n");
+ fprintf(stderr, " -noisify s Add O(s*edgelength) noise to each vertex\n");
+ fprintf(stderr, " -clip bbox Clip to the given bbox (file has 6 numbers)\n");
+ fprintf(stderr, " -xform file.xf Transform by the given matrix\n");
+ fprintf(stderr, " -ixform file.xf Transform by inverse of matrix\n");
+ fprintf(stderr, " -rot r x y z Rotate r degrees around axis (x,y,z)\n");
+ fprintf(stderr, " -trans x y z Translate by (x,y,z)\n");
+ fprintf(stderr, " -scale s Uniform scale by s\n");
+ fprintf(stderr, " -scale x y z Scale by (x,y,z)\n");
+ fprintf(stderr, " -scale s x y z Scale by s in direction (x,y,z)\n");
+ fprintf(stderr, " -center Translate so center of mass is at (0,0,0)\n");
+ fprintf(stderr, " -bbcenter Translate so center of bbox is at (0,0,0)\n");
+ fprintf(stderr, " -varnorm Scale so variance (RMS distance) from center is
1\n");
+ fprintf(stderr, " -bbnorm Scale so bbox has maximum extent 1\n");
+ fprintf(stderr, " -pcarot Rotate so that principal axes lie along X, Y,
Z\n");
+ fprintf(stderr, " -pcasnap As above, but only rotate by 90/180 degrees\n");
+ fprintf(stderr, " -rmunused Remove unreferenced vertices\n");
+ fprintf(stderr, " -rmslivers Remove long, skinny faces\n");
+ fprintf(stderr, " -erode Enlarge boundaries by removing boundary
vertices\n");
+ exit(1);
+}
+
+int main(int argc, char *argv[])
+{
+ if (argc < 3)
+ usage(argv[0]);
+ const char *filename = argv[1];
+
+ TriMesh *themesh = TriMesh::read(filename);
+ if (!themesh)
+ usage(argv[0]);
+
+ bool have_tstrips = !themesh->tstrips.empty();
+ for (int i = 2; i < argc; i++) {
+ if (!strcmp(argv[i], "-color") ||
+ !strcmp(argv[i], "-colors")) {
+ if (themesh->colors.empty()) {
+ int nv = themesh->vertices.size();
+ themesh->colors.resize(nv, Color::white());
+ }
+ } else if (!strcmp(argv[i], "-nocolor") ||
+ !strcmp(argv[i], "-nocolors")) {
+ themesh->colors.clear();
+ } else if (!strcmp(argv[i], "-conf")) {
+ if (themesh->confidences.empty()) {
+ int nv = themesh->vertices.size();
+ themesh->confidences.resize(nv, 1);
+ }
+ } else if (!strcmp(argv[i], "-noconf")) {
+ themesh->confidences.clear();
+ } else if (!strcmp(argv[i], "-tstrip") ||
+ !strcmp(argv[i], "-tstrips") ||
+ !strcmp(argv[i], "-strip") ||
+ !strcmp(argv[i], "-strips")) {
+ themesh->need_tstrips();
+ have_tstrips = true;
+ } else if (!strcmp(argv[i], "-notstrip") ||
+ !strcmp(argv[i], "-notstrips") ||
+ !strcmp(argv[i], "-nostrip") ||
+ !strcmp(argv[i], "-nostrips") ||
+ !strcmp(argv[i], "-unstrip")) {
+ themesh->need_faces();
+ themesh->tstrips.clear();
+ have_tstrips = false;
+ } else if (!strcmp(argv[i], "-nogrid")) {
+ themesh->need_faces();
+ themesh->grid.clear();
+ } else if (!strcmp(argv[i], "-reorder")) {
+ reorder_verts(themesh);
+ } else if (!strcmp(argv[i], "-orient")) {
+ orient(themesh);
+ } else if (!strcmp(argv[i], "-faceflip")) {
+ faceflip(themesh);
+ } else if (!strcmp(argv[i], "-edgeflip")) {
+ edgeflip(themesh);
+ } else if (!strcmp(argv[i], "-subdiv")) {
+ subdiv(themesh, SUBDIV_PLANAR);
+ } else if (!strcmp(argv[i], "-loop")) {
+ subdiv(themesh, SUBDIV_LOOP);
+ } else if (!strcmp(argv[i], "-loop2")) {
+ subdiv(themesh, SUBDIV_LOOP_ORIG);
+ } else if (!strcmp(argv[i], "-loop3")) {
+ subdiv(themesh, SUBDIV_LOOP_NEW);
+ } else if (!strcmp(argv[i], "-fly")) {
+ subdiv(themesh, SUBDIV_BUTTERFLY_MODIFIED);
+ } else if (!strcmp(argv[i], "-fly2")) {
+ subdiv(themesh, SUBDIV_BUTTERFLY);
+ } else if (!strcmp(argv[i], "-smooth")) {
+ i++;
+ if (!(i < argc && isanumber(argv[i]))) {
+ fprintf(stderr, "\n-smooth requires one float parameter: s\n\n");
+ usage(argv[0]);
+ }
+ float amount = atof(argv[i]) * themesh->feature_size();
+ smooth_mesh(themesh, amount);
+ themesh->pointareas.clear();
+ themesh->normals.clear();
+ } else if (!strcmp(argv[i], "-bilat")) {
+ i++;
+ if (!(i < argc && isanumber(argv[i]))) {
+ fprintf(stderr, "\n-smooth requires two float parameters: sd, sr\n\n");
+ usage(argv[0]);
+ }
+ float fs = themesh->feature_size();
+ float sd = atof(argv[i]) * fs;
+ i++;
+ if (!(i < argc && isanumber(argv[i]))) {
+ fprintf(stderr, "\n-smooth requires two float parameters: sd, sr\n\n");
+ usage(argv[0]);
+ }
+ float sr = atof(argv[i]) * fs;
+ bilateral_smooth_mesh(themesh, sd, sr);
+ themesh->normals.clear();
+ } else if (!strcmp(argv[i], "-sharpen")) {
+ i++;
+ if (!(i < argc && isanumber(argv[i]))) {
+ fprintf(stderr, "\n-sharpen requires one float parameter: s\n\n");
+ usage(argv[0]);
+ }
+ float amount = atof(argv[i]) * themesh->feature_size();
+ vector<point> origverts = themesh->vertices;
+ smooth_mesh(themesh, amount);
+ for (int v = 0; v < themesh->vertices.size(); v++)
+ themesh->vertices[v] += 2.0f *
+ (origverts[v] - themesh->vertices[v]);
+ themesh->pointareas.clear();
+ themesh->normals.clear();
+ } else if (!strcmp(argv[i], "-smoothnorm")) {
+ i++;
+ if (!(i < argc && isanumber(argv[i]))) {
+ fprintf(stderr, "\n-smoothnorm requires one float parameter: s\n\n");
+ usage(argv[0]);
+ }
+ float amount = atof(argv[i]) * themesh->feature_size();
+ diffuse_normals(themesh, amount);
+ } else if (!strcmp(argv[i], "-usmooth")) {
+ i++;
+ if (!(i < argc && isanint(argv[i]))) {
+ fprintf(stderr, "\n-usmooth requires one int parameter: n\n\n");
+ usage(argv[0]);
+ }
+ int niters = atoi(argv[i]);
+ for (int iter = 0; iter < niters; iter++)
+ umbrella(themesh, 0.5f);
+ } else if (!strcmp(argv[i], "-lmsmooth")) {
+ i++;
+ if (!(i < argc && isanint(argv[i]))) {
+ fprintf(stderr, "\n-lmsmooth requires one int parameter: n\n\n");
+ usage(argv[0]);
+ }
+ int niters = atoi(argv[i]);
+ lmsmooth(themesh, niters);
+ } else if (!strcmp(argv[i], "-inflate")) {
+ i++;
+ if (!(i < argc && isanumber(argv[i]))) {
+ fprintf(stderr, "\n-inflate requires one float parameter: s\n\n");
+ usage(argv[0]);
+ }
+ float amount = atof(argv[i]) * themesh->feature_size();
+ inflate(themesh, amount);
+ } else if (!strcmp(argv[i], "-noisify")) {
+ i++;
+ if (!(i < argc && isanumber(argv[i]))) {
+ fprintf(stderr, "\n-noisify requires one float parameter: s\n\n");
+ usage(argv[0]);
+ }
+ float amount = atof(argv[i]) * themesh->feature_size();
+ noisify(themesh, amount);
+ } else if (!strcmp(argv[i], "-clip")) {
+ i++;
+ if (!(i < argc)) {
+ fprintf(stderr, "\n-clip requires one argument\n\n");
+ usage(argv[0]);
+ }
+ if (!clip(themesh, argv[i]))
+ usage(argv[0]);
+ } else if (!strcmp(argv[i], "-xf") ||
+ !strcmp(argv[i], "-xform")) {
+ i++;
+ if (!(i < argc)) {
+ fprintf(stderr, "\n-xform requires one argument\n\n");
+ usage(argv[0]);
+ }
+ apply_xform(themesh, argv[i]);
+ } else if (!strcmp(argv[i], "-ixf") ||
+ !strcmp(argv[i], "-ixform")) {
+ i++;
+ if (!(i < argc)) {
+ fprintf(stderr, "\n-xform requires one argument\n\n");
+ usage(argv[0]);
+ }
+ apply_ixform(themesh, argv[i]);
+ } else if (!strcmp(argv[i], "-rot") ||
+ !strcmp(argv[i], "-rotate")) {
+ i += 4;
+ if (!(i < argc &&
+ isanumber(argv[i]) && isanumber(argv[i-1]) &&
+ isanumber(argv[i-2]) && isanumber(argv[i-3]))) {
+ fprintf(stderr, "\n-rot requires four arguments\n\n");
+ usage(argv[0]);
+ }
+ vec ax(atof(argv[i-2]), atof(argv[i-1]), atof(argv[i]));
+ float ang = M_PI / 180.0f * atof(argv[i-3]);
+ rot(themesh, ang, ax);
+ } else if (!strcmp(argv[i], "-trans") ||
+ !strcmp(argv[i], "-translate")) {
+ i += 3;
+ if (!(i < argc && isanumber(argv[i]) &&
+ isanumber(argv[i-1]) && isanumber(argv[i-2]))) {
+ fprintf(stderr, "\n-trans requires three arguments\n\n");
+ usage(argv[0]);
+ }
+ vec t(atof(argv[i-2]), atof(argv[i-1]), atof(argv[i]));
+ trans(themesh, t);
+ } else if (!strcmp(argv[i], "-scale")) {
+ int nargs = 0;
+ float args[4];
+ while (nargs < 4) {
+ if (++i >= argc)
+ break;
+ if (!isanumber(argv[i]) ||
+ !sscanf(argv[i], "%f", &(args[nargs]))) {
+ --i;
+ break;
+ }
+ nargs++;
+ }
+ if (!(i < argc) || nargs == 0 || nargs == 2) {
+ fprintf(stderr, "\n-scale requires 1, 3, or 4 arguments\n\n");
+ usage(argv[0]);
+ }
+ xform s = xform::scale(args[0]);
+ if (nargs == 3)
+ s = xform::scale(args[0], args[1], args[2]);
+ else if (nargs == 4)
+ s = xform::scale(args[0], args[1], args[2], args[3]);
+ apply_xform(themesh, s);
+ } else if (!strcmp(argv[i], "-center")) {
+ trans(themesh, -mesh_center_of_mass(themesh));
+ } else if (!strcmp(argv[i], "-bbcenter")) {
+ themesh->need_bbox();
+ trans(themesh, -themesh->bbox.center());
+ } else if (!strcmp(argv[i], "-varnorm")) {
+ normalize_variance(themesh);
+ } else if (!strcmp(argv[i], "-bbnorm")) {
+ themesh->need_bbox();
+ vec l = themesh->bbox.size();
+ float ll = max(max(l[0], l[1]), l[2]);
+ trans(themesh, -themesh->bbox.center());
+ float s = 1.0f / ll;
+ scale(themesh, s);
+ trans(themesh, themesh->bbox.center());
+ } else if (!strcmp(argv[i], "-pcarot")) {
+ pca_rotate(themesh);
+ } else if (!strcmp(argv[i], "-pcasnap")) {
+ pca_snap(themesh);
+ } else if (!strcmp(argv[i], "-rmunused")) {
+ remove_unused_vertices(themesh);
+ } else if (!strcmp(argv[i], "-rmslivers")) {
+ remove_sliver_faces(themesh);
+ } else if (!strcmp(argv[i], "-erode")) {
+ erode(themesh);
+ } else if (i == argc - 1 &&
+ (argv[i][0] != '-' || argv[i][1] == '\0')) {
+ if (have_tstrips && themesh->tstrips.empty())
+ themesh->need_tstrips();
+ themesh->write(argv[i]);
+ } else {
+ fprintf(stderr, "\nUnrecognized option [%s]\n\n", argv[i]);
+ usage(argv[0]);
+ }
+ }
+}
+
Index: external/trimesh/utilsrc/mesh_cat.cc
--- external/trimesh/utilsrc/mesh_cat.cc (revision 0)
+++ external/trimesh/utilsrc/mesh_cat.cc (revision 0)
@@ -0,0 +1,84 @@
+/*
+Szymon Rusinkiewicz
+Princeton University
+
+mesh_cat.cc
+Concatenate meshes together
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "TriMesh.h"
+
+
+void usage(const char *myname)
+{
+ fprintf(stderr, "Usage: %s infiles... -o outfile\n", myname);
+ exit(1);
+}
+
+int main(int argc, char *argv[])
+{
+ if (argc < 4)
+ usage(argv[0]);
+
+ TriMesh *outmesh = new TriMesh;
+ const char *outfile = NULL;
+ for (int i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-o") == 0 && i < argc-1) {
+ outfile = argv[i+1];
+ i++;
+ continue;
+ }
+ TriMesh *m = TriMesh::read(argv[i]);
+ if (!m) {
+ fprintf(stderr, "Couldn't read file %s\n", argv[i]);
+ continue;
+ }
+ int onv = outmesh->vertices.size();
+ outmesh->vertices.insert(outmesh->vertices.end(),
+ m->vertices.begin(),
+ m->vertices.end());
+
+ if (outmesh->colors.empty() && !m->colors.empty())
+ outmesh->colors.resize(onv, Color(1,1,1));
+ else if (m->colors.empty() && !outmesh->colors.empty())
+ m->colors.resize(m->vertices.size(), Color(1,1,1));
+ outmesh->colors.insert(outmesh->colors.end(),
+ m->colors.begin(),
+ m->colors.end());
+
+ if (outmesh->confidences.empty() && !m->confidences.empty())
+ outmesh->confidences.resize(onv);
+ else if (m->confidences.empty() && !outmesh->confidences.empty())
+ m->confidences.resize(m->vertices.size());
+ outmesh->confidences.insert(outmesh->confidences.end(),
+ m->confidences.begin(),
+ m->confidences.end());
+
+ if (outmesh->normals.empty() && !m->normals.empty()) {
+ outmesh->need_normals();
+ outmesh->normals.resize(onv);
+ } else if (m->normals.empty() && !outmesh->normals.empty())
+ m->need_normals();
+ outmesh->normals.insert(outmesh->normals.end(),
+ m->normals.begin(),
+ m->normals.end());
+
+ m->need_faces();
+ for (int i = 0; i < m->faces.size(); i++) {
+ m->faces[i][0] += onv;
+ m->faces[i][1] += onv;
+ m->faces[i][2] += onv;
+ }
+ outmesh->faces.insert(outmesh->faces.end(),
+ m->faces.begin(),
+ m->faces.end());
+ delete m;
+ }
+ if (outfile)
+ outmesh->write(outfile);
+ else
+ fprintf(stderr, "No output file specified\n");
+}
Index: external/trimesh/utilsrc/mesh_align.cc
--- external/trimesh/utilsrc/mesh_align.cc (revision 0)
+++ external/trimesh/utilsrc/mesh_align.cc (revision 0)
@@ -0,0 +1,91 @@
+/*
+Szymon Rusinkiewicz
+Princeton University
+
+mesh_align.cc
+Minimal interface to ICP: register two meshes given an initial guess
+for their alignment.
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include "TriMesh.h"
+#include "ICP.h"
+
+
+// Given a filename, find the filename of the transform
+// (replaces extension with ".xf")
+char *filename2xf(const char *filename)
+{
+ char *xffilename = new char[strlen(filename) + 4];
+ strcpy(xffilename, filename);
+ char *dot = strrchr(xffilename, '.');
+ if (!dot)
+ dot = strrchr(xffilename, '\0');
+ strcpy(dot, ".xf");
+ return xffilename;
+}
+
+
+void usage(const char *myname)
+{
+ fprintf(stderr, "Usage: %s [-options] mesh1.ply mesh2.ply\n", myname);
+ fprintf(stderr, "Options:\n");
+ fprintf(stderr, " -a Align using affine xform\n");
+ fprintf(stderr, " -r Align using rigid-body transform (default)\n");
+ fprintf(stderr, " -s Align using rigid + isotropic scale\n");
+ fprintf(stderr, " -v Verbose\n");
+ fprintf(stderr, "Reads transforms in mesh1.xf and mesh2.xf, updates the
latter\n");
+ exit(1);
+}
+
+int main(int argc, char *argv[])
+{
+ int verbose = 1;
+ bool do_scale = false;
+ bool do_affine = false;
+
+ int c;
+ while ((c = getopt(argc, argv, "harsv")) != EOF) {
+ switch (c) {
+ case 'a': do_affine = true; do_scale = false; break;
+ case 'r': do_affine = do_scale = false; break;
+ case 's': do_scale = true; do_affine = false; break;
+ case 'v': verbose = 2; break;
+ default: usage(argv[0]);
+ }
+ }
+ if (argc - optind < 2)
+ usage(argv[0]);
+ const char *filename1 = argv[optind], *filename2 = argv[optind+1];
+
+ TriMesh *mesh1 = TriMesh::read(filename1);
+ if (!mesh1)
+ usage(argv[0]);
+ TriMesh *mesh2 = TriMesh::read(filename2);
+ if (!mesh2)
+ usage(argv[0]);
+
+ xform xf1;
+ char *xffilename1 = filename2xf(filename1);
+ xf1.read(xffilename1);
+
+ xform xf2;
+ char *xffilename2 = filename2xf(filename2);
+ xf2.read(xffilename2);
+
+ float err = ICP(mesh1, mesh2, xf1, xf2, verbose, do_scale, do_affine);
+ if (err >= 0.0f)
+ err = ICP(mesh1, mesh2, xf1, xf2, verbose, do_scale, do_affine);
+
+ if (err < 0.0f) {
+ fprintf(stderr, "ICP failed\n");
+ } else {
+ fprintf(stderr, "ICP succeeded - distance = %f\n", err);
+ xf2.write(xffilename2);
+ }
+}
+
Index: external/trimesh/utilsrc/mesh_view.cc
--- external/trimesh/utilsrc/mesh_view.cc (revision 0)
+++ external/trimesh/utilsrc/mesh_view.cc (revision 0)
@@ -0,0 +1,598 @@
+/*
+Szymon Rusinkiewicz
+Princeton University
+
+mesh_view.cc
+Simple viewer
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "TriMesh.h"
+#include "XForm.h"
+#include "GLCamera.h"
+#include "ICP.h"
+#include <GL/glut.h>
+#include <string>
+using std::string;
+
+
+// Globals
+vector<TriMesh *> meshes;
+vector<xform> xforms;
+vector<bool> visible;
+vector<string> xffilenames;
+
+TriMesh::BSphere global_bsph;
+xform global_xf;
+GLCamera camera;
+
+int current_mesh = -1;
+
+bool draw_edges = false;
+bool draw_2side = false;
+bool draw_shiny = true;
+bool draw_lit = true;
+bool draw_falsecolor = false;
+bool draw_index = false;
+bool white_bg = false;
+
+
+// Make some mesh current
+void set_current(int i)
+{
+ if (i >= 0 && i < meshes.size() && visible[i])
+ current_mesh = i;
+ else
+ current_mesh = -1;
+ camera.stopspin();
+}
+
+
+// Change visiblility of a mesh
+void toggle_vis(int i)
+{
+ if (i >= 0 && i < meshes.size())
+ visible[i] = !visible[i];
+ if (current_mesh == i && !visible[i])
+ set_current(-1);
+}
+
+
+// Signal a redraw
+void need_redraw()
+{
+ glutPostRedisplay();
+}
+
+
+// Clear the screen
+void cls()
+{
+ glDisable(GL_DITHER);
+ glDisable(GL_BLEND);
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_NORMALIZE);
+ glDisable(GL_LIGHTING);
+ glDisable(GL_NORMALIZE);
+ glDisable(GL_COLOR_MATERIAL);
+ if (white_bg)
+ glClearColor(1, 1, 1, 0);
+ else
+ glClearColor(0.08, 0.08, 0.08, 0);
+ glClearDepth(1);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+}
+
+
+// Set up lights and materials
+void setup_lighting(int id)
+{
+ Color c(1.0f);
+ if (draw_falsecolor)
+ c = Color::hsv(-3.88 * id, 0.6 + 0.2 * sin(0.42 * id), 1.0);
+ glColor3fv(c);
+
+ if (!draw_lit || meshes[id]->normals.empty()) {
+ glDisable(GL_LIGHTING);
+ return;
+ }
+
+ GLfloat mat_specular[4] = { 0.18, 0.18, 0.18, 0.18 };
+ if (!draw_shiny) {
+ mat_specular[0] = mat_specular[1] =
+ mat_specular[2] = mat_specular[3] = 0.0f;
+ }
+ GLfloat mat_shininess[] = { 64 };
+ GLfloat global_ambient[] = { 0.02, 0.02, 0.05, 0.05 };
+ GLfloat light0_ambient[] = { 0, 0, 0, 0 };
+ GLfloat light0_diffuse[] = { 0.85, 0.85, 0.8, 0.85 };
+ if (current_mesh >= 0 && id != current_mesh) {
+ light0_diffuse[0] *= 0.5f;
+ light0_diffuse[1] *= 0.5f;
+ light0_diffuse[2] *= 0.5f;
+ }
+ GLfloat light1_diffuse[] = { -0.01, -0.01, -0.03, -0.03 };
+ GLfloat light0_specular[] = { 0.85, 0.85, 0.85, 0.85 };
+ glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
+ glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient);
+ glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
+ glLightfv(GL_LIGHT0, GL_SPECULAR, light0_specular);
+ glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_diffuse);
+ glLightModelfv(GL_LIGHT_MODEL_AMBIENT, global_ambient);
+ glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_FALSE);
+ glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, draw_2side);
+ glEnable(GL_LIGHTING);
+ glEnable(GL_LIGHT0);
+ glEnable(GL_LIGHT1);
+ glEnable(GL_COLOR_MATERIAL);
+ glEnable(GL_NORMALIZE);
+}
+
+
+// Draw triangle strips. They are stored as length followed by values.
+void draw_tstrips(const TriMesh *themesh)
+{
+ const int *t = &themesh->tstrips[0];
+ const int *end = t + themesh->tstrips.size();
+ while (likely(t < end)) {
+ int striplen = *t++;
+ glDrawElements(GL_TRIANGLE_STRIP, striplen, GL_UNSIGNED_INT, t);
+ t += striplen;
+ }
+}
+
+
+// Draw the mesh
+void draw_mesh(int i)
+{
+ const TriMesh *themesh = meshes[i];
+
+ glPushMatrix();
+ glMultMatrixd(xforms[i]);
+
+ glDepthFunc(GL_LESS);
+ glEnable(GL_DEPTH_TEST);
+
+ if (draw_2side) {
+ glDisable(GL_CULL_FACE);
+ } else {
+ glCullFace(GL_BACK);
+ glEnable(GL_CULL_FACE);
+ }
+
+ // Vertices
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(3, GL_FLOAT,
+ sizeof(themesh->vertices[0]),
+ &themesh->vertices[0][0]);
+
+ // Normals
+ if (!themesh->normals.empty() && !draw_index) {
+ glEnableClientState(GL_NORMAL_ARRAY);
+ glNormalPointer(GL_FLOAT,
+ sizeof(themesh->normals[0]),
+ &themesh->normals[0][0]);
+ } else {
+ glDisableClientState(GL_NORMAL_ARRAY);
+ }
+
+ // Colors
+ if (!themesh->colors.empty() && !draw_falsecolor && !draw_index) {
+ glEnableClientState(GL_COLOR_ARRAY);
+ glColorPointer(3, GL_FLOAT,
+ sizeof(themesh->colors[0]),
+ &themesh->colors[0][0]);
+ } else {
+ glDisableClientState(GL_COLOR_ARRAY);
+ }
+
+ // Main drawing pass
+ if (themesh->tstrips.empty()) {
+ // No triangles - draw as points
+ glPointSize(1);
+ glDrawArrays(GL_POINTS, 0, themesh->vertices.size());
+ glPopMatrix();
+ return;
+ }
+
+ if (draw_edges) {
+ glPolygonOffset(10.0f, 10.0f);
+ glEnable(GL_POLYGON_OFFSET_FILL);
+ }
+
+ draw_tstrips(themesh);
+ glDisable(GL_POLYGON_OFFSET_FILL);
+
+ // Edge drawing pass
+ if (draw_edges) {
+ glPolygonMode(GL_FRONT, GL_LINE);
+ glDisableClientState(GL_COLOR_ARRAY);
+ glDisable(GL_COLOR_MATERIAL);
+ GLfloat global_ambient[] = { 0.2, 0.2, 0.2, 1.0 };
+ GLfloat light0_diffuse[] = { 0.8, 0.8, 0.8, 0.0 };
+ GLfloat light1_diffuse[] = { -0.2, -0.2, -0.2, 0.0 };
+ GLfloat light0_specular[] = { 0.0f, 0.0f, 0.0f, 0.0f };
+ glLightModelfv(GL_LIGHT_MODEL_AMBIENT, global_ambient);
+ glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
+ glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_diffuse);
+ glLightfv(GL_LIGHT0, GL_SPECULAR, light0_specular);
+ GLfloat mat_diffuse[4] = { 0.0f, 0.0f, 1.0f, 1.0f };
+ glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_diffuse);
+ glColor3f(0, 0, 1); // Used iff unlit
+ draw_tstrips(themesh);
+ glPolygonMode(GL_FRONT, GL_FILL);
+ }
+
+ glPopMatrix();
+}
+
+
+// Draw the scene
+void redraw()
+{
+ timestamp t = now();
+ camera.setupGL(global_xf * global_bsph.center, global_bsph.r);
+ glPushMatrix();
+ glMultMatrixd(global_xf);
+ cls();
+ for (int i = 0; i < meshes.size(); i++) {
+ if (!visible[i])
+ continue;
+ setup_lighting(i);
+ draw_mesh(i);
+ }
+
+ glPopMatrix();
+ glutSwapBuffers();
+ printf("\r \r%.1f msec.", 1000.0f * (now() - t));
+ fflush(stdout);
+}
+
+
+// Update global bounding sphere.
+void update_bsph()
+{
+ point boxmin(1e38, 1e38, 1e38);
+ point boxmax(-1e38, -1e38, -1e38);
+ bool some_vis = false;
+ for (int i = 0; i < meshes.size(); i++) {
+ if (!visible[i])
+ continue;
+ some_vis = true;
+ point c = xforms[i] * meshes[i]->bsphere.center;
+ float r = meshes[i]->bsphere.r;
+ for (int j = 0; j < 3; j++) {
+ boxmin[j] = min(boxmin[j], c[j]-r);
+ boxmax[j] = max(boxmax[j], c[j]+r);
+ }
+ }
+ if (!some_vis)
+ return;
+ point &gc = global_bsph.center;
+ float &gr = global_bsph.r;
+ gc = 0.5f * (boxmin + boxmax);
+ gr = 0.0f;
+ for (int i = 0; i < meshes.size(); i++) {
+ if (!visible[i])
+ continue;
+ point c = xforms[i] * meshes[i]->bsphere.center;
+ float r = meshes[i]->bsphere.r;
+ gr = max(gr, dist(c, gc) + r);
+ }
+}
+
+
+// Set the view...
+void resetview()
+{
+ camera.stopspin();
+ for (int i = 0; i < meshes.size(); i++)
+ if (!xforms[i].read(xffilenames[i]))
+ xforms[i] = xform();
+ update_bsph();
+ global_xf = xform::trans(0, 0, -5.0f * global_bsph.r) *
+ xform::trans(-global_bsph.center);
+
+ // Special case for 1 mesh
+ if (meshes.size() == 1 && xforms[0].read(xffilenames[0])) {
+ global_xf = xforms[0];
+ xforms[0] = xform();
+ }
+}
+
+
+// Save the current image to a PPM file.
+// Uses the next available filename matching filenamepattern
+void dump_image()
+{
+ // Find first non-used filename
+ const char filenamepattern[] = "img%d.ppm";
+ int imgnum = 0;
+ FILE *f;
+ while (1) {
+ char filename[1024];
+ sprintf(filename, filenamepattern, imgnum++);
+ f = fopen(filename, "rb");
+ if (!f) {
+ f = fopen(filename, "wb");
+ printf("\n\nSaving image %s... ", filename);
+ fflush(stdout);
+ break;
+ }
+ fclose(f);
+ }
+
+ // Read pixels
+ GLint V[4];
+ glGetIntegerv(GL_VIEWPORT, V);
+ GLint width = V[2], height = V[3];
+ char *buf = new char[width*height*3];
+ glPixelStorei(GL_PACK_ALIGNMENT, 1);
+ glReadPixels(V[0], V[1], width, height, GL_RGB, GL_UNSIGNED_BYTE, buf);
+
+ // Flip top-to-bottom
+ for (int i = 0; i < height/2; i++) {
+ char *row1 = buf + 3 * width * i;
+ char *row2 = buf + 3 * width * (height - 1 - i);
+ for (int j = 0; j < 3 * width; j++)
+ swap(row1[j], row2[j]);
+ }
+
+ // Write out file
+ fprintf(f, "P6\n#\n%d %d\n255\n", width, height);
+ fwrite(buf, width*height*3, 1, f);
+ fclose(f);
+ delete [] buf;
+
+ printf("Done.\n\n");
+}
+
+
+// Save all transforms
+void save_xforms()
+{
+ if (xforms.size() == 1) {
+ printf("Writing %s\n", xffilenames[0].c_str());
+ global_xf.write(xffilenames[0]);
+ return;
+ }
+ for (int i = 0; i < xforms.size(); i++) {
+ printf("Writing %s\n", xffilenames[i].c_str());
+ xforms[i].write(xffilenames[i]);
+ }
+}
+
+
+// ICP
+void do_icp(int n)
+{
+ camera.stopspin();
+
+ if (current_mesh < 0 || current_mesh >= meshes.size())
+ return;
+ if (n < 0 || n >= meshes.size())
+ return;
+ if (!visible[n] || !visible[current_mesh] || n == current_mesh)
+ return;
+ ICP(meshes[n], meshes[current_mesh], xforms[n], xforms[current_mesh], 2);
+ update_bsph();
+ need_redraw();
+}
+
+
+// Handle mouse button and motion events
+static unsigned buttonstate = 0;
+
+void doubleclick(int button, int x, int y)
+{
+ // Render and read back ID reference image
+ camera.setupGL(global_xf * global_bsph.center, global_bsph.r);
+ glDisable(GL_BLEND);
+ glDisable(GL_LIGHTING);
+ glClearColor(1,1,1,1);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glEnable(GL_DEPTH_TEST);
+ draw_index = true;
+ glPushMatrix();
+ glMultMatrixd(global_xf);
+ for (int i = 0; i < meshes.size(); i++) {
+ if (!visible[i])
+ continue;
+ glColor3ub((i >> 16) & 0xff,
+ (i >> 8) & 0xff,
+ i & 0xff);
+ draw_mesh(i);
+ }
+ glPopMatrix();
+ draw_index = false;
+ GLint V[4];
+ glGetIntegerv(GL_VIEWPORT, V);
+ y = int(V[1] + V[3]) - 1 - y;
+ unsigned char pix[3];
+ glReadPixels(x, y, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, pix);
+ int n = (pix[0] << 16) + (pix[1] << 8) + pix[2];
+
+ if (button == 0 || buttonstate == (1 << 0)) {
+ // Double left click - select a mesh
+ set_current(n);
+ } else if (button == 2 || buttonstate == (1 << 2)) {
+ // Double right click - ICP current to clicked-on
+ do_icp(n);
+ }
+}
+
+void mousemotionfunc(int x, int y)
+{
+ static const Mouse::button physical_to_logical_map[] = {
+ Mouse::NONE, Mouse::ROTATE, Mouse::MOVEXY, Mouse::MOVEZ,
+ Mouse::MOVEZ, Mouse::MOVEXY, Mouse::MOVEXY, Mouse::MOVEXY,
+ };
+
+ Mouse::button b = Mouse::NONE;
+ if (buttonstate & (1 << 3))
+ b = Mouse::WHEELUP;
+ else if (buttonstate & (1 << 4))
+ b = Mouse::WHEELDOWN;
+ else if (buttonstate & (1 << 30))
+ b = Mouse::LIGHT;
+ else
+ b = physical_to_logical_map[buttonstate & 7];
+
+ if (current_mesh < 0) {
+ camera.mouse(x, y, b,
+ global_xf * global_bsph.center, global_bsph.r,
+ global_xf);
+ } else {
+ xform tmp_xf = global_xf * xforms[current_mesh];
+ camera.mouse(x, y, b,
+ tmp_xf * meshes[current_mesh]->bsphere.center,
+ meshes[current_mesh]->bsphere.r,
+ tmp_xf);
+ xforms[current_mesh] = inv(global_xf) * tmp_xf;
+ update_bsph();
+ }
+ if (b != Mouse::NONE)
+ need_redraw();
+}
+
+void mousebuttonfunc(int button, int state, int x, int y)
+{
+ static timestamp last_click_time;
+ static unsigned last_click_buttonstate = 0;
+ static float doubleclick_threshold = 0.25f;
+
+ if (glutGetModifiers() & GLUT_ACTIVE_CTRL)
+ buttonstate |= (1 << 30);
+ else
+ buttonstate &= ~(1 << 30);
+
+ if (state == GLUT_DOWN) {
+ buttonstate |= (1 << button);
+ if (buttonstate == last_click_buttonstate &&
+ now() - last_click_time < doubleclick_threshold) {
+ doubleclick(button, x, y);
+ last_click_buttonstate = 0;
+ } else {
+ last_click_time = now();
+ last_click_buttonstate = buttonstate;
+ }
+ } else {
+ buttonstate &= ~(1 << button);
+ }
+
+ mousemotionfunc(x, y);
+}
+
+
+// Idle callback
+void idle()
+{
+ xform tmp_xf = global_xf;
+ if (current_mesh >= 0)
+ tmp_xf = global_xf * xforms[current_mesh];
+
+ if (camera.autospin(tmp_xf))
+ need_redraw();
+ else
+ usleep(10000);
+
+ if (current_mesh >= 0) {
+ xforms[current_mesh] = inv(global_xf) * tmp_xf;
+ update_bsph();
+ } else {
+ global_xf = tmp_xf;
+ }
+}
+
+
+// Keyboard
+#define Ctrl (1-'a')
+void keyboardfunc(unsigned char key, int x, int y)
+{
+ switch (key) {
+ case ' ':
+ if (current_mesh < 0)
+ resetview();
+ else
+ set_current(-1);
+ break;
+ case '@': // Shift-2
+ draw_2side = !draw_2side; break;
+ case 'e':
+ draw_edges = !draw_edges; break;
+ case 'f':
+ draw_falsecolor = !draw_falsecolor; break;
+ case 'l':
+ draw_lit = !draw_lit; break;
+ case 's':
+ draw_shiny = !draw_shiny; break;
+ case 'w':
+ white_bg = !white_bg; break;
+ case 'I':
+ dump_image(); break;
+ case Ctrl+'x':
+ save_xforms();
+ break;
+ case '\033': // Esc
+ case Ctrl+'q':
+ case 'Q':
+ case 'q':
+ exit(0);
+ default:
+ if (key >= '1' && key <= '9') {
+ int m = key - '1';
+ toggle_vis(m);
+ }
+ }
+ need_redraw();
+}
+
+
+void usage(const char *myname)
+{
+ fprintf(stderr, "Usage: %s infile...\n", myname);
+ exit(1);
+}
+
+int main(int argc, char *argv[])
+{
+ glutInitWindowSize(512, 512);
+ glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
+ glutInit(&argc, argv);
+
+ if (argc < 2)
+ usage(argv[0]);
+
+ for (int i = 1; i < argc; i++) {
+ const char *filename = argv[i];
+ TriMesh *themesh = TriMesh::read(filename);
+ if (!themesh)
+ usage(argv[0]);
+ themesh->need_normals();
+ themesh->need_tstrips();
+ themesh->need_bsphere();
+ meshes.push_back(themesh);
+
+ string xffilename = xfname(filename);
+ xffilenames.push_back(xffilename);
+
+ xforms.push_back(xform());
+ visible.push_back(true);
+ }
+
+ glutCreateWindow(argv[1]);
+ glutDisplayFunc(redraw);
+ glutMouseFunc(mousebuttonfunc);
+ glutMotionFunc(mousemotionfunc);
+ glutKeyboardFunc(keyboardfunc);
+ glutIdleFunc(idle);
+
+ resetview();
+
+ glutMainLoop();
+}
+
Index: external/trimesh/utilsrc/mesh_make.cc
--- external/trimesh/utilsrc/mesh_make.cc (revision 0)
+++ external/trimesh/utilsrc/mesh_make.cc (revision 0)
@@ -0,0 +1,976 @@
+/*
+Szymon Rusinkiewicz
+Princeton University
+
+mesh_make.cc
+Create various kinds of meshes for testing...
+*/
+
+#include <cmath>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <iostream>
+#include "TriMesh.h"
+#include "TriMesh_algo.h"
+#include "XForm.h"
+#include "noise3d.h"
+#ifndef M_PI
+# define M_PI 3.14159265358979323846
+#endif
+using namespace std;
+
+
+static inline void mkpoint(TriMesh *mesh, float x, float y, float z)
+{
+ mesh->vertices.push_back(point(x,y,z));
+}
+
+static inline void mkface(TriMesh *mesh, int v1, int v2, int v3)
+{
+ mesh->faces.push_back(TriMesh::Face(v1, v2, v3));
+}
+
+static inline void mkquad(TriMesh *mesh, int ll, int lr, int ul, int ur)
+{
+ mkface(mesh, ll, lr, ur);
+ mkface(mesh, ll, ur, ul);
+}
+
+static inline void tess4(TriMesh *mesh, int v1, int v2, int v3, int v4)
+{
+ point c = 0.25f * (mesh->vertices[v1] + mesh->vertices[v2] +
+ mesh->vertices[v3] + mesh->vertices[v4]);
+ mkpoint(mesh, c[0], c[1], c[2]);
+ int ci = mesh->vertices.size() - 1;
+ mkface(mesh, ci, v1, v2);
+ mkface(mesh, ci, v2, v3);
+ mkface(mesh, ci, v3, v4);
+ mkface(mesh, ci, v4, v1);
+}
+
+static inline void tess5(TriMesh *mesh, int v1, int v2, int v3, int v4, int v5)
+{
+ point c = 0.2f * (mesh->vertices[v1] + mesh->vertices[v2] +
+ mesh->vertices[v3] + mesh->vertices[v4] +
+ mesh->vertices[v5]);
+ mkpoint(mesh, c[0], c[1], c[2]);
+ int ci = mesh->vertices.size() - 1;
+ mkface(mesh, ci, v1, v2);
+ mkface(mesh, ci, v2, v3);
+ mkface(mesh, ci, v3, v4);
+ mkface(mesh, ci, v4, v5);
+ mkface(mesh, ci, v5, v1);
+}
+
+
+TriMesh *make_plane(int tess_x, int tess_y)
+{
+ if (tess_x < 1)
+ tess_x = 1;
+ if (tess_y < 1)
+ tess_y = 1;
+
+ TriMesh *mesh = new TriMesh;
+ mesh->vertices.reserve((tess_x+1)*(tess_y+1));
+ for (int j = 0; j < tess_y+1; j++) {
+ float y = -1.0f + 2.0f * j / tess_y;
+ for (int i = 0; i < tess_x+1; i++) {
+ float x = -1.0f + 2.0f * i / tess_x;
+ mkpoint(mesh, x, y, 0);
+ }
+ }
+
+ mesh->faces.reserve(2*tess_x*tess_y);
+ for (int j = 0; j < tess_y; j++) {
+ for (int i = 0; i < tess_x; i++) {
+ int ind = i + j * (tess_x+1);
+ mkquad(mesh, ind, ind+1, ind+tess_x+1, ind+tess_x+2);
+ }
+ }
+
+ return mesh;
+}
+
+
+TriMesh *make_bump(int tess, float sigma)
+{
+ if (tess < 2)
+ tess = 2;
+
+ TriMesh *mesh = make_plane(tess, tess);
+ int nv = mesh->vertices.size();
+ float escale = -0.5f * sqr(1.0f / sigma);
+ for (int i = 0; i < nv; i++) {
+ point &p = mesh->vertices[i];
+ p[2] = exp(escale * (sqr(p[0]) + sqr(p[1])));
+ }
+ return mesh;
+}
+
+
+TriMesh *make_wave(int tess, float omega)
+{
+ if (tess < 2)
+ tess = 2;
+
+ TriMesh *mesh = make_plane(tess, tess);
+ int nv = mesh->vertices.size();
+ float scale = 1.0f / omega;
+ for (int i = 0; i < nv; i++) {
+ point &p = mesh->vertices[i];
+ p[2] = scale * sin(omega * p[0]) * sin(omega * p[1]);
+ }
+ return mesh;
+}
+
+
+TriMesh *make_frac(int tess)
+{
+ if (tess < 2)
+ tess = 2;
+
+ TriMesh *mesh = make_plane(tess, tess);
+ int nv = mesh->vertices.size();
+ PerlinNoise3D noise(tess, tess, tess);
+ for (int i = 0; i < nv; i++) {
+ point &p = mesh->vertices[i];
+ p[2] = noise.lookup(p[0], p[1], 0.5f);
+ }
+ return mesh;
+}
+
+TriMesh *make_cube(int tess)
+{
+ if (tess < 1)
+ tess = 1;
+
+ TriMesh *mesh = new TriMesh;
+ mesh->vertices.reserve(6*sqr(tess)+2);
+ for (int j = 0; j < tess+1; j++) {
+ float y = 1.0f - 2.0f * j / tess;
+ for (int i = 0; i < tess+1; i++) {
+ float x = 1.0f - 2.0f * i / tess;
+ mkpoint(mesh, x, y, -1);
+ }
+ }
+ for (int j = 1; j < tess; j++) {
+ float z = -1.0f + 2.0f * j / tess;
+ for (int i = 0; i < tess; i++) {
+ float x = -1.0f + 2.0f * i / tess;
+ mkpoint(mesh, x, -1, z);
+ }
+ for (int i = 0; i < tess; i++) {
+ float y = -1.0f + 2.0f * i / tess;
+ mkpoint(mesh, 1, y, z);
+ }
+ for (int i = 0; i < tess; i++) {
+ float x = 1.0f - 2.0f * i / tess;
+ mkpoint(mesh, x, 1, z);
+ }
+ for (int i = 0; i < tess; i++) {
+ float y = 1.0f - 2.0f * i / tess;
+ mkpoint(mesh, -1, y, z);
+ }
+ }
+ for (int j = 0; j < tess+1; j++) {
+ float y = -1.0f + 2.0f * j / tess;
+ for (int i = 0; i < tess+1; i++) {
+ float x = -1.0f + 2.0f * i / tess;
+ mkpoint(mesh, x, y, 1);
+ }
+ }
+
+ mesh->faces.reserve(12*sqr(tess));
+ for (int j = 0; j < tess; j++) {
+ for (int i = 0; i < tess; i++) {
+ int ind = i + j * (tess+1);
+ mkquad(mesh, ind, ind+tess+1, ind+1, ind+tess+2);
+ }
+ }
+
+ int topstart = sqr(tess+1) + 4*tess*(tess-1);
+ for (int j = 0; j < tess; j++) {
+ int next = sqr(tess+1) + 4*tess*(j-1);
+ for (int i = 0; i < tess; i++) {
+ int ll = next++;
+ int lr = ll + 1;
+ int ul = ll + 4*tess;
+ int ur = ul + 1;
+ if (j == 0) {
+ ll = sqr(tess+1)-1 - i;
+ lr = ll - 1;
+ }
+ mkquad(mesh, ll, lr, ul, ur);
+ }
+ for (int i = 0; i < tess; i++) {
+ int ll = next++;
+ int lr = ll + 1;
+ int ul = ll + 4*tess;
+ int ur = ul + 1;
+ if (j == 0) {
+ ll = tess*(tess+1) - i*(tess+1);
+ lr = ll - (tess+1);
+ }
+ if (j == tess-1) {
+ ul = topstart + tess + i*(tess+1);
+ ur = ul + (tess+1);
+ }
+ mkquad(mesh, ll, lr, ul, ur);
+ }
+ for (int i = 0; i < tess; i++) {
+ int ll = next++;
+ int lr = ll + 1;
+ int ul = ll + 4*tess;
+ int ur = ul + 1;
+ if (j == 0) {
+ ll = i;
+ lr = i + 1;
+ }
+ if (j == tess-1) {
+ ul = topstart + sqr(tess+1)-1 - i;
+ ur = ul - 1;
+ }
+ mkquad(mesh, ll, lr, ul, ur);
+ }
+ for (int i = 0; i < tess; i++) {
+ int ll = next++;
+ int lr = ll + 1;
+ int ul = ll + 4*tess;
+ int ur = ul + 1;
+ if (j == 0) {
+ ll = tess + i*(tess+1);
+ lr = ll + (tess+1);
+ }
+ if (j == tess-1) {
+ ul = topstart + tess*(tess+1) - i*(tess+1);
+ ur = ul - (tess+1);
+ }
+ if (i == tess-1) {
+ if (j != 0)
+ lr -= 4*tess;
+ if (j != tess-1)
+ ur -= 4*tess;
+ }
+ mkquad(mesh, ll, lr, ul, ur);
+ }
+ }
+ for (int j = 0; j < tess; j++) {
+ for (int i = 0; i < tess; i++) {
+ int ind = topstart + i + j * (tess+1);
+ mkquad(mesh, ind, ind+1, ind+tess+1, ind+tess+2);
+ }
+ }
+
+ return mesh;
+}
+
+
+TriMesh *make_disc(int tess_th, int tess_r)
+{
+ if (tess_th < 3)
+ tess_th = 3;
+ if (tess_r < 1)
+ tess_r = 1;
+
+ TriMesh *mesh = new TriMesh;
+ mesh->vertices.reserve(1+tess_th*tess_r);
+ mkpoint(mesh, 0, 0, 0);
+ for (int j = 1; j <= tess_r; j++) {
+ float r = (float) j / tess_r;
+ for (int i = 0; i < tess_th; i++) {
+ float th = 2.0f * M_PI * i / tess_th;
+ mkpoint(mesh, r*cos(th), r*sin(th), 0);
+ }
+ }
+
+ mesh->faces.reserve(2*tess_th*tess_r-tess_th);
+ for (int i = 0; i < tess_th; i++)
+ mkface(mesh, 0, i+1, ((i+1)%tess_th)+1);
+ for (int j = 1; j < tess_r; j++) {
+ int base = 1 + (j-1) * tess_th;
+ for (int i = 0; i < tess_th; i++) {
+ int i1 = (i+1)%tess_th;
+ mkquad(mesh, base+tess_th+i, base+tess_th+i1,
+ base+i, base+i1);
+ }
+ }
+
+ return mesh;
+}
+
+
+TriMesh *make_cyl(int tess_th, int tess_h, float r = 1.0f)
+{
+ if (tess_th < 3)
+ tess_th = 3;
+ if (tess_h < 1)
+ tess_h = 1;
+
+ TriMesh *mesh = new TriMesh;
+ mesh->vertices.reserve(tess_th * (tess_h+1));
+ for (int j = 0; j <= tess_h; j++) {
+ float z = -1.0f + 2.0f * j / tess_h;
+ for (int i = 0; i < tess_th; i++) {
+ float th = 2.0f * M_PI * i / tess_th;
+ mkpoint(mesh, r*cos(th), r*sin(th), z);
+ }
+ }
+
+ mesh->faces.reserve(2*tess_th*tess_h);
+ for (int j = 0; j < tess_h; j++) {
+ int base = j * tess_th;
+ for (int i = 0; i < tess_th; i++) {
+ int i1 = (i+1)%tess_th;
+ mkquad(mesh, base + i, base + i1,
+ base+tess_th+i, base+tess_th+i1);
+ }
+ }
+
+ return mesh;
+}
+
+
+TriMesh *make_ccyl(int tess_th, int tess_h, float r = 1.0f)
+{
+ if (tess_th < 3)
+ tess_th = 3;
+ if (tess_h < 1)
+ tess_h = 1;
+
+ TriMesh *mesh = new TriMesh;
+ mesh->vertices.reserve(2+3*tess_th*tess_h-tess_th);
+
+ mkpoint(mesh, 0, 0, -1);
+ for (int j = 1; j <= tess_h; j++) {
+ float rr = r * j / tess_h;
+ for (int i = 0; i < tess_th; i++) {
+ float th = 2.0f * M_PI * i / tess_th;
+ mkpoint(mesh, rr*cos(th), rr*sin(th), -1);
+ }
+ }
+ int side_start = mesh->vertices.size();
+ for (int j = 1; j < tess_h; j++) {
+ float z = -1.0f + 2.0f * j / tess_h;
+ for (int i = 0; i < tess_th; i++) {
+ float th = 2.0f * M_PI * i / tess_th;
+ mkpoint(mesh, r*cos(th), r*sin(th), z);
+ }
+ }
+ int top_start = mesh->vertices.size();
+ for (int j = tess_h; j > 0; j--) {
+ float rr = r * j / tess_h;
+ for (int i = 0; i < tess_th; i++) {
+ float th = 2.0f * M_PI * i / tess_th;
+ mkpoint(mesh, rr*cos(th), rr*sin(th), 1);
+ }
+ }
+ mkpoint(mesh, 0, 0, 1);
+
+ mesh->faces.reserve(6*tess_th*tess_h - 2*tess_th);
+
+ for (int i = 0; i < tess_th; i++)
+ mkface(mesh, 0, ((i+1)%tess_th)+1, i+1);
+ for (int j = 1; j < tess_h; j++) {
+ int base = 1 + (j-1) * tess_th;
+ for (int i = 0; i < tess_th; i++) {
+ int i1 = (i+1)%tess_th;
+ mkquad(mesh, base+tess_th+i1, base+tess_th+i,
+ base+i1, base+i);
+ }
+ }
+
+ for (int j = 0; j < tess_h; j++) {
+ int base = side_start - tess_th + j * tess_th;
+ for (int i = 0; i < tess_th; i++) {
+ int i1 = (i+1)%tess_th;
+ mkquad(mesh, base + i, base + i1,
+ base+tess_th+i, base+tess_th+i1);
+ }
+ }
+
+ for (int j = 0; j < tess_h-1; j++) {
+ int base = top_start + j * tess_th;
+ for (int i = 0; i < tess_th; i++) {
+ int i1 = (i+1)%tess_th;
+ mkquad(mesh, base+tess_th+i1, base+tess_th+i,
+ base+i1, base+i);
+ }
+ }
+ int base = top_start + (tess_h-1)*tess_th;
+ for (int i = 0; i < tess_th; i++)
+ mkface(mesh, base+i, base+((i+1)%tess_th), base+tess_th);
+
+ return mesh;
+}
+
+
+TriMesh *make_cone(int tess_th, int tess_r, float r = 1.0f)
+{
+ if (tess_th < 3)
+ tess_th = 3;
+ if (tess_r < 1)
+ tess_r = 1;
+
+ TriMesh *mesh = make_disc(tess_th, tess_r);
+ for (int j = 0; j <= tess_r; j++) {
+ float z = 1.0f - 2.0f * j / tess_r;
+ if (j == 0) {
+ mesh->vertices[0][2] = z;
+ continue;
+ }
+ for (int i = 0; i < tess_th; i++) {
+ int ind = 1 + i + (j-1)*tess_th;
+ mesh->vertices[ind][0] *= r;
+ mesh->vertices[ind][1] *= r;
+ mesh->vertices[ind][2] = z;
+ }
+ }
+ return mesh;
+}
+
+
+TriMesh *make_ccone(int tess_th, int tess_r, float r = 1.0f)
+{
+ if (tess_th < 3)
+ tess_th = 3;
+ if (tess_r < 1)
+ tess_r = 1;
+
+ TriMesh *mesh = new TriMesh;
+ mesh->vertices.reserve(2+2*tess_th*tess_r-tess_th);
+
+ mkpoint(mesh, 0, 0, -1);
+ for (int j = 1; j <= tess_r; j++) {
+ float rr = r * j / tess_r;
+ for (int i = 0; i < tess_th; i++) {
+ float th = 2.0f * M_PI * i / tess_th;
+ mkpoint(mesh, rr*cos(th), rr*sin(th), -1);
+ }
+ }
+ int side_start = mesh->vertices.size();
+ for (int j = 1; j < tess_r; j++) {
+ float z = -1.0f + 2.0f * j / tess_r;
+ float rr = r * (tess_r - j) / tess_r;
+ for (int i = 0; i < tess_th; i++) {
+ float th = 2.0f * M_PI * i / tess_th;
+ mkpoint(mesh, rr*cos(th), rr*sin(th), z);
+ }
+ }
+ mkpoint(mesh, 0, 0, 1);
+
+ mesh->faces.reserve(4*tess_th*tess_r - 2*tess_th);
+
+ for (int i = 0; i < tess_th; i++)
+ mkface(mesh, 0, ((i+1)%tess_th)+1, i+1);
+ for (int j = 1; j < tess_r; j++) {
+ int base = 1 + (j-1) * tess_th;
+ for (int i = 0; i < tess_th; i++) {
+ int i1 = (i+1)%tess_th;
+ mkquad(mesh, base+tess_th+i1, base+tess_th+i,
+ base+i1, base+i);
+ }
+ }
+
+ for (int j = 0; j < tess_r-1; j++) {
+ int base = side_start - tess_th + j * tess_th;
+ for (int i = 0; i < tess_th; i++) {
+ int i1 = (i+1)%tess_th;
+ mkquad(mesh, base + i, base + i1,
+ base+tess_th+i, base+tess_th+i1);
+ }
+ }
+
+ int base = side_start + (tess_r-2)*tess_th;
+ for (int i = 0; i < tess_th; i++)
+ mkface(mesh, base+i, base+((i+1)%tess_th), base+tess_th);
+
+ return mesh;
+}
+
+
+TriMesh *make_torus(int tess_th, int tess_ph, float r = 0.25f)
+{
+ if (tess_th < 3)
+ tess_th = 3;
+ if (tess_ph < 3)
+ tess_ph = 3;
+
+ TriMesh *mesh = make_cyl(tess_ph, tess_th);
+
+ for (int i = 0; i < tess_ph; i++)
+ mesh->vertices.pop_back();
+ for (int i = 0; i < mesh->faces.size(); i++) {
+ mesh->faces[i][0] %= mesh->vertices.size();
+ mesh->faces[i][1] %= mesh->vertices.size();
+ mesh->faces[i][2] %= mesh->vertices.size();
+ }
+
+ for (int j = 0; j < tess_th; j++) {
+ float th = 2.0f * M_PI * j / tess_th;
+ vec circlepos(cos(th), sin(th), 0);
+ for (int i = 0; i < tess_ph; i++) {
+ float ph = 2.0f * M_PI * i / tess_ph;
+ mesh->vertices[i+j*tess_ph] = circlepos +
+ cos(ph)*r*circlepos +
+ sin(ph)*r*vec(0,0,-1);
+ }
+ }
+ return mesh;
+}
+
+
+TriMesh *make_knot(int tess_th, int tess_ph, float r = 0.2f)
+{
+ if (tess_th < 3)
+ tess_th = 3;
+ if (tess_ph < 3)
+ tess_ph = 3;
+
+ TriMesh *mesh = make_torus(tess_th, tess_ph, r);
+
+ for (int j = 0; j < tess_th; j++) {
+ float th = 2.0f * M_PI * j / tess_th;
+ vec pos(2.0f*sin(2.0f*th) + cos(th),
+ 2.0f*cos(2.0f*th) + sin(th),
+ cos(3.0f*th));
+ pos /= 3.0f;
+ vec vel( 4.0f*cos(2.0f*th) - sin(th),
+ -4.0f*sin(2.0f*th) + cos(th),
+ -3.0f*sin(3.0f*th));
+ normalize(vel);
+ for (int i = 0; i < tess_ph; i++) {
+ float ph = 2.0f * M_PI * i / tess_ph;
+ vec u = vel CROSS vec(0,0,1);
+ normalize(u);
+ vec v = u CROSS vel;
+ mesh->vertices[i+j*tess_ph] =
+ pos + cos(ph)*r*v + sin(ph)*r*u;
+ }
+ }
+ return mesh;
+}
+
+TriMesh *make_klein(int tess_th, int tess_ph)
+{
+ if (tess_th < 3)
+ tess_th = 3;
+ if (tess_ph < 3)
+ tess_ph = 3;
+
+ TriMesh *mesh = make_torus(tess_th, tess_ph, 0.2f);
+
+ for (int j = 0; j < tess_th; j++) {
+ float v = 8.0f * M_PI * j / tess_th;
+ int part = 0;
+ for (int i = 0; i < 7; i++)
+ if (v > (float)M_PI)
+ v -= (float)M_PI, part++;
+ float flipx = 1.0f;
+ if (part > 3)
+ part -= 4, flipx = -1.0f;
+ if (part == 0 || part == 2)
+ v = M_PI - v;
+ for (int i = 0; i < tess_ph; i++) {
+ float u = 2.0f * M_PI * i / tess_ph;
+ // Based on formulae from
+ //
http://emsh.calarts.edu/~mathart/sw/klein/Klein.html
+ if (part == 0)
+ mesh->vertices[i+j*tess_ph] = point(
+ (2.5f + 1.5f * cos(v)) * flipx * cos(u),
+ (2.5f + 1.5f * cos(v)) * sin(u),
+ -2.5f * sin(v));
+ else if (part == 1)
+ mesh->vertices[i+j*tess_ph] = point(
+ (2.5f + 1.5f * cos(v)) * flipx * cos(u),
+ (2.5f + 1.5f * cos(v)) * sin(u),
+ 3.0f * v);
+ else if (part == 2)
+ mesh->vertices[i+j*tess_ph] = point(
+ 2.0f + (2.0f - flipx * cos(u)) * cos(v),
+ sin(u),
+ 3.0f * (float) M_PI + (2.0f - flipx * cos(u)) * sin(v));
+ else
+ mesh->vertices[i+j*tess_ph] = point(
+ 2.0f + 2.0f * cos(v) - flipx * cos(u),
+ sin(u),
+ 3.0f * ((float)M_PI - v));
+ }
+ }
+ return mesh;
+}
+
+
+TriMesh *make_helix(int tess_th, int tess_ph, float turns, float r = 0.25f)
+{
+ if (tess_th < 3)
+ tess_th = 3;
+ if (tess_ph < 3)
+ tess_ph = 3;
+
+ TriMesh *mesh = make_cyl(tess_ph, tess_th);
+
+ const float angle = atan(1.0 / M_PI);
+ for (int j = 0; j <= tess_th; j++) {
+ float z = (-1.0f + 2.0f * j / tess_th) * turns;
+ float th = 2.0f * M_PI * j / tess_th * turns;
+ vec helixpos(cos(th), sin(th), z);
+ vec xdir(cos(th), sin(th), 0);
+ vec ydir = xform::rot(angle, xdir) * vec(0, 0, -1);
+ for (int i = 0; i < tess_ph; i++) {
+ float ph = 2.0f * M_PI * i / tess_ph;
+ mesh->vertices[i+j*tess_ph] = helixpos +
+ r*cos(ph)*xdir +
+ r*sin(ph)*ydir;
+ }
+ }
+ return mesh;
+}
+
+
+TriMesh *make_sphere_polar(int tess_ph, int tess_th)
+{
+ if (tess_th < 3)
+ tess_th = 3;
+ if (tess_ph < 3)
+ tess_ph = 3;
+
+ TriMesh *mesh = new TriMesh;
+ mesh->vertices.reserve(2+tess_ph*(tess_th-1));
+
+ mkpoint(mesh, 0, 0, -1);
+ for (int j = 1; j < tess_th; j++) {
+ float th = M_PI * j / tess_th;
+ float z = -cos(th);
+ float r = sin(th);
+ for (int i = 0; i < tess_ph; i++) {
+ float ph = 2.0f * M_PI * i / tess_ph;
+ mkpoint(mesh, r*cos(ph), r*sin(ph), z);
+ }
+ }
+ mkpoint(mesh, 0, 0, 1);
+
+ mesh->faces.reserve(2*tess_th*tess_ph - 2*tess_ph);
+
+ for (int i = 0; i < tess_ph; i++)
+ mkface(mesh, 0, ((i+1)%tess_ph)+1, i+1);
+
+ for (int j = 0; j < tess_th-2; j++) {
+ int base = 1 + j * tess_ph;
+ for (int i = 0; i < tess_ph; i++) {
+ int i1 = (i+1)%tess_ph;
+ mkquad(mesh, base + i, base + i1,
+ base+tess_ph+i, base+tess_ph+i1);
+ }
+ }
+
+ int base = 1 + (tess_th-2)*tess_ph;
+ for (int i = 0; i < tess_ph; i++)
+ mkface(mesh, base+i, base+((i+1)%tess_ph), base+tess_ph);
+
+ return mesh;
+}
+
+
+TriMesh *make_platonic(int nfaces)
+{
+ float phi = 0.5f * (1.0f + sqrt(5.0f));
+ float phibar = phi - 1.0f;
+
+ TriMesh *mesh = new TriMesh;
+ switch (nfaces) {
+ case 4:
+ mkpoint(mesh, 0, 0, 3);
+ mkpoint(mesh, sqrt(8.0f), 0.0f, -1.0f);
+ mkpoint(mesh, sqrt(8.0f) - sqrt(18.0f),
+ sqrt(6.0f), -1.0f);
+ mkpoint(mesh, sqrt(8.0f) - sqrt(18.0f),
+ -sqrt(6.0f), -1.0f);
+ for (int i = 0; i < 4; i++)
+ normalize(mesh->vertices[i]);
+ mkface(mesh, 0, 1, 2);
+ mkface(mesh, 0, 2, 3);
+ mkface(mesh, 3, 2, 1);
+ mkface(mesh, 3, 1, 0);
+ break;
+
+ case 6:
+ mkpoint(mesh, -1, -1, -1);
+ mkpoint(mesh, -1, 1, -1);
+ mkpoint(mesh, 1, 1, -1);
+ mkpoint(mesh, 1, -1, -1);
+ mkpoint(mesh, 1, -1, 1);
+ mkpoint(mesh, 1, 1, 1);
+ mkpoint(mesh, -1, 1, 1);
+ mkpoint(mesh, -1, -1, 1);
+ for (int i = 0; i < 8; i++)
+ normalize(mesh->vertices[i]);
+ tess4(mesh, 0, 1, 2, 3);
+ tess4(mesh, 5, 4, 3, 2);
+ tess4(mesh, 4, 5, 6, 7);
+ tess4(mesh, 1, 0, 7, 6);
+ tess4(mesh, 6, 5, 2, 1);
+ tess4(mesh, 0, 3, 4, 7);
+ break;
+
+ case 8:
+ mkpoint(mesh, 1, 0, 0);
+ mkpoint(mesh, 0, 1, 0);
+ mkpoint(mesh, 0, 0, 1);
+ mkpoint(mesh, -1, 0, 0);
+ mkpoint(mesh, 0, -1, 0);
+ mkpoint(mesh, 0, 0, -1);
+ mkface(mesh, 0, 1, 2);
+ mkface(mesh, 0, 2, 4);
+ mkface(mesh, 0, 4, 5);
+ mkface(mesh, 0, 5, 1);
+ mkface(mesh, 3, 2, 1);
+ mkface(mesh, 3, 1, 5);
+ mkface(mesh, 3, 5, 4);
+ mkface(mesh, 3, 4, 2);
+ break;
+
+ case 12:
+ mkpoint(mesh, -1, -1, -1);
+ mkpoint(mesh, -1, 1, -1);
+ mkpoint(mesh, 1, 1, -1);
+ mkpoint(mesh, 1, -1, -1);
+ mkpoint(mesh, 1, -1, 1);
+ mkpoint(mesh, 1, 1, 1);
+ mkpoint(mesh, -1, 1, 1);
+ mkpoint(mesh, -1, -1, 1);
+ mkpoint(mesh, phi, phibar, 0);
+ mkpoint(mesh, phi, -phibar, 0);
+ mkpoint(mesh, -phi, -phibar, 0);
+ mkpoint(mesh, -phi, phibar, 0);
+ mkpoint(mesh, phibar, 0, phi);
+ mkpoint(mesh, -phibar, 0, phi);
+ mkpoint(mesh, -phibar, 0, -phi);
+ mkpoint(mesh, phibar, 0, -phi);
+ mkpoint(mesh, 0, phi, phibar);
+ mkpoint(mesh, 0, phi, -phibar);
+ mkpoint(mesh, 0, -phi, -phibar);
+ mkpoint(mesh, 0, -phi, phibar);
+ for (int i = 0; i < 20; i++)
+ normalize(mesh->vertices[i]);
+ tess5(mesh, 13, 12, 5, 16, 6);
+ tess5(mesh, 12, 13, 7, 19, 4);
+ tess5(mesh, 12, 4, 9, 8, 5);
+ tess5(mesh, 9, 4, 19, 18, 3);
+ tess5(mesh, 2, 17, 16, 5, 8);
+ tess5(mesh, 0, 14, 15, 3, 18);
+ tess5(mesh, 0, 10, 11, 1, 14);
+ tess5(mesh, 0, 18, 19, 7, 10);
+ tess5(mesh, 7, 13, 6, 11, 10);
+ tess5(mesh, 3, 15, 2, 8, 9);
+ tess5(mesh, 1, 17, 2, 15, 14);
+ tess5(mesh, 1, 11, 6, 16, 17);
+ break;
+
+ case 20:
+ mkpoint(mesh, 0, -1, phi);
+ mkpoint(mesh, 0, 1, phi);
+ mkpoint(mesh, 0, -1, -phi);
+ mkpoint(mesh, 0, 1, -phi);
+ mkpoint(mesh, phi, 0, 1);
+ mkpoint(mesh, phi, 0, -1);
+ mkpoint(mesh, -phi, 0, 1);
+ mkpoint(mesh, -phi, 0, -1);
+ mkpoint(mesh, 1, phi, 0);
+ mkpoint(mesh, 1, -phi, 0);
+ mkpoint(mesh, -1, phi, 0);
+ mkpoint(mesh, -1, -phi, 0);
+ for (int i = 0; i < 12; i++)
+ normalize(mesh->vertices[i]);
+ mkface(mesh, 0, 4, 1);
+ mkface(mesh, 0, 9, 4);
+ mkface(mesh, 9, 5, 4);
+ mkface(mesh, 4, 5, 8);
+ mkface(mesh, 4, 8, 1);
+ mkface(mesh, 8, 10, 1);
+ mkface(mesh, 8, 3, 10);
+ mkface(mesh, 5, 3, 8);
+ mkface(mesh, 5, 2, 3);
+ mkface(mesh, 2, 7, 3);
+ mkface(mesh, 7, 10, 3);
+ mkface(mesh, 7, 6, 10);
+ mkface(mesh, 7, 11, 6);
+ mkface(mesh, 11, 0, 6);
+ mkface(mesh, 0, 1, 6);
+ mkface(mesh, 6, 1, 10);
+ mkface(mesh, 9, 0, 11);
+ mkface(mesh, 9, 11, 2);
+ mkface(mesh, 9, 2, 5);
+ mkface(mesh, 7, 2, 11);
+ break;
+
+ default:
+ fprintf(stderr, "\nNumber of faces must be 4, 6, 8, 12, or 20\n\n");
+ delete mesh;
+ return 0;
+ }
+ return mesh;
+}
+
+
+TriMesh *make_sphere_subdiv(int nfaces, int nsubdiv)
+{
+ TriMesh *mesh = make_platonic(nfaces);
+ if (!mesh)
+ return 0;
+ for (int i = 0; i < mesh->vertices.size(); i++)
+ normalize(mesh->vertices[i]);
+ for (int i = 0; i < nsubdiv; i++)
+ subdiv(mesh);
+ for (int i = 0; i < mesh->vertices.size(); i++)
+ normalize(mesh->vertices[i]);
+ return mesh;
+}
+
+
+TriMesh *make_rd()
+{
+ TriMesh *mesh = make_platonic(6);
+ for (int i = 8; i < 14; i++)
+ mesh->vertices[i] *= 2.0f;
+ return mesh;
+}
+
+TriMesh *make_rt()
+{
+ const float phi3 = 0.5f * (5.0f - sqrt(5.0f));
+ TriMesh *mesh = make_platonic(12);
+ for (int i = 20; i < 32; i++)
+ mesh->vertices[i] *= phi3;
+ return mesh;
+}
+
+void usage(const char *myname)
+{
+ fprintf(stderr, "Usage: %s shape outfile\n", myname);
+ fprintf(stderr, "Shapes:\n");
+ fprintf(stderr, " plane m [n] m x n tessellated square (default n = m)\n");
+ fprintf(stderr, " bump n sigma n x n tessellated Gaussian bump of width
sigma\n");
+ fprintf(stderr, " wave n omega n x n tessellated sine wave of frequency
omega\n");
+ fprintf(stderr, " frac n n x n fractal landscape\n");
+ fprintf(stderr, " cube n n x n tessellated cube\n");
+ fprintf(stderr, " disc n m Circular disc, tessellated with m rings of n
points\n");
+ fprintf(stderr, " cyl n m [r] Cylinder of radius r (default 1)\n");
+ fprintf(stderr, " ccyl n m [r] Capped cylinder\n");
+ fprintf(stderr, " cone n m [r] Cone\n");
+ fprintf(stderr, " ccone n m [r] Capped cone\n");
+ fprintf(stderr, " torus n m [r] Torus of minor radius r (default 0.25)\n");
+ fprintf(stderr, " knot n m [r] Trefoil knot of minor radius r (default
0.2)\n");
+ fprintf(stderr, " klein n m Klein bottle\n");
+ fprintf(stderr, " helix n m t [r] Helix of minor radius r, with t turns\n");
+ fprintf(stderr, " sphere n m Sphere, tessellated in polar coordinates\n");
+ fprintf(stderr, " platonic n Platonic solid with n sides\n");
+ fprintf(stderr, " ssphere n m Sphere, subdivided m times from a Platonic of n
sides\n");
+ fprintf(stderr, " rd Rhombic dodecahedron\n");
+ fprintf(stderr, " rt Rhombic triacontahedron\n");
+ exit(1);
+}
+
+int main(int argc, char *argv[])
+{
+ if (argc < 3)
+ usage(argv[0]);
+
+ TriMesh *mesh = NULL;
+ const char *outfilename = argv[2];
+
+ if (!strcmp(argv[1], "plane") && argc > 4) {
+ mesh = make_plane(atoi(argv[2]), atoi(argv[3]));
+ outfilename = argv[4];
+ } else if (!strcmp(argv[1], "plane") && argc > 3) {
+ mesh = make_plane(atoi(argv[2]), atoi(argv[2]));
+ outfilename = argv[3];
+ } else if (!strcmp(argv[1], "bump") && argc > 4) {
+ mesh = make_bump(atoi(argv[2]), atof(argv[3]));
+ outfilename = argv[4];
+ } else if (!strcmp(argv[1], "wave") && argc > 4) {
+ mesh = make_wave(atoi(argv[2]), atof(argv[3]));
+ outfilename = argv[4];
+ } else if (!strcmp(argv[1], "frac") && argc > 3) {
+ mesh = make_frac(atoi(argv[2]));
+ outfilename = argv[3];
+ } else if (!strcmp(argv[1], "cube") && argc > 3) {
+ mesh = make_cube(atoi(argv[2]));
+ outfilename = argv[3];
+ } else if (!strcmp(argv[1], "disc") && argc > 4) {
+ mesh = make_disc(atoi(argv[2]), atoi(argv[3]));
+ outfilename = argv[4];
+ } else if (!strcmp(argv[1], "disk") && argc > 4) {
+ mesh = make_disc(atoi(argv[2]), atoi(argv[3]));
+ outfilename = argv[4];
+ } else if (!strcmp(argv[1], "cyl") && argc > 5) {
+ mesh = make_cyl(atoi(argv[2]), atoi(argv[3]), atof(argv[4]));
+ outfilename = argv[5];
+ } else if (!strcmp(argv[1], "cyl") && argc > 4) {
+ mesh = make_cyl(atoi(argv[2]), atoi(argv[3]));
+ outfilename = argv[4];
+ } else if (!strcmp(argv[1], "ccyl") && argc > 5) {
+ mesh = make_ccyl(atoi(argv[2]), atoi(argv[3]), atof(argv[4]));
+ outfilename = argv[5];
+ } else if (!strcmp(argv[1], "ccyl") && argc > 4) {
+ mesh = make_ccyl(atoi(argv[2]), atoi(argv[3]));
+ outfilename = argv[4];
+ } else if (!strcmp(argv[1], "cone") && argc > 5) {
+ mesh = make_cone(atoi(argv[2]), atoi(argv[3]), atof(argv[4]));
+ outfilename = argv[5];
+ } else if (!strcmp(argv[1], "cone") && argc > 4) {
+ mesh = make_cone(atoi(argv[2]), atoi(argv[3]));
+ outfilename = argv[4];
+ } else if (!strcmp(argv[1], "ccone") && argc > 5) {
+ mesh = make_ccone(atoi(argv[2]), atoi(argv[3]), atof(argv[4]));
+ outfilename = argv[5];
+ } else if (!strcmp(argv[1], "ccone") && argc > 4) {
+ mesh = make_ccone(atoi(argv[2]), atoi(argv[3]));
+ outfilename = argv[4];
+ } else if (!strcmp(argv[1], "torus") && argc > 5) {
+ mesh = make_torus(atoi(argv[2]), atoi(argv[3]), atof(argv[4]));
+ outfilename = argv[5];
+ } else if (!strcmp(argv[1], "torus") && argc > 4) {
+ mesh = make_torus(atoi(argv[2]), atoi(argv[3]));
+ outfilename = argv[4];
+ } else if (!strcmp(argv[1], "knot") && argc > 5) {
+ mesh = make_knot(atoi(argv[2]), atoi(argv[3]), atof(argv[4]));
+ outfilename = argv[5];
+ } else if (!strcmp(argv[1], "knot") && argc > 4) {
+ mesh = make_knot(atoi(argv[2]), atoi(argv[3]));
+ outfilename = argv[4];
+ } else if (!strcmp(argv[1], "klein") && argc > 4) {
+ mesh = make_klein(atoi(argv[2]), atoi(argv[3]));
+ outfilename = argv[4];
+ } else if (!strcmp(argv[1], "helix") && argc > 6) {
+ mesh = make_helix(atoi(argv[2]), atoi(argv[3]), atof(argv[4]), atof(argv[5]));
+ outfilename = argv[6];
+ } else if (!strcmp(argv[1], "helix") && argc > 5) {
+ mesh = make_helix(atoi(argv[2]), atoi(argv[3]), atof(argv[4]));
+ outfilename = argv[5];
+ } else if (!strcmp(argv[1], "sphere") && argc > 4) {
+ mesh = make_sphere_polar(atoi(argv[2]), atoi(argv[3]));
+ outfilename = argv[4];
+ } else if (!strcmp(argv[1], "platonic") && argc > 3) {
+ mesh = make_platonic(atoi(argv[2]));
+ outfilename = argv[3];
+ } else if (!strcmp(argv[1], "ssphere") && argc > 4) {
+ mesh = make_sphere_subdiv(atoi(argv[2]), atoi(argv[3]));
+ outfilename = argv[4];
+ } else if (!strcmp(argv[1], "rd") && argc > 2) {
+ mesh = make_rd();
+ outfilename = argv[2];
+ } else if (!strcmp(argv[1], "rt") && argc > 2) {
+ mesh = make_rt();
+ outfilename = argv[2];
+ }
+
+ if (mesh) {
+ mesh->need_tstrips();
+ mesh->write(outfilename);
+ } else {
+ usage(argv[0]);
+ }
+
+}
+
Index: external/trimesh/utilsrc/Makefile
--- external/trimesh/utilsrc/Makefile (revision 0)
+++ external/trimesh/utilsrc/Makefile (revision 0)
@@ -0,0 +1,46 @@
+# DEBUG = y
+MAKERULESDIR = ..
+DESTDIR = ../bin.$(UNAME)
+INCLUDES = -I../include
+LIBDIR = -L../lib.$(UNAME)
+
+include $(MAKERULESDIR)/Makerules
+
+VIEWSOURCES = mesh_view.cc
+
+OTHERSOURCES = mesh_align.cc \
+ mesh_cat.cc \
+ mesh_cc.cc \
+ mesh_filter.cc \
+ mesh_make.cc \
+ mesh_shade.cc
+
+VIEWOFILES = $(addprefix $(OBJDIR)/,$(VIEWSOURCES:.cc=.o))
+OTHEROFILES = $(addprefix $(OBJDIR)/,$(OTHERSOURCES:.cc=.o))
+OFILES = $(VIEWOFILES) $(OTHEROFILES)
+
+VIEWPROG = $(DESTDIR)/mesh_view$(EXE)
+OTHERPROGS = $(addsuffix $(EXE), $(addprefix $(DESTDIR)/, $(OTHERSOURCES:.cc=)))
+PROGS = $(OTHERPROGS) $(VIEWPROG)
+
+default: $(PROGS)
+
+
+LIBS += -ltrimesh
+$(VIEWPROG) : $(VIEWOFILES)
+ $(LINK) $(GLLIBS)
+
+$(OTHERPROGS) : $(DESTDIR)/%$(EXE) : $(OBJDIR)/%.o
+ $(LINK)
+
+$(PROGS) : ../lib.$(UNAME)/libtrimesh.a
+
+clean :
+ -rm -f $(OFILES) $(OBJDIR)/Makedepend $(OBJDIR)/*.d
+ -rm -rf $(OBJDIR)/ii_files
+ -rmdir $(OBJDIR)
+
+spotless : clean
+ -rm -f $(PROGS)
+ -rmdir $(DESTDIR)
+
Index: external/trimesh/Makedefs.Linux64
--- external/trimesh/Makedefs.Linux64 (revision 0)
+++ external/trimesh/Makedefs.Linux64 (revision 0)
@@ -0,0 +1,59 @@
+CC = gcc
+CXX = g++
+AR = ar
+
+COPTS = -m64 -march=nocona -mfpmath=sse
+XLIBDIR = /usr/X11R6/lib64
+
+ifdef DEBUG
+ COPTS += -fopenmp
+ COPTS += -ggdb3
+ COPTS += -Wall -Wextra -Wno-unused -Wno-sign-compare -Wno-unknown-pragmas
+ CXXOPTS = $(COPTS)
+else
+ COPTS += -fopenmp
+ COPTS += -O3 -ffast-math -funroll-loops -fomit-frame-pointer -ftree-vectorize
+ COPTS += -Wall -Wextra -Wno-unused -Wno-sign-compare -Wno-unknown-pragmas
+ CXXOPTS = $(COPTS)
+ LDOPTS = -s
+endif
+
+CFLAGS = $(INCLUDES) $(DEFINES) $(COPTS)
+CXXFLAGS = $(INCLUDES) $(DEFINES) $(CXXOPTS)
+LDFLAGS = $(LIBDIR) $(LDOPTS)
+
+
+LIBS = -lm
+GLLIBS = -L$(XLIBDIR) -lgluit -lGL -lGLU -lX11 -lXmu -lXi
+
+
+$(OBJDIR)/%.o: %.c
+ @ echo "Compiling $<"
+ @ rm -f "$(@:.o=.d)" && env DEPENDENCIES_OUTPUT="$(@:.o=.d)
$@" $(CC) $(CFLAGS) -c $< -o $@
+
+$(OBJDIR)/%.o: %.cc
+ @ echo "Compiling $<"
+ @ rm -f "$(@:.o=.d)" && env DEPENDENCIES_OUTPUT="$(@:.o=.d)
$@" $(CXX) $(CXXFLAGS) -c $< -o $@
+
+
+define LINK
+ @ echo "Linking $@"
+ @ rm -f $@
+ @ $(CXX) $(CXXFLAGS) $^ $(LDFLAGS) $(LIBS) -o $@
+endef
+
+define STATICLIB
+ @ echo "Creating library $@"
+ @ rm -f $@
+ @ $(AR) -rcs $@ $^
+endef
+
+define SHAREDLIB
+ @ echo "Creating library $@"
+ @ rm -f $@
+ @ $(CXX) $(CXXFLAGS) -shared $^ -o $@
+endef
+
+
+-include $(OBJDIR)/*.d
+
Index: external/trimesh/COPYING
--- external/trimesh/COPYING (revision 0)
+++ external/trimesh/COPYING (revision 0)
@@ -0,0 +1,302 @@
+This distribution includes source to "miniball", "freeGLUT",
+and "GLUI", which are covered under their own licenses.
+
+All other code distributed as part of trimesh2 is covered
+by the following license:
+
+
+Copyright (c) 2004-2007 Szymon Rusinkiewicz.
+All rights reserved.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License,
+Version 2, as reprinted below.
+
+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.
+
+
+
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
+
+ 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.)
+
+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.
+
+ 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.
+
+ 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
Index: external/trimesh/Makerules
--- external/trimesh/Makerules (revision 0)
+++ external/trimesh/Makerules (revision 0)
@@ -0,0 +1,80 @@
+#
+# Makerules
+#
+# Pays attention to the following variables:
+# DEBUG = y - debugging compiler flags
+# UNAME = xxxxx - cross-compile for the given platform
+# (In particular, you can say UNAME = Win32 if mingw
+# is installed to cross-compile for Windows, or
+# UNAME = IRIX64 to get 64-bit binaries on IRIX
+# instead of -n32)
+# If UNAME undefined on input, gets defined here.
+# DESTDIR = xxxx - Place to put output binaries.
+# MAKERULESDIR - Where to find Makerules and Makedefs
+#
+#
+# Defines the following variables:
+# UNAME - destination system type (if not set by user)
+# OBJDIR - directory for object files
+# CC - C compiler
+# CXX - C++ compiler
+# CFLAGS - C compiler flags
+# CXXFLAGS - C++ compiler flags
+# LDFLAGS - Linker flags
+# LIBS - Libraries
+# GLLIBS - OpenGL libraries
+# EXE - Extension of executables (.exe under Win32)
+# LINK - The entire linking process
+# STATICLIB - Create .a archive
+# SHAREDLIB - Create .so archive
+#
+#
+# Client Makefiles need to define a "default:" rule
+# - SMR
+#
+
+ifdef windir
+ UNAME := Win32
+else
+ UNAME := $(shell uname)
+ UNAME := $(patsubst CYGWIN%,Win32,$(UNAME))
+
+ ARCH := $(shell uname -m)
+ ifeq ($(ARCH),x86_64)
+ UNAME := Linux64
+ endif
+endif
+
+ifndef DESTDIR
+ DESTDIR = .
+endif
+
+OBJDIR = OBJ.$(UNAME)
+all: $(OBJDIR) $(DESTDIR) default
+
+$(OBJDIR) $(DESTDIR):
+ -mkdir $@
+
+ifdef MAKERULESDIR
+ include $(MAKERULESDIR)/Makedefs.$(UNAME)
+else
+ include Makedefs.$(UNAME)
+endif
+
+ifdef DEBUG
+ DEFINES += -DDEBUG
+endif
+debug:
+ $(MAKE) DEBUG=y
+
+win32:
+ $(MAKE) UNAME=Win32
+
+linux32:
+ $(MAKE) UNAME=Linux
+
+linux64:
+ $(MAKE) UNAME=Linux64
+
+.PHONY: all default clean debug win32 linux32 linux64
+
Index: external/trimesh/README
--- external/trimesh/README (revision 0)
+++ external/trimesh/README (revision 0)
@@ -0,0 +1,144 @@
+
+This is trimesh2, a C++ library and set of utilities for input, output,
+and basic manipulation of 3D triangle meshes. The goals of the code are
+ease of use and efficiency, possibly at the expense of some generality.
+
+
+The library includes the following:
+
+ - Support for reading PLY, OFF, 3DS, VVD, and Wavefront OBJ files,
+ together with a few other formats of mostly local interest (SM, RAY).
+
+ - Support for writing PLY, OFF, and OBJ files.
+
+ - A templated C++ class for constant-length vectors, with support for the
+ usual arithmetic operations (add, subtract, componentwise multiply and
+ divide, dot product, cross product, etc.)
+
+ - A class for rigid-body transformations.
+
+ - An OpenGL trackball/arcball implementation, with automatic selection of
+ rotation center.
+
+ - Algorithms for subdivision, smoothing, curvature estimation, triangle
+ stripping, and various other simple mesh manipulations.
+
+
+Bundled together with the library are:
+
+ - Bernd Gartner's "miniball" code for efficient exact bounding sphere
+ computation:
http://www.inf.ethz.ch/personal/gaertner/minibal.html
+
+ - An ever-so-slightly tweaked version of the freeglut library, an
+ open source GLUT replacement:
http://freeglut.sourceforge.net/
+
+ - GLUI, a user interface library that sits on top of OpenGL, hence is
+ portable to many different systems:
http://www.nigels.com/glt/glui/
+
+
+In addition, the following utility programs are included:
+
+ - mesh_view: a simple 3D mesh viewer
+
+ - mesh_make: create arbitrarily-tessellated meshes of various simple shapes
+
+ - mesh_filter: applies a variety of simple transformations to a mesh,
+ such as converting formats, flipping faces, subdivision, smoothing,
+ rigid-body transformations, etc.
+
+ - mesh_cc: list and/or extract connected components from a mesh
+
+ - mesh_cat: combine several meshes into a single file
+
+ - mesh_align: align 2 meshes using ICP
+
+
+The author of trimesh2 is Szymon Rusinkiewicz, and the library is
+distributed under the GNU General Public License (GPL). The various
+libraries distributed with trimesh2 are open source, and are believed
+to be covered by GPL-compatible licenses. Please see the COPYING file.
+
+
+Running the utilities:
+----------------------
+
+All of the programs must be run from the command line. Each displays
+a list of options when run without arguments.
+
+In the mesh_view program, the view is changed by dragging with particular
+mouse buttons as follows:
+
+ Left: Rotate (release while moving to spin the object)
+ Middle: Translate left, right, up, down
+ Left+right: Translate left, right, up, down
+ Right: Translate forward and back
+ Mouse wheel: Translate forward and back
+ Ctrl+Left: Move the light
+
+In addition, the following keys invoke various options:
+
+ Space bar: Reset to initial view
+ e: Toggle display of mesh edges
+ l: Toggle lighting
+ q: Exit
+ s: Toggle specular component in reflection
+ 2: Toggle 2-sided lighting
+ x: Write current viewpoint as a ".xf" file
+
+
+Using the library:
+------------------
+
+There is no complete documentation for the library - poke around in
+include/*.h to see what is available, and look in utilsrc/*.cc to
+see how it's used. Here's a trivial program to help you get started:
+
+
+#include "TriMesh.h"
+#include <iostream>
+using namespace std;
+
+int main(int argc, char *argv[])
+{
+ const char *filename = "foo.ply";
+ TriMesh *m = TriMesh::read(filename);
+ if (!m)
+ exit(1);
+
+ cout << "There are " << m->vertices.size() <<
" vertices" << endl;
+ cout << "Vertex 0 is at " << m->vertices[0] <<
endl;
+
+ // Convert triangle strips to faces, if necessary
+ m->need_faces();
+ cout << "Face 0 has vertices " << m->faces[0][0]
<< ", "
+ << m->faces[0][1] << ", and " <<
m->faces[0][2] << endl;
+
+ m->need_normals();
+ cout << "Vertex 0 has normal " << m->normals[0] <<
endl;
+}
+
+
+Compiling:
+----------
+
+The code is written in C++, and is known to compile using a recent (3.x-4.x)
+version of g++. Compiling under Windows is possible using Cygwin or
+Mingw32. Other compilers have not been tested - let me know of any
+successes or failures.
+
+After unpacking the code, edit the appropriate "Makedefs.*" file to
+specify the compiler and any necessary options. If there is no Makedefs
+for your OS, run "uname" to determine what it should be named and create
+one (probably starting with one of the existing files as a template).
+At this point, just running "make" in the top-level directory should make
+the library (placed in lib.`uname`) and utilities (placed in bin.`uname`).
+
+If you have any problems, please double check the following:
+ - You are using a recent version of the compiler
+ - You are using a recent version of GNU make
+ - The correct -I option is included to find all the headers you need,
+ including OpenGL headers
+If you still have problems, let me (smr(a)princeton.edu) know and I'll do
+my best to help resolve them.
+
+
Index: external/trimesh/Makedefs.Linux
--- external/trimesh/Makedefs.Linux (revision 0)
+++ external/trimesh/Makedefs.Linux (revision 0)
@@ -0,0 +1,59 @@
+CC = gcc
+CXX = g++
+AR = ar
+
+COPTS = -m32 -march=pentium3 -mfpmath=sse
+XLIBDIR = /usr/X11R6/lib
+
+ifdef DEBUG
+ COPTS += -fopenmp
+ COPTS += -ggdb3
+ COPTS += -Wall -Wextra -Wno-unused -Wno-sign-compare -Wno-unknown-pragmas
+ CXXOPTS = $(COPTS)
+else
+ COPTS += -fopenmp
+ COPTS += -O3 -ffast-math -funroll-loops -fomit-frame-pointer -ftree-vectorize
+ COPTS += -Wall -Wextra -Wno-unused -Wno-sign-compare -Wno-unknown-pragmas
+ CXXOPTS = $(COPTS)
+ LDOPTS = -s
+endif
+
+CFLAGS = $(INCLUDES) $(DEFINES) $(COPTS)
+CXXFLAGS = $(INCLUDES) $(DEFINES) $(CXXOPTS)
+LDFLAGS = $(LIBDIR) $(LDOPTS)
+
+
+LIBS = -lm
+GLLIBS = -L$(XLIBDIR) -lgluit -lGL -lGLU -lX11 -lXmu -lXi
+
+
+$(OBJDIR)/%.o: %.c
+ @ echo "Compiling $<"
+ @ rm -f "$(@:.o=.d)" && env DEPENDENCIES_OUTPUT="$(@:.o=.d)
$@" $(CC) $(CFLAGS) -c $< -o $@
+
+$(OBJDIR)/%.o: %.cc
+ @ echo "Compiling $<"
+ @ rm -f "$(@:.o=.d)" && env DEPENDENCIES_OUTPUT="$(@:.o=.d)
$@" $(CXX) $(CXXFLAGS) -c $< -o $@
+
+
+define LINK
+ @ echo "Linking $@"
+ @ rm -f $@
+ @ $(CXX) $(CXXFLAGS) $^ $(LDFLAGS) $(LIBS) -o $@
+endef
+
+define STATICLIB
+ @ echo "Creating library $@"
+ @ rm -f $@
+ @ $(AR) -rcs $@ $^
+endef
+
+define SHAREDLIB
+ @ echo "Creating library $@"
+ @ rm -f $@
+ @ $(CXX) $(CXXFLAGS) -shared $^ -o $@
+endef
+
+
+-include $(OBJDIR)/*.d
+
Index: external/trimesh/Makefile
--- external/trimesh/Makefile (revision 0)
+++ external/trimesh/Makefile (revision 0)
@@ -0,0 +1,20 @@
+all win32 linux32 linux64 clean:
+ $(MAKE) -C libsrc $@
+ $(MAKE) -C gluit $@
+ $(MAKE) -C utilsrc $@
+
+debug:
+ $(MAKE) -C libsrc DEBUG=y
+ $(MAKE) -C gluit DEBUG=y
+ $(MAKE) -C utilsrc DEBUG=y
+
+FINDCMD = find trimesh2 -name 'OBJ*' -prune -o -name CVS -prune -o -type f
-print
+
+tar:
+ cd .. && tar zcvf trimesh2.tar.gz `$(FINDCMD) | sort`
+
+zip:
+ cd .. && $(FINDCMD) | sort | zip -9 trimesh2 -@
+
+.PHONY : all clean debug default tar win32 zip
+
Index: external/trimesh/libsrc/subdiv.cc
--- external/trimesh/libsrc/subdiv.cc (revision 0)
+++ external/trimesh/libsrc/subdiv.cc (revision 0)
@@ -0,0 +1,396 @@
+/*
+Szymon Rusinkiewicz
+Princeton University
+
+subdiv.cc
+Perform subdivision on a mesh.
+*/
+
+
+#include <stdio.h>
+#include "TriMesh.h"
+#include "TriMesh_algo.h"
+
+
+// i+1 and i-1 modulo 3
+// This way of computing it tends to be faster than using %
+#define NEXT(i) ((i)<2 ? (i)+1 : (i)-2)
+#define PREV(i) ((i)>0 ? (i)-1 : (i)+2)
+
+
+// Compute the ordinary Loop edge stencil
+static point loop(TriMesh *mesh, int f1, int f2,
+ int v0, int v1, int v2, int v3)
+{
+ return 0.125f * (mesh->vertices[v0] + mesh->vertices[v3]) +
+ 0.375f * (mesh->vertices[v1] + mesh->vertices[v2]);
+}
+
+
+// The point at the opposite quadrilateral corner.
+// If it doesn't exist, reflect the given point across the edge.
+static point opposite(TriMesh *mesh, int f, int v)
+{
+ int ind = mesh->faces[f].indexof(v);
+ int ae = mesh->across_edge[f][ind];
+ if (ae) {
+ int j = mesh->faces[ae].indexof(mesh->faces[f][NEXT(ind)]);
+ return mesh->vertices[mesh->faces[ae][NEXT(j)]];
+ }
+ return mesh->vertices[mesh->faces[f][NEXT(ind)]] +
+ mesh->vertices[mesh->faces[f][PREV(ind)]] -
+ mesh->vertices[v];
+}
+
+
+// Compute the butterfly stencil
+static point butterfly(TriMesh *mesh, int f1, int f2,
+ int v0, int v1, int v2, int v3)
+{
+ point p = 0.5f * (mesh->vertices[v1] + mesh->vertices[v2]) +
+ 0.125f * (mesh->vertices[v0] + mesh->vertices[v3]);
+ p -= 0.0625f * (opposite(mesh, f1, v1) + opposite(mesh, f1, v2) +
+ opposite(mesh, f2, v1) + opposite(mesh, f2, v2));
+ return p;
+}
+
+
+// Compute Loop's new edge mask for an extraordinary vertex for SUBDIV_LOOP_NEW
+static point new_loop_edge(TriMesh *mesh, int f1, int f2,
+ int v0, int v1, int v2, int v3)
+{
+ static const float wts[6][5] = {
+ { 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { 0.3828125f, 0.125f, 0.0078125f, 0.125f, 0 },
+ { 0.3945288f, 0.1215267f, 0.01074729f, 0.01074729f, 0.1215267f },
+ };
+
+ int n = mesh->adjacentfaces[v1].size();
+ if (n <= 3)
+ return loop(mesh, f1, f2, v0, v1, v2, v3);
+ point p;
+ float sumwts = 0.0f;
+ int f = f1;
+ float s1 = 1.0f / n;
+ float s2 = 2.0f * (float)M_PI * s1;
+ float l = 0.375f + 0.25f * cos(s2);
+ float a = (2.0f * l*l*l) / ((1.0f - l) * n);
+ float b = (1.0f / l) - 1.5f;
+ for (int i = 0; i < n; i++) {
+ int ind = mesh->faces[f].indexof(v1);
+ if (ind == -1)
+ return loop(mesh, f1, f2, v0, v1, v2, v3);
+ ind = NEXT(ind);
+ int v = mesh->faces[f][ind];
+ float wt;
+ if (n < 6) {
+ wt = wts[n][i];
+ } else {
+ float c = cos(s2 * i);
+ wt = a * (1.0f + c) * sqr(b + c);
+ }
+ p += wt * mesh->vertices[v];
+ sumwts += wt;
+ f = mesh->across_edge[f][ind];
+ if (f == -1)
+ return loop(mesh, f1, f2, v0, v1, v2, v3);
+ }
+ if (f != f1)
+ return loop(mesh, f1, f2, v0, v1, v2, v3);
+ return p + (1.0f - sumwts) * mesh->vertices[v1];
+}
+
+
+// Compute Zorin's edge mask for an extraordinary vertex for
+// SUBDIV_BUTTERFLY_MODIFIED
+static point zorin_edge(TriMesh *mesh, int f1, int f2,
+ int v0, int v1, int v2, int v3)
+{
+ static const float wts[6][5] = {
+ { 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { 0.4166667f, -0.08333333f, -0.08333333f, 0, 0 },
+ { 0.375f, 0, -0.125f, 0, 0 },
+ { 0.35f, 0.0309017f, -0.0809017f, -0.0809017f, 0.0309017f },
+ };
+
+ int n = mesh->adjacentfaces[v1].size();
+ if (n < 3)
+ return butterfly(mesh, f1, f2, v0, v1, v2, v3);
+ point p;
+ float sumwts = 0.0f;
+ int f = f1;
+ float s1 = 1.0f / n;
+ float s2 = 2.0f * (float)M_PI * s1;
+ for (int i = 0; i < n; i++) {
+ int ind = mesh->faces[f].indexof(v1);
+ if (ind == -1)
+ return butterfly(mesh, f1, f2, v0, v1, v2, v3);
+ ind = NEXT(ind);
+ int v = mesh->faces[f][ind];
+ float wt;
+ if (n < 6) {
+ wt = wts[n][i];
+ } else {
+ float c = cos(s2 * i);
+ wt = s1 * (c*c + c - 0.25f);
+ }
+ p += wt * mesh->vertices[v];
+ sumwts += wt;
+ f = mesh->across_edge[f][ind];
+ if (f == -1)
+ return butterfly(mesh, f1, f2, v0, v1, v2, v3);
+ }
+ if (f != f1)
+ return butterfly(mesh, f1, f2, v0, v1, v2, v3);
+ return p + (1.0f - sumwts) * mesh->vertices[v1];
+}
+
+
+// Average position of all boundary vertices on triangles adjacent to v
+static point avg_bdy(TriMesh *mesh, int v)
+{
+ point p;
+ int n = 0;
+ const vector<int> &a = mesh->adjacentfaces[v];
+ for (int i = 0; i < a.size(); i++) {
+ int f = a[i];
+ for (int j = 0; j < 3; j++) {
+ if (mesh->across_edge[f][j] == -1) {
+ p += mesh->vertices[mesh->faces[f][NEXT(j)]];
+ p += mesh->vertices[mesh->faces[f][PREV(j)]];
+ n += 2;
+ }
+ }
+ }
+ return p * (1.0f / n);
+}
+
+
+// Compute the weight on the central vertex used in updating original
+// vertices in Loop subdivision
+static float loop_update_alpha(int scheme, int n)
+{
+ if (scheme == SUBDIV_LOOP) {
+ if (n == 3) return 0.3438f;
+ else if (n == 4) return 0.4625f;
+ else if (n == 5) return 0.5625f;
+ return 0.625f;
+ } else if (scheme == SUBDIV_LOOP_ORIG) {
+ if (n == 3) return 0.4375f;
+ else if (n == 4) return 0.515625f;
+ else if (n == 5) return 0.5795339f;
+ else if (n == 6) return 0.625f;
+ return 0.375f + (float)sqr(0.375f + 0.25f * cos(2.0f * M_PI / n));
+ }
+ // SUBDIV_LOOP_NEW
+ if (n == 3) return 0.4375f;
+ else if (n == 4) return 0.5f;
+ else if (n == 5) return 0.545466f;
+ else if (n == 6) return 0.625f;
+ float l = 0.375f + 0.25f * (float)cos(2.0f * M_PI / n);
+ float beta = l * (4.0f + l * (5.0f * l - 8.0f)) / (2.0f * (1.0f - l));
+ return 1.0f - beta + l * l;
+}
+
+
+// Insert a new vertex
+static void insert_vert(TriMesh *mesh, int scheme, int f, int e)
+{
+ int v1 = mesh->faces[f][NEXT(e)], v2 = mesh->faces[f][PREV(e)];
+ if (scheme == SUBDIV_PLANAR) {
+ point p = 0.5f * (mesh->vertices[v1] +
+ mesh->vertices[v2]);
+ mesh->vertices.push_back(p);
+ return;
+ }
+
+ int ae = mesh->across_edge[f][e];
+ if (ae == -1) {
+ // Boundary
+ point p = 0.5f * (mesh->vertices[v1] +
+ mesh->vertices[v2]);
+ if (scheme == SUBDIV_BUTTERFLY ||
+ scheme == SUBDIV_BUTTERFLY_MODIFIED) {
+ p *= 1.5f;
+ p -= 0.25f * (avg_bdy(mesh, v1) + avg_bdy(mesh, v2));
+ }
+ mesh->vertices.push_back(p);
+ return;
+ }
+
+ int v0 = mesh->faces[f][e];
+ const TriMesh::Face &aef = mesh->faces[ae];
+ int v3 = aef[NEXT(aef.indexof(v1))];
+ point p;
+ if (scheme == SUBDIV_LOOP || scheme == SUBDIV_LOOP_ORIG) {
+ p = loop(mesh, f, ae, v0, v1, v2, v3);
+ } else if (scheme == SUBDIV_LOOP_NEW) {
+ bool e1 = (mesh->adjacentfaces[v1].size() != 6);
+ bool e2 = (mesh->adjacentfaces[v2].size() != 6);
+ if (e1 && e2)
+ p = 0.5f * (new_loop_edge(mesh, f, ae, v0, v1, v2, v3) +
+ new_loop_edge(mesh, ae, f, v3, v2, v1, v0));
+ else if (e1)
+ p = new_loop_edge(mesh, f, ae, v0, v1, v2, v3);
+ else if (e2)
+ p = new_loop_edge(mesh, ae, f, v3, v2, v1, v0);
+ else
+ p = loop(mesh, f, ae, v0, v1, v2, v3);
+ } else if (scheme == SUBDIV_BUTTERFLY) {
+ p = butterfly(mesh, f, ae, v0, v1, v2, v3);
+ } else if (scheme == SUBDIV_BUTTERFLY_MODIFIED) {
+ bool e1 = (mesh->adjacentfaces[v1].size() != 6);
+ bool e2 = (mesh->adjacentfaces[v2].size() != 6);
+ if (e1 && e2)
+ p = 0.5f * (zorin_edge(mesh, f, ae, v0, v1, v2, v3) +
+ zorin_edge(mesh, ae, f, v3, v2, v1, v0));
+ else if (e1)
+ p = zorin_edge(mesh, f, ae, v0, v1, v2, v3);
+ else if (e2)
+ p = zorin_edge(mesh, ae, f, v3, v2, v1, v0);
+ else
+ p = butterfly(mesh, f, ae, v0, v1, v2, v3);
+ }
+
+ mesh->vertices.push_back(p);
+}
+
+
+// Subdivide a mesh
+void subdiv(TriMesh *mesh, int scheme /* = SUBDIV_LOOP */)
+{
+ bool have_col = !mesh->colors.empty();
+ bool have_conf = !mesh->confidences.empty();
+ mesh->flags.clear();
+ mesh->normals.clear();
+ mesh->pdir1.clear(); mesh->pdir2.clear();
+ mesh->curv1.clear(); mesh->curv2.clear();
+ mesh->dcurv.clear();
+ mesh->cornerareas.clear(); mesh->pointareas.clear();
+ mesh->bbox.valid = false;
+ mesh->bsphere.valid = false;
+ mesh->need_faces(); mesh->tstrips.clear(); mesh->grid.clear();
+ mesh->neighbors.clear();
+ mesh->need_across_edge(); mesh->need_adjacentfaces();
+
+
+ TriMesh::dprintf("Subdividing mesh... ");
+
+ // Introduce new vertices
+ int nf = mesh->faces.size();
+ vector<TriMesh::Face> newverts(nf, TriMesh::Face(-1,-1,-1));
+ int old_nv = mesh->vertices.size();
+ mesh->vertices.reserve(4 * old_nv);
+ vector<int> newvert_count(old_nv + 3*nf);
+ if (have_col)
+ mesh->colors.reserve(4 * old_nv);
+ if (have_conf)
+ mesh->confidences.reserve(4 * old_nv);
+
+ for (int i = 0; i < nf; i++) {
+ for (int j = 0; j < 3; j++) {
+ if (newverts[i][j] != -1)
+ continue;
+ int ae = mesh->across_edge[i][j];
+ if (ae != -1) {
+ if (mesh->across_edge[ae][0] == i)
+ newverts[i][j] = newverts[ae][0];
+ else if (mesh->across_edge[ae][1] == i)
+ newverts[i][j] = newverts[ae][1];
+ else if (mesh->across_edge[ae][2] == i)
+ newverts[i][j] = newverts[ae][2];
+ }
+ if (newverts[i][j] != -1)
+ continue;
+
+ insert_vert(mesh, scheme, i, j);
+ newverts[i][j] = mesh->vertices.size() - 1;
+ if (ae != -1) {
+ if (mesh->across_edge[ae][0] == i)
+ newverts[ae][0] = newverts[i][j];
+ else if (mesh->across_edge[ae][1] == i)
+ newverts[ae][1] = newverts[i][j];
+ else if (mesh->across_edge[ae][2] == i)
+ newverts[ae][2] = newverts[i][j];
+ }
+ const TriMesh::Face &v = mesh->faces[i];
+ if (have_col) {
+ mesh->colors.push_back(0.5f *
+ mesh->colors[v[NEXT(j)]] +
+ mesh->colors[v[PREV(j)]]);
+ }
+ if (have_conf)
+ mesh->confidences.push_back(0.5f *
+ mesh->confidences[v[NEXT(j)]] +
+ mesh->confidences[v[PREV(j)]]);
+ }
+ }
+
+ // Update old vertices
+ if (scheme == SUBDIV_LOOP ||
+ scheme == SUBDIV_LOOP_ORIG ||
+ scheme == SUBDIV_LOOP_NEW) {
+#pragma omp parallel for
+ for (int i = 0; i < old_nv; i++) {
+ point bdyavg, nbdyavg;
+ int nbdy = 0, nnbdy = 0;
+ int naf = mesh->adjacentfaces[i].size();
+ if (!naf)
+ continue;
+ for (int j = 0; j < naf; j++) {
+ int af = mesh->adjacentfaces[i][j];
+ int afi = mesh->faces[af].indexof(i);
+ int n1 = NEXT(afi);
+ int n2 = PREV(afi);
+ if (mesh->across_edge[af][n1] == -1) {
+ bdyavg += mesh->vertices[mesh->faces[af][n2]];
+ nbdy++;
+ } else {
+ nbdyavg += mesh->vertices[mesh->faces[af][n2]];
+ nnbdy++;
+ }
+ if (mesh->across_edge[af][n2] == -1) {
+ bdyavg += mesh->vertices[mesh->faces[af][n1]];
+ nbdy++;
+ } else {
+ nbdyavg += mesh->vertices[mesh->faces[af][n1]];
+ nnbdy++;
+ }
+ }
+
+ float alpha;
+ point newpt;
+ if (nbdy) {
+ newpt = bdyavg / (float) nbdy;
+ alpha = 0.75f;
+ } else if (nnbdy) {
+ newpt = nbdyavg / (float) nnbdy;
+ alpha = loop_update_alpha(scheme, nnbdy/2);
+ } else {
+ continue;
+ }
+ mesh->vertices[i] *= alpha;
+ mesh->vertices[i] += (1.0f - alpha) * newpt;
+ }
+ }
+
+ // Insert new faces
+ mesh->adjacentfaces.clear(); mesh->across_edge.clear();
+ mesh->faces.reserve(4*nf);
+ for (int i = 0; i < nf; i++) {
+ TriMesh::Face &v = mesh->faces[i];
+ TriMesh::Face &n = newverts[i];
+ mesh->faces.push_back(TriMesh::Face(v[0], n[2], n[1]));
+ mesh->faces.push_back(TriMesh::Face(v[1], n[0], n[2]));
+ mesh->faces.push_back(TriMesh::Face(v[2], n[1], n[0]));
+ v = n;
+ }
+
+ TriMesh::dprintf("Done.\n");
+}
+
Index: external/trimesh/libsrc/remove.cc
--- external/trimesh/libsrc/remove.cc (revision 0)
+++ external/trimesh/libsrc/remove.cc (revision 0)
@@ -0,0 +1,137 @@
+/*
+Szymon Rusinkiewicz
+Princeton University
+
+remove.cc
+Removing sets of vertices or faces from TriMeshes.
+*/
+
+#include <stdio.h>
+#include "TriMesh.h"
+#include "TriMesh_algo.h"
+
+
+// Remove the indicated vertices from the TriMesh.
+void remove_vertices(TriMesh *mesh, const vector<bool> &toremove)
+{
+ int nv = mesh->vertices.size();
+
+ // Build a table that tells how the vertices will be remapped
+ if (!nv)
+ return;
+
+ TriMesh::dprintf("Removing vertices... ");
+ vector<int> remap_table(nv);
+ int next = 0;
+ for (int i = 0; i < nv; i++) {
+ if (toremove[i])
+ remap_table[i] = -1;
+ else
+ remap_table[i] = next++;
+ }
+
+ // Nothing to delete?
+ if (next == nv) {
+ TriMesh::dprintf("None removed.\n");
+ return;
+ }
+
+ remap_verts(mesh, remap_table);
+
+ TriMesh::dprintf("%d vertices removed... Done.\n", nv - next);
+}
+
+
+// Remove vertices that aren't referenced by any face
+void remove_unused_vertices(TriMesh *mesh)
+{
+ int nv = mesh->vertices.size();
+ if (!nv)
+ return;
+
+ bool had_faces = !mesh->faces.empty();
+ mesh->need_faces();
+ vector<bool> unused(nv, true);
+ for (int i = 0; i < mesh->faces.size(); i++) {
+ unused[mesh->faces[i][0]] = false;
+ unused[mesh->faces[i][1]] = false;
+ unused[mesh->faces[i][2]] = false;
+ }
+ remove_vertices(mesh, unused);
+ if (!had_faces)
+ mesh->faces.clear();
+}
+
+
+// Remove faces as indicated by toremove. Should probably be
+// followed by a call to remove_unused_vertices()
+void remove_faces(TriMesh *mesh, const vector<bool> &toremove)
+{
+ bool had_tstrips = !mesh->tstrips.empty();
+ bool had_faces = !mesh->faces.empty();
+ mesh->need_faces();
+ int numfaces = mesh->faces.size();
+ if (!numfaces)
+ return;
+
+ mesh->tstrips.clear();
+ mesh->adjacentfaces.clear();
+ mesh->neighbors.clear();
+ mesh->across_edge.clear();
+ mesh->cornerareas.clear();
+ mesh->pointareas.clear();
+
+ TriMesh::dprintf("Removing faces... ");
+ int next = 0;
+ for (int i = 0; i < numfaces; i++) {
+ if (toremove[i])
+ continue;
+ mesh->faces[next++] = mesh->faces[i];
+ }
+ if (next == numfaces) {
+ TriMesh::dprintf("None removed.\n");
+ return;
+ }
+
+ mesh->faces.erase(mesh->faces.begin() + next, mesh->faces.end());
+ TriMesh::dprintf("%d faces removed... Done.\n", numfaces - next);
+
+ if (had_tstrips)
+ mesh->need_tstrips();
+ if (!had_faces)
+ mesh->faces.clear();
+
+ mesh->bbox.valid = false;
+ mesh->bsphere.valid = false;
+}
+
+
+// Remove long, skinny faces. Should probably be followed by a
+// call to remove_unused_vertices()
+void remove_sliver_faces(TriMesh *mesh)
+{
+ mesh->need_faces();
+ int numfaces = mesh->faces.size();
+
+ const float l2thresh = sqr(4.0f * mesh->feature_size());
+ const float cos2thresh = 0.85f;
+ vector<bool> toremove(numfaces, false);
+ for (int i = 0; i < numfaces; i++) {
+ const point &v0 = mesh->vertices[mesh->faces[i][0]];
+ const point &v1 = mesh->vertices[mesh->faces[i][1]];
+ const point &v2 = mesh->vertices[mesh->faces[i][2]];
+ float d01 = dist2(v0, v1);
+ float d12 = dist2(v1, v2);
+ float d20 = dist2(v2, v0);
+ if (d01 < l2thresh && d12 < l2thresh && d20 < l2thresh)
+ continue;
+ // c2 is square of cosine of smallest angle
+ float m = min(min(d01,d12),d20);
+ float c2 = sqr(d01+d12+d20-2.0f*m) * m/(4.0f*d01*d12*d20);
+ if (c2 < cos2thresh)
+ continue;
+ toremove[i] = true;
+ }
+ remove_faces(mesh, toremove);
+}
+
Index: external/trimesh/libsrc/TriMesh_bounding.cc
--- external/trimesh/libsrc/TriMesh_bounding.cc (revision 0)
+++ external/trimesh/libsrc/TriMesh_bounding.cc (revision 0)
@@ -0,0 +1,135 @@
+/*
+Szymon Rusinkiewicz
+Princeton University
+
+TriMesh_bounding.cc
+Bounding box and bounding sphere.
+*/
+
+
+#include <stdio.h>
+#include <float.h>
+#include "TriMesh.h"
+#include "bsphere.h"
+
+
+// Find axis-aligned bounding box of the vertices
+void TriMesh::need_bbox()
+{
+ if (vertices.empty() || bbox.valid)
+ return;
+
+ dprintf("Computing bounding box... ");
+
+ bbox.min = bbox.max = vertices[0];
+ for (int i = 1; i < vertices.size(); i++) {
+ if (vertices[i][0] < bbox.min[0]) bbox.min[0] = vertices[i][0];
+ if (vertices[i][0] > bbox.max[0]) bbox.max[0] = vertices[i][0];
+ if (vertices[i][1] < bbox.min[1]) bbox.min[1] = vertices[i][1];
+ if (vertices[i][1] > bbox.max[1]) bbox.max[1] = vertices[i][1];
+ if (vertices[i][2] < bbox.min[2]) bbox.min[2] = vertices[i][2];
+ if (vertices[i][2] > bbox.max[2]) bbox.max[2] = vertices[i][2];
+ }
+
+ bbox.valid = true;
+ dprintf("Done.\n x = %g .. %g, y = %g .. %g, z = %g .. %g\n",
+ bbox.min[0], bbox.max[0], bbox.min[1],
+ bbox.max[1], bbox.min[2], bbox.max[2]);
+}
+
+
+// Change this to #if 0 to enable a simpler (approximate) bsphere computation
+// that does not use the Miniball code
+#if 1
+
+// Compute bounding sphere of the vertices.
+void TriMesh::need_bsphere()
+{
+ if (vertices.empty() || bsphere.valid)
+ return;
+
+ dprintf("Computing bounding sphere... ");
+
+ Miniball<3,float> mb;
+ mb.check_in(vertices.begin(), vertices.end());
+ mb.build();
+ bsphere.center = mb.center();
+ bsphere.r = sqrt(mb.squared_radius());
+ bsphere.valid = true;
+
+ dprintf("Done.\n center = (%g, %g, %g), radius = %g\n",
+ bsphere.center[0], bsphere.center[1],
+ bsphere.center[2], bsphere.r);
+}
+
+#else
+
+// Find extreme vertex in a given direction
+static int farthest_vertex_along(const TriMesh &t, const vec &dir)
+{
+ const vector<point> &v = t.vertices;
+ int nv = v.size();
+
+ int farthest = 0;
+ float farthest_dot = v[0] DOT dir;
+
+ for (int i = 1; i < nv; i++) {
+ float my_dot = v[i] DOT dir;
+ if (my_dot > farthest_dot)
+ farthest = i, farthest_dot = my_dot;
+ }
+ return farthest;
+}
+
+
+// Approximate bounding sphere code based on an algorithm by Ritter
+void TriMesh::need_bsphere()
+{
+ if (vertices.empty() || bsphere.valid)
+ return;
+
+ need_bbox();
+ dprintf("Computing bounding sphere... ");
+
+ point best_min, best_max;
+ vector<vec> dirs;
+ dirs.push_back(vec(1,0,0));
+ dirs.push_back(vec(0,1,0));
+ dirs.push_back(vec(0,0,1));
+ dirs.push_back(vec(1,1,1));
+ dirs.push_back(vec(1,-1,1));
+ dirs.push_back(vec(1,-1,-1));
+ dirs.push_back(vec(1,1,-1));
+ for (int i = 0; i < dirs.size(); i++) {
+ point p1 = vertices[farthest_vertex_along(*this, -dirs[i])];
+ point p2 = vertices[farthest_vertex_along(*this, dirs[i])];
+ if (dist2(p1, p2) > dist2(best_min, best_max)) {
+ best_min = p1;
+ best_max = p2;
+ }
+ }
+ bsphere.center = 0.5f * (best_min + best_max);
+ bsphere.r = 0.5f * dist(best_min, best_max);
+ float r2 = sqr(bsphere.r);
+
+ // Expand bsphere to contain all points
+ for (int i = 0; i < vertices.size(); i++) {
+ float d2 = dist2(vertices[i], bsphere.center);
+ if (d2 <= r2)
+ continue;
+ float d = sqrt(d2);
+ bsphere.r = 0.5f * (bsphere.r + d);
+ r2 = sqr(bsphere.r);
+ bsphere.center -= vertices[i];
+ bsphere.center *= bsphere.r / d;
+ bsphere.center += vertices[i];
+ }
+
+ bsphere.valid = true;
+ dprintf("Done.\n center = (%g, %g, %g), radius = %g\n",
+ bsphere.center[0], bsphere.center[1],
+ bsphere.center[2], bsphere.r);
+}
+
+#endif
+
Index: external/trimesh/libsrc/TriMesh_pointareas.cc
--- external/trimesh/libsrc/TriMesh_pointareas.cc (revision 0)
+++ external/trimesh/libsrc/TriMesh_pointareas.cc (revision 0)
@@ -0,0 +1,77 @@
+/*
+Szymon Rusinkiewicz
+Princeton University
+
+TriMesh_pointareas.cc
+Compute the area "belonging" to each vertex or each corner
+of a triangle (defined as Voronoi area restricted to the 1-ring of
+a vertex, or to the triangle).
+*/
+
+#include <stdio.h>
+#include "TriMesh.h"
+
+
+// Compute per-vertex point areas
+void TriMesh::need_pointareas()
+{
+ if (pointareas.size() == vertices.size())
+ return;
+ need_faces();
+
+ dprintf("Computing point areas... ");
+
+ int nf = faces.size(), nv = vertices.size();
+ pointareas.clear();
+ pointareas.resize(nv);
+ cornerareas.clear();
+ cornerareas.resize(nf);
+
+#pragma omp parallel for
+ for (int i = 0; i < nf; i++) {
+ // Edges
+ vec e[3] = { vertices[faces[i][2]] - vertices[faces[i][1]],
+ vertices[faces[i][0]] - vertices[faces[i][2]],
+ vertices[faces[i][1]] - vertices[faces[i][0]] };
+
+ // Compute corner weights
+ float area = 0.5f * len(e[0] CROSS e[1]);
+ float l2[3] = { len2(e[0]), len2(e[1]), len2(e[2]) };
+ float ew[3] = { l2[0] * (l2[1] + l2[2] - l2[0]),
+ l2[1] * (l2[2] + l2[0] - l2[1]),
+ l2[2] * (l2[0] + l2[1] - l2[2]) };
+ if (ew[0] <= 0.0f) {
+ cornerareas[i][1] = -0.25f * l2[2] * area /
+ (e[0] DOT e[2]);
+ cornerareas[i][2] = -0.25f * l2[1] * area /
+ (e[0] DOT e[1]);
+ cornerareas[i][0] = area - cornerareas[i][1] -
+ cornerareas[i][2];
+ } else if (ew[1] <= 0.0f) {
+ cornerareas[i][2] = -0.25f * l2[0] * area /
+ (e[1] DOT e[0]);
+ cornerareas[i][0] = -0.25f * l2[2] * area /
+ (e[1] DOT e[2]);
+ cornerareas[i][1] = area - cornerareas[i][2] -
+ cornerareas[i][0];
+ } else if (ew[2] <= 0.0f) {
+ cornerareas[i][0] = -0.25f * l2[1] * area /
+ (e[2] DOT e[1]);
+ cornerareas[i][1] = -0.25f * l2[0] * area /
+ (e[2] DOT e[0]);
+ cornerareas[i][2] = area - cornerareas[i][0] -
+ cornerareas[i][1];
+ } else {
+ float ewscale = 0.5f * area / (ew[0] + ew[1] + ew[2]);
+ for (int j = 0; j < 3; j++)
+ cornerareas[i][j] = ewscale * (ew[(j+1)%3] +
+ ew[(j+2)%3]);
+ }
+ pointareas[faces[i][0]] += cornerareas[i][0];
+ pointareas[faces[i][1]] += cornerareas[i][1];
+ pointareas[faces[i][2]] += cornerareas[i][2];
+ }
+
+ dprintf("Done.\n");
+}
+
Index: external/trimesh/libsrc/lmsmooth.cc
--- external/trimesh/libsrc/lmsmooth.cc (revision 0)
+++ external/trimesh/libsrc/lmsmooth.cc (revision 0)
@@ -0,0 +1,76 @@
+/*
+Szymon Rusinkiewicz
+Princeton University
+
+lmsmooth.cc
+Taubin lambda/mu mesh smoothing
+*/
+
+#include <stdio.h>
+#include "TriMesh.h"
+#include "TriMesh_algo.h"
+
+
+// One iteration of umbrella-operator smoothing
+void umbrella(TriMesh *mesh, float stepsize)
+{
+ mesh->need_neighbors();
+ mesh->need_adjacentfaces();
+ int nv = mesh->vertices.size();
+ vector<vec> disp(nv);
+#pragma omp parallel for
+ for (int i = 0; i < nv; i++) {
+ if (mesh->is_bdy(i)) {
+ // Change to #if 1 to smooth boundaries.
+ // This way, we leave boundaries alone.
+#if 0
+ int nn = mesh->neighbors[i].size();
+ int nnused = 0;
+ if (!nn)
+ continue;
+ for (int j = 0; j < nn; j++) {
+ if (!mesh->is_bdy(mesh->neighbors[i][j]))
+ continue;
+ disp[i] += mesh->vertices[mesh->neighbors[i][j]];
+ nnused++;
+ }
+ disp[i] /= nnused;
+ disp[i] -= mesh->vertices[i];
+#else
+ disp[i].clear();
+#endif
+ } else {
+ int nn = mesh->neighbors[i].size();
+ if (!nn)
+ continue;
+ for (int j = 0; j < nn; j++)
+ disp[i] += mesh->vertices[mesh->neighbors[i][j]];
+ disp[i] /= (float)nn;
+ disp[i] -= mesh->vertices[i];
+ }
+ }
+#pragma omp parallel for
+ for (int i = 0; i < nv; i++)
+ mesh->vertices[i] += stepsize * disp[i];
+
+ mesh->bbox.valid = false;
+ mesh->bsphere.valid = false;
+}
+
+
+// Several iterations of Taubin lambda/mu
+void lmsmooth(TriMesh *mesh, int niters)
+{
+ mesh->need_neighbors();
+ mesh->need_adjacentfaces();
+ TriMesh::dprintf("Smoothing mesh... ");
+ for (int i = 0; i < niters; i++) {
+ umbrella(mesh, 0.330f);
+ umbrella(mesh, -0.331f);
+ }
+ TriMesh::dprintf("Done.\n");
+
+ mesh->bbox.valid = false;
+ mesh->bsphere.valid = false;
+}
+
Index: external/trimesh/libsrc/TriMesh_io.cc
--- external/trimesh/libsrc/TriMesh_io.cc (revision 0)
+++ external/trimesh/libsrc/TriMesh_io.cc (revision 0)
@@ -0,0 +1,1925 @@
+/*
+Szymon Rusinkiewicz
+Princeton University
+
+TriMesh_io.cc
+Input and output of triangle meshes
+Can read: PLY (triangle mesh and range grid), OFF, OBJ, RAY, SM, 3DS, VVD
+Can write: PLY (triangle mesh and range grid), OFF, OBJ, RAY, SM, C++
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdarg.h>
+#include "TriMesh.h"
+
+#ifdef WIN32
+# ifndef strncasecmp
+# define strncasecmp strnicmp
+# endif
+#endif
+
+#define GET_LINE() if (!fgets(buf, 1024, f)) return false
+#define COND_READ(cond, where, len) if ((cond) && !fread((void *)&(where),
(len), 1, f)) return false
+#define LINE_IS(text) !strncasecmp(buf, text, strlen(text))
+
+#define BIGNUM 1.0e10
+
+
+// Forward declarations
+static bool read_ply(FILE *f, TriMesh *mesh);
+static bool read_3ds(FILE *f, TriMesh *mesh);
+static bool read_vvd(FILE *f, TriMesh *mesh);
+static bool read_ray(FILE *f, TriMesh *mesh);
+static bool read_obj(FILE *f, TriMesh *mesh);
+static bool read_off(FILE *f, TriMesh *mesh);
+static bool read_sm( FILE *f, TriMesh *mesh);
+
+static bool read_verts_bin(FILE *f, TriMesh *mesh, bool &need_swap,
+ int nverts, int vert_len, int vert_pos, int vert_norm,
+ int vert_color, bool float_color, int vert_conf);
+static bool slurp_verts_bin(FILE *f, TriMesh *mesh, bool need_swap,
+ int nverts);
+static bool read_verts_asc(FILE *f, TriMesh *mesh,
+ int nverts, int vert_len, int vert_pos, int vert_norm,
+ int vert_color, bool float_color, int vert_conf);
+static bool read_faces_bin(FILE *f, TriMesh *mesh, bool need_swap,
+ int nfaces, int face_len, int face_count, int face_idx);
+static bool read_faces_asc(FILE *f, TriMesh *mesh, int nfaces,
+ int face_len, int face_count, int face_idx, bool read_to_eol = false);
+static bool read_strips_bin(FILE *f, TriMesh *mesh, bool need_swap);
+static bool read_strips_asc(FILE *f, TriMesh *mesh);
+static bool read_grid_bin(FILE *f, TriMesh *mesh, bool need_swap);
+static bool read_grid_asc(FILE *f, TriMesh *mesh);
+
+static bool ply_property(const char *buf, int &len, bool binary);
+static bool we_are_little_endian();
+static void check_need_swap(const point &p, bool &need_swap);
+static void check_ind_range(TriMesh *mesh);
+static void skip_comments(FILE *f);
+static void tess(const vector<point> &verts, const vector<int>
&thisface,
+ vector<TriMesh::Face> &tris);
+
+static void write_ply_ascii(TriMesh *mesh, FILE *f,
+ bool write_norm, bool float_color);
+static void write_ply_binary(TriMesh *mesh, FILE *f,
+ bool need_swap, bool write_norm, bool float_color);
+static void write_ray(TriMesh *mesh, FILE *f);
+static void write_obj(TriMesh *mesh, FILE *f);
+static void write_off(TriMesh *mesh, FILE *f);
+static void write_sm(TriMesh *mesh, FILE *f);
+static void write_cc(TriMesh *mesh, FILE *f, const char *filename,
+ bool write_norm, bool float_color);
+static void write_verts_asc(TriMesh *mesh, FILE *f,
+ const char *before_vert,
+ const char *before_norm,
+ const char *before_color,
+ bool float_color,
+ const char *before_conf,
+ const char *after_line);
+static void write_verts_bin(TriMesh *mesh, FILE *f, bool need_swap,
+ bool write_norm, bool write_color,
+ bool float_color, bool write_conf);
+static void write_faces_asc(TriMesh *mesh, FILE *f,
+ const char *before_face, const char *after_line);
+static void write_faces_bin(TriMesh *mesh, FILE *f, bool need_swap,
+ int before_face_len, const char *before_face,
+ int after_face_len, const char *after_face);
+static void write_strips_asc(TriMesh *mesh, FILE *f);
+static void write_strips_bin(TriMesh *mesh, FILE *f, bool need_swap);
+static void write_grid_asc(TriMesh *mesh, FILE *f);
+static void write_grid_bin(TriMesh *mesh, FILE *f, bool need_swap);
+
+
+
+// Byte swap uints, ints, and floats
+static inline void swap_unsigned(volatile unsigned &x)
+{
+ x = (x << 24u) |
+ ((x << 8u) & 0x00ff0000u) |
+ ((x >> 8u) & 0x0000ff00u) |
+ (x >> 24u);
+}
+
+static inline void swap_int(int &x)
+{
+ swap_unsigned(* (unsigned *)(&x));
+}
+
+static inline void swap_float(float &x)
+{
+ swap_unsigned(* (unsigned *)(&x));
+}
+
+static inline void swap_double(double &x)
+{
+ unsigned char buf[8];
+ memcpy(buf, &x, 8);
+ swap(buf[0], buf[7]);
+ swap(buf[1], buf[6]);
+ swap(buf[2], buf[5]);
+ swap(buf[3], buf[4]);
+ memcpy(&x, buf, 8);
+}
+
+static inline void swap_ushort(volatile unsigned short &x)
+{
+ x = (x << 8u) | (x >> 8u);
+}
+
+static inline void swap_short(signed short &x)
+{
+ swap_ushort(* (unsigned short *)(&x));
+}
+
+
+
+// unget a whole string of characters
+static void pushback(const char *buf, FILE *f)
+{
+ const char *c = buf;
+ while (*c)
+ c++;
+ while ((--c) >= buf)
+ ungetc(*c, f);
+}
+
+
+// Read a TriMesh from a file. Defined to use a helper function to make
+// subclassing easier.
+TriMesh *TriMesh::read(const char *filename)
+{
+ TriMesh *mesh = new TriMesh();
+
+ if (read_helper(filename, mesh))
+ return mesh;
+
+ delete mesh;
+ return NULL;
+}
+
+
+// Actually read a mesh. Tries to figure out type of file from first
+// few bytes. Filename can be "-" for stdin
+bool TriMesh::read_helper(const char *filename, TriMesh *mesh)
+{
+ if (!filename || *filename == '\0')
+ return false;
+
+ FILE *f = NULL;
+ bool ok = false;
+ int c;
+
+ if (strcmp(filename, "-") == 0) {
+ f = stdin;
+ filename = "standard input";
+ } else {
+ f = fopen(filename, "rb");
+ if (!f) {
+ perror("fopen");
+ goto out;
+ }
+ }
+ dprintf("Reading %s... ", filename);
+
+ c = fgetc(f);
+ if (c == EOF) {
+ fprintf(stderr, "Can't read header\n");
+ goto out;
+ }
+
+ if (c == 'p') {
+ // See if it's a ply file
+ char buf[4];
+ if (!fgets(buf, 4, f)) {
+ fprintf(stderr, "Can't read header\n");
+ goto out;
+ }
+ if (strncmp(buf, "ly", 2) == 0)
+ ok = read_ply(f, mesh);
+ } else if (c == 0x4d) {
+ int c2 = fgetc(f);
+ ungetc(c2, f);
+ ungetc(c, f);
+ if (c2 == 0x4d)
+ ok = read_3ds(f, mesh);
+ } else if (c == 'V') {
+ char buf[5];
+ if (!fgets(buf, 5, f)) {
+ fprintf(stderr, "Can't read header\n");
+ goto out;
+ }
+ if (strncmp(buf, "IVID", 4) == 0)
+ ok = read_vvd(f, mesh);
+ } else if (c == '#') {
+ char buf[1024];
+ fscanf(f, "%1024s", buf);
+ if (LINE_IS("material") || LINE_IS("vertex") ||
+ LINE_IS("shape_")) {
+ // Assume a ray file
+ pushback(buf, f);
+ ungetc(c, f);
+ ok = read_ray(f, mesh);
+ } else {
+ // Assume an obj file
+ ok = read_obj(f, mesh);
+ }
+ } else if (c == 'v' || c == 'u' || c == 'f' || c == 'g'
|| c == 's' || c == 'o') {
+ // Assume an obj file
+ ungetc(c, f);
+ ok = read_obj(f, mesh);
+ } else if (c == 'O') {
+ // Assume an OFF file
+ char buf[3];
+ if (!fgets(buf, 3, f)) {
+ fprintf(stderr, "Can't read header\n");
+ goto out;
+ }
+ if (strncmp(buf, "FF", 2) == 0)
+ ok = read_off(f, mesh);
+ } else if (isdigit(c)) {
+ // Assume an old-style sm file
+ ungetc(c, f);
+ ok = read_sm(f, mesh);
+ } else {
+ fprintf(stderr, "Unknown file type\n");
+ }
+
+out:
+ if (f)
+ fclose(f);
+ if (!ok || (mesh->vertices.empty() && mesh->faces.empty())) {
+ fprintf(stderr, "\nError reading file [%s]\n", filename);
+ return false;
+ }
+
+ dprintf("Done.\n");
+ check_ind_range(mesh);
+ return true;
+}
+
+
+// Read a ply file
+static bool read_ply(FILE *f, TriMesh *mesh)
+{
+ char buf[1024];
+ bool binary = false, need_swap = false, float_color = false;
+ int result, nverts = 0, nfaces = 0, nstrips = 0, ngrid = 0;
+ int vert_len = 0, vert_pos = -1, vert_norm = -1;
+ int vert_color = -1, vert_conf = -1;
+ int face_len = 0, face_count = -1, face_idx = -1;
+
+ // Read file format
+ GET_LINE();
+ while (buf[0] && isspace(buf[0]))
+ GET_LINE();
+ if (LINE_IS("format binary_big_endian 1.0")) {
+ binary = true;
+ need_swap = we_are_little_endian();
+ } else if (LINE_IS("format binary_little_endian 1.0")) {
+ binary = true;
+ need_swap = !we_are_little_endian();
+ } else if (LINE_IS("format ascii 1.0")) {
+ binary = false;
+ } else {
+ fprintf(stderr, "Unknown ply format or version\n");
+ return false;
+ }
+
+ // Skip comments and unknown obj_info lines
+ GET_LINE();
+ while (LINE_IS("obj_info") || LINE_IS("comment")) {
+ if (LINE_IS("obj_info num_cols"))
+ sscanf(buf, "obj_info num_cols %d", &mesh->grid_width);
+ if (LINE_IS("obj_info num_rows"))
+ sscanf(buf, "obj_info num_rows %d", &mesh->grid_height);
+ GET_LINE();
+ }
+
+ // Skip until we find vertices
+ int skip1 = 0;
+ while (!LINE_IS("end_header") && !LINE_IS("element vertex"))
{
+ char elem_name[1024];
+ int nelem = 0, elem_len = 0;
+ sscanf(buf, "element %s %d", elem_name, &nelem);
+ GET_LINE();
+ while (LINE_IS("property")) {
+ if (!ply_property(buf, elem_len, binary))
+ return false;
+ GET_LINE();
+ }
+ skip1 += nelem * elem_len;
+ }
+
+ // Find number of vertices
+ result = sscanf(buf, "element vertex %d\n", &nverts);
+ if (result != 1) {
+ fprintf(stderr, "Expected \"element vertex\"\n");
+ return false;
+ }
+
+ // Parse vertex properties
+ GET_LINE();
+ while (LINE_IS("property")) {
+ if (LINE_IS("property float x") ||
+ LINE_IS("property float32 x"))
+ vert_pos = vert_len;
+ if (LINE_IS("property float nx") ||
+ LINE_IS("property float32 nx"))
+ vert_norm = vert_len;
+ if (LINE_IS("property uchar diffuse_red") ||
+ LINE_IS("property uint8 diffuse_red") ||
+ LINE_IS("property uchar red") ||
+ LINE_IS("property uint8 red"))
+ vert_color = vert_len;
+ if (LINE_IS("property float diffuse_red") ||
+ LINE_IS("property float32 diffuse_red") ||
+ LINE_IS("property float red") ||
+ LINE_IS("property float32 red"))
+ vert_color = vert_len, float_color = true;
+ if (LINE_IS("property float confidence") ||
+ LINE_IS("property float32 confidence"))
+ vert_conf = vert_len;
+
+ if (!ply_property(buf, vert_len, binary))
+ return false;
+
+ GET_LINE();
+ }
+
+ // Skip until we find faces
+ int skip2 = 0;
+ while (!LINE_IS("end_header") && !LINE_IS("element face")
&&
+ !LINE_IS("element tristrips") && !LINE_IS("element
range_grid")) {
+ char elem_name[1024];
+ int nelem = 0, elem_len = 0;
+ sscanf(buf, "element %s %d", elem_name, &nelem);
+ GET_LINE();
+ while (LINE_IS("property")) {
+ if (!ply_property(buf, elem_len, binary))
+ return false;
+ GET_LINE();
+ }
+ skip2 += nelem * elem_len;
+ }
+
+
+ // Look for faces, tristrips, or range grid
+ if (LINE_IS("element face")) {
+ if (sscanf(buf, "element face %d\n", &nfaces) != 1)
+ return false;
+ GET_LINE();
+ while (LINE_IS("property")) {
+ if (LINE_IS("property list uchar int vertex_indices") ||
+ LINE_IS("property list uint8 int32 vertex_indices") ||
+ LINE_IS("property list char int vertex_indices") ||
+ LINE_IS("property list int8 int32 vertex_indices") ||
+ LINE_IS("property list uchar int vertex_index") ||
+ LINE_IS("property list uint8 int32 vertex_index") ||
+ LINE_IS("property list char int vertex_index") ||
+ LINE_IS("property list int8 int32 vertex_index")) {
+ face_count = face_len;
+ face_idx = face_len + 1;
+ face_len += 1;
+ } else if
+ (LINE_IS("property list uint int vertex_indices") ||
+ LINE_IS("property list uint32 int32 vertex_indices") ||
+ LINE_IS("property list int int vertex_indices") ||
+ LINE_IS("property list int32 int32 vertex_indices") ||
+ LINE_IS("property list uint int vertex_index") ||
+ LINE_IS("property list uint32 int32 vertex_index") ||
+ LINE_IS("property list int int vertex_index") ||
+ LINE_IS("property list int32 int32 vertex_index")) {
+ face_count = face_len;
+ face_idx = face_len + (binary ? 4 : 1);
+ face_len += (binary ? 4 : 1);
+ } else if (!ply_property(buf, face_len, binary))
+ return false;
+ GET_LINE();
+ }
+ } else if (LINE_IS("element tristrips")) {
+ nstrips = 1;
+ GET_LINE();
+ if (!LINE_IS("property list int int vertex_indices") &&
+ !LINE_IS("property list int32 int32 vertex_indices"))
+ return false;
+ GET_LINE();
+ } else if (LINE_IS("element range_grid")) {
+ if (sscanf(buf, "element range_grid %d\n", &ngrid) != 1)
+ return false;
+ if (ngrid != mesh->grid_width*mesh->grid_height) {
+ fprintf(stderr, "Range grid size does not equal num_rows*num_cols\n");
+ return false;
+ }
+ GET_LINE();
+ if (!LINE_IS("property list uchar int vertex_indices") &&
+ !LINE_IS("property list uint8 int32 vertex_indices") &&
+ !LINE_IS("property list char int vertex_indices") &&
+ !LINE_IS("property list int8 int32 vertex_indices"))
+ return false;
+ GET_LINE();
+ }
+
+ while (LINE_IS("property")) {
+ if (!ply_property(buf, face_len, binary))
+ return false;
+ GET_LINE();
+ }
+
+ // Skip to the end of the header
+ while (!LINE_IS("end_header"))
+ GET_LINE();
+ if (binary && buf[10] == '\r') {
+ fprintf(stderr, "Warning! Possibly corrupt file\n");
+ fprintf(stderr, " If things don't work, make sure this file was
transferred in BINARY, not ASCII mode\n");
+ }
+
+
+ // Actually read everything in
+ if (skip1) {
+ if (binary)
+ fseek(f, skip1, SEEK_CUR);
+ else
+ for (int i = 0; i < skip1; i++)
+ fscanf(f, "%s", buf);
+ }
+ if (binary) {
+ if (!read_verts_bin(f, mesh, need_swap, nverts, vert_len,
+ vert_pos, vert_norm, vert_color,
+ float_color, vert_conf))
+ return false;
+ } else {
+ if (!read_verts_asc(f, mesh, nverts, vert_len,
+ vert_pos, vert_norm, vert_color,
+ float_color, vert_conf))
+ return false;
+ }
+
+ if (skip2) {
+ if (binary)
+ fseek(f, skip2, SEEK_CUR);
+ else
+ for (int i = 0; i < skip2; i++)
+ fscanf(f, "%s", buf);
+ }
+
+ if (ngrid) {
+ if (binary) {
+ if (!read_grid_bin(f, mesh, need_swap))
+ return false;
+ } else {
+ if (!read_grid_asc(f, mesh))
+ return false;
+ }
+ } else if (nstrips) {
+ if (binary) {
+ if (!read_strips_bin(f, mesh, need_swap))
+ return false;
+ } else {
+ if (!read_strips_asc(f, mesh))
+ return false;
+ }
+ mesh->convert_strips(TriMesh::TSTRIP_LENGTH);
+ } else if (nfaces) {
+ if (binary) {
+ if (!read_faces_bin(f, mesh, need_swap, nfaces,
+ face_len, face_count, face_idx))
+ return false;
+ } else {
+ if (!read_faces_asc(f, mesh, nfaces,
+ face_len, face_count, face_idx))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+#define CHUNK_3DS_MAIN 0x4d4d
+#define CHUNK_3DS_MODEL 0x3d3d
+#define CHUNK_3DS_OBJ 0x4000
+#define CHUNK_3DS_MESH 0x4100
+#define CHUNK_3DS_VERT 0x4110
+#define CHUNK_3DS_FACE 0x4120
+
+// Read a 3DS file.
+static bool read_3ds(FILE *f, TriMesh *mesh)
+{
+ bool need_swap = !we_are_little_endian();
+ int mstart = 0;
+
+ while (!feof(f)) {
+ short chunkid;
+ int chunklen;
+ if (!fread(&chunkid, 2, 1, f) ||
+ !fread(&chunklen, 4, 1, f))
+ return false;
+ if (need_swap) {
+ swap_short(chunkid);
+ swap_int(chunklen);
+ }
+ //TriMesh::dprintf("Found chunk %x of length %d\n", chunkid, chunklen);
+ switch (chunkid) {
+ case CHUNK_3DS_MAIN:
+ case CHUNK_3DS_MODEL:
+ // Just recurse into this chunk
+ break;
+
+ case CHUNK_3DS_OBJ:
+ // Skip name, then recurse
+ while (!feof(f) && fgetc(f))
+ ;
+ break;
+
+ case CHUNK_3DS_MESH:
+ mstart = mesh->vertices.size();
+ break;
+
+ case CHUNK_3DS_VERT: {
+ unsigned short nverts;
+ if (!fread(&nverts, 2, 1, f))
+ return false;
+ if (need_swap)
+ swap_ushort(nverts);
+ read_verts_bin(f, mesh, need_swap,
+ nverts, 12, 0, -1, -1, false, -1);
+ break;
+ }
+ case CHUNK_3DS_FACE: {
+ unsigned short nfaces;
+ if (!fread(&nfaces, 2, 1, f))
+ return false;
+ if (need_swap)
+ swap_ushort(nfaces);
+ TriMesh::dprintf("\n Reading %d faces... ", nfaces);
+ int old_nfaces = mesh->faces.size();
+ int new_nfaces = old_nfaces + nfaces;
+ mesh->faces.resize(new_nfaces);
+ for (int i = old_nfaces; i < new_nfaces; i++) {
+ unsigned short buf[4];
+ COND_READ(true, buf[0], 8);
+ if (need_swap) {
+ swap_ushort(buf[0]);
+ swap_ushort(buf[1]);
+ swap_ushort(buf[2]);
+ }
+ mesh->faces[i][0] = mstart + buf[0];
+ mesh->faces[i][1] = mstart + buf[1];
+ mesh->faces[i][2] = mstart + buf[2];
+ }
+ break;
+ }
+ default: {
+ // Skip over this chunk
+ fseek(f, chunklen-6, SEEK_CUR);
+ }
+ }
+ }
+ return true;
+}
+
+
+// Read a VVD file.
+static bool read_vvd(FILE *f, TriMesh *mesh)
+{
+ bool need_swap = we_are_little_endian();
+ const int skip = 127;
+ char buf[skip];
+ fread(buf, skip, 1, f);
+
+ int nverts;
+ if (fread(&nverts, 4, 1, f) != 1) {
+ fprintf(stderr, "Couldn't read vertex count\n");
+ return false;
+ }
+ if (need_swap)
+ swap_int(nverts);
+ mesh->vertices.resize(nverts);
+ TriMesh::dprintf("\n Reading %d vertices... ", nverts);
+
+ for (int i = 0; i < nverts; i++) {
+ double v[3];
+ if (fread(&v[0], 24, 1, f) != 1) {
+ fprintf(stderr, "Couldn't read vertex\n");
+ return false;
+ }
+ if (need_swap) {
+ swap_double(v[0]);
+ swap_double(v[1]);
+ swap_double(v[2]);
+ }
+ mesh->vertices[i] = point(float(v[0]), float(v[1]), float(v[2]));
+ }
+
+ int nfaces;
+ if (fread(&nfaces, 4, 1, f) != 1) {
+ fprintf(stderr, "Couldn't read face count\n");
+ return false;
+ }
+ if (need_swap)
+ swap_int(nfaces);
+ read_faces_bin(f, mesh, need_swap, nfaces, 4, 0, 4);
+
+ return true;
+}
+
+
+// Read a ray file
+static bool read_ray(FILE *f, TriMesh *mesh)
+{
+ while (!feof(f)) {
+ char buf[1024];
+ buf[0] = '\0';
+ if (fscanf(f, " %1024s", buf) == 0)
+ return true;
+ if (LINE_IS("#vertex")) {
+ float x, y, z;
+ if (fscanf(f, "%f %f %f", &x, &y, &z) != 3) {
+ return false;
+ }
+ mesh->vertices.push_back(point(x,y,z));
+ } else if (LINE_IS("#shape_triangle")) {
+ int f1, f2, f3, m;
+ if (fscanf(f, "%d %d %d %d", &m, &f1, &f2, &f3) != 4) {
+ return false;
+ }
+ mesh->faces.push_back(TriMesh::Face(f1,f2,f3));
+ }
+ }
+ return true;
+}
+
+
+// Read an obj file
+static bool read_obj(FILE *f, TriMesh *mesh)
+{
+ vector<int> thisface;
+ while (1) {
+ skip_comments(f);
+ if (feof(f))
+ return true;
+ char buf[1024];
+ GET_LINE();
+ if (LINE_IS("v ") || LINE_IS("v\t")) {
+ float x, y, z;
+ if (sscanf(buf+1, "%f %f %f", &x, &y, &z) != 3) {
+ return false;
+ }
+ mesh->vertices.push_back(point(x,y,z));
+ } else if (LINE_IS("f ") || LINE_IS("f\t") ||
+ LINE_IS("t ") || LINE_IS("t\t")) {
+ thisface.clear();
+ char *c = buf;
+ while (1) {
+ while (*c && *c != '\n' && !isspace(*c))
+ c++;
+ while (*c && isspace(*c))
+ c++;
+ int thisf;
+ if (sscanf(c, " %d", &thisf) != 1)
+ break;
+ if (thisf < 0)
+ thisf += mesh->vertices.size();
+ else
+ thisf--;
+ thisface.push_back(thisf);
+ }
+ tess(mesh->vertices, thisface, mesh->faces);
+ }
+ }
+ return true;
+}
+
+
+// Read an off file
+static bool read_off(FILE *f, TriMesh *mesh)
+{
+ skip_comments(f);
+ char buf[1024];
+ GET_LINE();
+ int nverts, nfaces, unused;
+ if (sscanf(buf, "%d %d %d", &nverts, &nfaces, &unused) < 2)
+ return false;
+ if (!read_verts_asc(f, mesh, nverts, 3, 0, -1, -1, false, -1))
+ return false;
+ if (!read_faces_asc(f, mesh, nfaces, 1, 0, 1, true))
+ return false;
+
+ return true;
+}
+
+
+// Read an sm file
+static bool read_sm(FILE *f, TriMesh *mesh)
+{
+ int nverts, nfaces;
+
+ if (fscanf(f, "%d", &nverts) != 1)
+ return false;
+
+ if (!read_verts_asc(f, mesh, nverts, 3, 0, -1, -1, false, -1))
+ return false;
+
+ skip_comments(f);
+ if (fscanf(f, "%d", &nfaces) != 1)
+ return true;
+ if (!read_faces_asc(f, mesh, nfaces, 0, -1, 0))
+ return false;
+
+ return true;
+}
+
+
+// Read nverts vertices from a binary file.
+// vert_len = total length of a vertex record in bytes
+// vert_pos, vert_norm, vert_color, vert_conf =
+// position of vertex coordinates / normals / color / confidence in record
+// need_swap = swap for opposite endianness
+// float_color = colors are 4-byte float * 3, vs 1-byte uchar * 3
+static bool read_verts_bin(FILE *f, TriMesh *mesh, bool &need_swap,
+ int nverts, int vert_len, int vert_pos, int vert_norm,
+ int vert_color, bool float_color, int vert_conf)
+{
+ const int vert_size = 12;
+ const int norm_size = 12;
+ const int color_size = float_color ? 12 : 3;
+ const int conf_size = 4;
+
+ if (nverts <= 0 || vert_len < 12 || vert_pos < 0)
+ return false;
+
+ int old_nverts = mesh->vertices.size();
+ int new_nverts = old_nverts + nverts;
+ mesh->vertices.resize(new_nverts);
+
+ bool have_norm = (vert_norm >= 0);
+ bool have_color = (vert_color >= 0);
+ bool have_conf = (vert_conf >= 0);
+ if (have_norm)
+ mesh->normals.resize(new_nverts);
+ if (have_color)
+ mesh->colors.resize(new_nverts);
+ if (have_conf)
+ mesh->confidences.resize(new_nverts);
+
+ unsigned char *buf = new unsigned char[vert_len];
+ COND_READ(true, buf[0], vert_len);
+
+ int i = old_nverts;
+ memcpy(&mesh->vertices[i][0], &buf[vert_pos], vert_size);
+ if (have_norm)
+ memcpy(&mesh->normals[i][0], &buf[vert_norm], norm_size);
+ if (have_color && float_color)
+ memcpy(&mesh->colors[i][0], &buf[vert_color], color_size);
+ if (have_color && !float_color)
+ mesh->colors[i] = Color(&buf[vert_color]);
+ if (have_conf)
+ memcpy(&mesh->confidences[i], &buf[vert_conf], conf_size);
+
+ check_need_swap(mesh->vertices[i], need_swap);
+ if (need_swap) {
+ swap_float(mesh->vertices[i][0]);
+ swap_float(mesh->vertices[i][1]);
+ swap_float(mesh->vertices[i][2]);
+ if (have_norm) {
+ swap_float(mesh->normals[i][0]);
+ swap_float(mesh->normals[i][1]);
+ swap_float(mesh->normals[i][2]);
+ }
+ if (have_color && float_color) {
+ swap_float(mesh->colors[i][0]);
+ swap_float(mesh->colors[i][1]);
+ swap_float(mesh->colors[i][2]);
+ }
+ if (have_conf)
+ swap_float(mesh->confidences[i]);
+ }
+
+ TriMesh::dprintf("\n Reading %d vertices... ", nverts);
+ if (vert_len == 12 && sizeof(point) == 12 && nverts > 1)
+ return slurp_verts_bin(f, mesh, need_swap, nverts);
+ while (++i < new_nverts) {
+ COND_READ(true, buf[0], vert_len);
+ memcpy(&mesh->vertices[i][0], &buf[vert_pos], vert_size);
+ if (have_norm)
+ memcpy(&mesh->normals[i][0], &buf[vert_norm], norm_size);
+ if (have_color && float_color)
+ memcpy(&mesh->colors[i][0], &buf[vert_color], color_size);
+ if (have_color && !float_color)
+ mesh->colors[i] = Color(&buf[vert_color]);
+ if (have_conf)
+ memcpy(&mesh->confidences[i], &buf[vert_conf], conf_size);
+
+ if (need_swap) {
+ swap_float(mesh->vertices[i][0]);
+ swap_float(mesh->vertices[i][1]);
+ swap_float(mesh->vertices[i][2]);
+ if (have_norm) {
+ swap_float(mesh->normals[i][0]);
+ swap_float(mesh->normals[i][1]);
+ swap_float(mesh->normals[i][2]);
+ }
+ if (have_color && float_color) {
+ swap_float(mesh->colors[i][0]);
+ swap_float(mesh->colors[i][1]);
+ swap_float(mesh->colors[i][2]);
+ }
+ if (have_conf)
+ swap_float(mesh->confidences[i]);
+ }
+ }
+
+ return true;
+}
+
+
+// Optimized reader for the simple case of just vertices w/o other properties
+static bool slurp_verts_bin(FILE *f, TriMesh *mesh, bool need_swap, int nverts)
+{
+ int first = mesh->vertices.size() - nverts + 1;
+ COND_READ(true, mesh->vertices[first][0], (nverts-1)*12);
+ if (need_swap) {
+ for (int i = first; i < mesh->vertices.size(); i++) {
+ swap_float(mesh->vertices[i][0]);
+ swap_float(mesh->vertices[i][1]);
+ swap_float(mesh->vertices[i][2]);
+ }
+ }
+ return true;
+}
+
+
+// Read a bunch of vertices from an ASCII file.
+// Parameters are as in read_verts_bin, but offsets are in
+// (white-space-separated) words, rather than in bytes
+static bool read_verts_asc(FILE *f, TriMesh *mesh,
+ int nverts, int vert_len, int vert_pos, int vert_norm,
+ int vert_color, bool float_color, int vert_conf)
+{
+ if (nverts <= 0 || vert_len < 3 || vert_pos < 0)
+ return false;
+
+ int old_nverts = mesh->vertices.size();
+ int new_nverts = old_nverts + nverts;
+ mesh->vertices.resize(new_nverts);
+ if (vert_norm > 0)
+ mesh->normals.resize(new_nverts);
+ if (vert_color > 0)
+ mesh->colors.resize(new_nverts);
+ if (vert_conf > 0)
+ mesh->confidences.resize(new_nverts);
+
+ char buf[1024];
+ skip_comments(f);
+ TriMesh::dprintf("\n Reading %d vertices... ", nverts);
+ for (int i = old_nverts; i < new_nverts; i++) {
+ for (int j = 0; j < vert_len; j++) {
+ if (j == vert_pos) {
+ if (fscanf(f, "%f %f %f",
+ &mesh->vertices[i][0],
+ &mesh->vertices[i][1],
+ &mesh->vertices[i][2]) != 3)
+ return false;
+ j += 2;
+ } else if (j == vert_norm) {
+ if (fscanf(f, "%f %f %f",
+ &mesh->normals[i][0],
+ &mesh->normals[i][1],
+ &mesh->normals[i][2]) != 3)
+ return false;
+ j += 2;
+ } else if (j == vert_color && float_color) {
+ float r, g, b;
+ if (fscanf(f, "%f %f %f", &r, &g, &b) != 3)
+ return false;
+ mesh->colors[i] = Color(r,g,b);
+ j += 2;
+ } else if (j == vert_color && !float_color) {
+ int r, g, b;
+ if (fscanf(f, "%d %d %d", &r, &g, &b) != 3)
+ return false;
+ mesh->colors[i] = Color(r,g,b);
+ j += 2;
+ } else if (j == vert_conf) {
+ if (fscanf(f, "%f", &mesh->confidences[i]) != 1)
+ return false;
+ } else {
+ fscanf(f, " %1024s", buf);
+ }
+ }
+ }
+
+ return true;
+}
+
+
+// Read nfaces faces from a binary file.
+// face_len = total length of face record, *not counting the indices*
+// (Yes, this is bizarre, but there is potentially a variable # of indices...)
+// face_count = offset within record of the count of indices in this face
+// (If this is -1, does not read a count and assumes triangles)
+// face_idx = offset within record of the indices themselves
+static bool read_faces_bin(FILE *f, TriMesh *mesh, bool need_swap,
+ int nfaces, int face_len, int face_count, int face_idx)
+{
+ if (nfaces < 0 || face_idx < 0)
+ return false;
+
+ if (nfaces == 0)
+ return true;
+
+ TriMesh::dprintf("\n Reading %d faces... ", nfaces);
+
+ int old_nfaces = mesh->faces.size();
+ int new_nfaces = old_nfaces + nfaces;
+ mesh->faces.reserve(new_nfaces);
+
+ // face_len doesn't include the indices themeselves, since that's
+ // potentially variable-length
+ int face_skip = face_len - face_idx;
+
+ vector<unsigned char> buf(max(face_idx, face_skip));
+ vector<int> thisface;
+ for (int i = 0; i < nfaces; i++) {
+ COND_READ(face_idx > 0, buf[0], face_idx);
+
+ unsigned this_ninds = 3;
+ if (face_count >= 0) {
+ // Read count - either 1 or 4 bytes
+ if (face_idx - face_count == 4) {
+ this_ninds = * (unsigned *) &(buf[face_count]);
+ if (need_swap)
+ swap_unsigned(this_ninds);
+ } else {
+ this_ninds = buf[face_count];
+ }
+ }
+ thisface.resize(this_ninds);
+ COND_READ(true, thisface[0], 4*this_ninds);
+ if (need_swap) {
+ for (size_t j = 0; j < thisface.size(); j++)
+ swap_int(thisface[j]);
+ }
+ tess(mesh->vertices, thisface, mesh->faces);
+ COND_READ(face_skip > 0, buf[0], face_skip);
+ }
+
+ return true;
+}
+
+
+// Read a bunch of faces from an ASCII file
+static bool read_faces_asc(FILE *f, TriMesh *mesh, int nfaces,
+ int face_len, int face_count, int face_idx, bool read_to_eol /* = false */)
+{
+ if (nfaces < 0 || face_idx < 0)
+ return false;
+
+ if (nfaces == 0)
+ return true;
+
+ int old_nfaces = mesh->faces.size();
+ int new_nfaces = old_nfaces + nfaces;
+ mesh->faces.reserve(new_nfaces);
+
+ char buf[1024];
+ skip_comments(f);
+ TriMesh::dprintf("\n Reading %d faces... ", nfaces);
+ vector<int> thisface;
+ for (int i = 0; i < nfaces; i++) {
+ thisface.clear();
+ int this_face_count = 3;
+ for (int j = 0; j < face_len + this_face_count; j++) {
+ if (j >= face_idx && j < face_idx + this_face_count) {
+ thisface.push_back(0);
+ if (!fscanf(f, " %d", &(thisface.back()))) {
+ TriMesh::dprintf("Couldn't read vertex index %d for face %d\n",
+ j - face_idx, i);
+ return false;
+ }
+ } else if (j == face_count) {
+ if (!fscanf(f, " %d", &this_face_count)) {
+ TriMesh::dprintf("Couldn't read vertex count for face %d\n", i);
+ return false;
+ }
+ } else {
+ fscanf(f, " %s", buf);
+ }
+ }
+ tess(mesh->vertices, thisface, mesh->faces);
+ if (read_to_eol) {
+ while (1) {
+ int c = fgetc(f);
+ if (c == EOF || c == '\n')
+ break;
+ }
+ }
+ }
+
+ return true;
+}
+
+
+// Read triangle strips from a binary file
+static bool read_strips_bin(FILE *f, TriMesh *mesh, bool need_swap)
+{
+ int striplen;
+ COND_READ(true, striplen, 4);
+ if (need_swap)
+ swap_int(striplen);
+
+ int old_striplen = mesh->tstrips.size();
+ int new_striplen = old_striplen + striplen;
+ mesh->tstrips.resize(new_striplen);
+
+ TriMesh::dprintf("\n Reading triangle strips... ");
+ COND_READ(true, mesh->tstrips[old_striplen], 4*striplen);
+ if (need_swap) {
+ for (int i = old_striplen; i < new_striplen; i++)
+ swap_int(mesh->tstrips[i]);
+ }
+
+ return true;
+}
+
+
+// Read triangle strips from an ASCII file
+static bool read_strips_asc(FILE *f, TriMesh *mesh)
+{
+ skip_comments(f);
+ int striplen;
+ if (fscanf(f, "%d", &striplen) != 1)
+ return false;
+ int old_striplen = mesh->tstrips.size();
+ int new_striplen = old_striplen + striplen;
+ mesh->tstrips.resize(new_striplen);
+
+ TriMesh::dprintf("\n Reading triangle strips... ");
+ skip_comments(f);
+ for (int i = old_striplen; i < new_striplen; i++)
+ if (fscanf(f, "%d", &mesh->tstrips[i]) != 1)
+ return false;
+
+ return true;
+}
+
+
+// Read range grid data from a binary file
+static bool read_grid_bin(FILE *f, TriMesh *mesh, bool need_swap)
+{
+ TriMesh::dprintf("\n Reading range grid... ");
+ int ngrid = mesh->grid_width * mesh->grid_height;
+ mesh->grid.resize(ngrid, TriMesh::GRID_INVALID);
+ for (int i = 0; i < ngrid; i++) {
+ int n = fgetc(f);
+ if (n == EOF)
+ return false;
+ while (n--) {
+ if (!fread((void *)&(mesh->grid[i]), 4, 1, f))
+ return false;
+ if (need_swap)
+ swap_int(mesh->grid[i]);
+ }
+ }
+
+ mesh->triangulate_grid();
+ return true;
+}
+
+
+// Read range grid data from an ASCII file
+static bool read_grid_asc(FILE *f, TriMesh *mesh)
+{
+ TriMesh::dprintf("\n Reading range grid... ");
+ int ngrid = mesh->grid_width * mesh->grid_height;
+ mesh->grid.resize(ngrid, TriMesh::GRID_INVALID);
+ for (int i = 0; i < ngrid; i++) {
+ int n;
+ if (fscanf(f, "%d", &n) != 1)
+ return false;
+ while (n--) {
+ if (fscanf(f, "%d", &(mesh->grid[i])) != 1)
+ return false;
+ }
+ }
+
+ mesh->triangulate_grid();
+ return true;
+}
+
+
+// Parse a PLY property line, and figure how many bytes it represents
+// Increments "len" by the number of bytes, or by 1 if !binary
+static bool ply_property(const char *buf, int &len, bool binary)
+{
+ if (LINE_IS("property char") ||
+ LINE_IS("property uchar") ||
+ LINE_IS("property int8") ||
+ LINE_IS("property uint8")) {
+ len += 1;
+ } else if (LINE_IS("property short") ||
+ LINE_IS("property ushort") ||
+ LINE_IS("property int16") ||
+ LINE_IS("property uint16")) {
+ len += (binary ? 2 : 1);
+ } else if (LINE_IS("property int") ||
+ LINE_IS("property uint") ||
+ LINE_IS("property float") ||
+ LINE_IS("property int32") ||
+ LINE_IS("property uint32") ||
+ LINE_IS("property float32")) {
+ len += (binary ? 4 : 1);
+ } else if (LINE_IS("property double") ||
+ LINE_IS("property float64")) {
+ len += (binary ? 8 : 1);
+ } else {
+ fprintf(stderr, "Unsupported vertex property: %s\n", buf);
+ return false;
+ }
+ return true;
+}
+
+
+// Figure out whether this machine is little- or big-endian
+static bool we_are_little_endian()
+{
+ char buf[4];
+ *(int *)(&buf[0]) = 1;
+ return (buf[0] == 1);
+}
+
+
+// Figure out whether the need_swap setting makes sense, or whether this
+// file incorrectly declares its endianness
+static void check_need_swap(const point &p, bool &need_swap)
+{
+ float p0 = p[0], p1 = p[1], p2 = p[2];
+ if (need_swap) {
+ swap_float(p0);
+ swap_float(p1);
+ swap_float(p2);
+ }
+ bool makes_sense = (p0 > -BIGNUM && p0 < BIGNUM &&
+ p1 > -BIGNUM && p1 < BIGNUM &&
+ p2 > -BIGNUM && p2 < BIGNUM);
+ if (makes_sense)
+ return;
+
+ swap_float(p0);
+ swap_float(p1);
+ swap_float(p2);
+
+ bool makes_sense_swapped = (p0 > -BIGNUM && p0 < BIGNUM &&
+ p1 > -BIGNUM && p1 < BIGNUM &&
+ p2 > -BIGNUM && p2 < BIGNUM);
+ if (makes_sense_swapped) {
+ fprintf(stderr, "Compensating for bogus endianness.\n");
+ need_swap = !need_swap;
+ }
+}
+
+
+// Check whether the indices in the file mistakenly go
+// from 1..N instead of 0..N-1
+static void check_ind_range(TriMesh *mesh)
+{
+ if (mesh->faces.empty())
+ return;
+ int min_ind = mesh->faces[0][0];
+ int max_ind = mesh->faces[0][0];
+ for (int i = 0; i < mesh->faces.size(); i++) {
+ for (int j = 0; j < 3; j++) {
+ min_ind = min(min_ind, mesh->faces[i][j]);
+ max_ind = max(max_ind, mesh->faces[i][j]);
+ }
+ }
+
+ int nv = mesh->vertices.size();
+
+ // All good
+ if (min_ind == 0 && max_ind == nv-1)
+ return;
+
+ // Simple fix: offset everything
+ if (max_ind - min_ind == nv-1) {
+ TriMesh::dprintf("Found indices ranging from %d through %d\n",
+ min_ind, max_ind);
+ TriMesh::dprintf("Remapping to %d through %d\n", 0, nv-1);
+ for (int i = 0; i < mesh->faces.size(); i++)
+ for (int j = 0; j < 3; j++)
+ mesh->faces[i][j] -= min_ind;
+ return;
+ }
+
+ // Else can't do anything...
+}
+
+
+// Skip comments in an ASCII file (lines beginning with #)
+static void skip_comments(FILE *f)
+{
+ int c;
+ bool in_comment = false;
+ while (1) {
+ c = fgetc(f);
+ if (c == EOF)
+ return;
+ if (in_comment) {
+ if (c == '\n')
+ in_comment = false;
+ } else if (c == '#') {
+ in_comment = true;
+ } else if (!isspace(c)) {
+ break;
+ }
+ }
+ ungetc(c, f);
+}
+
+
+// Tesselate an arbitrary n-gon. Appends triangles to "tris".
+static void tess(const vector<point> &verts, const vector<int>
&thisface,
+ vector<TriMesh::Face> &tris)
+{
+ if (thisface.size() < 3)
+ return;
+ if (thisface.size() == 3) {
+ tris.push_back(TriMesh::Face(thisface[0],
+ thisface[1],
+ thisface[2]));
+ return;
+ }
+ if (thisface.size() == 4) {
+ // Triangulate in the direction that
+ // gives the shorter diagonal
+ const point &p0 = verts[thisface[0]], &p1 = verts[thisface[1]];
+ const point &p2 = verts[thisface[2]], &p3 = verts[thisface[3]];
+ float d02 = dist2(p0, p2);
+ float d13 = dist2(p1, p3);
+ int i = (d02 < d13) ? 0 : 1;
+ tris.push_back(TriMesh::Face(thisface[i],
+ thisface[(i+1)%4],
+ thisface[(i+2)%4]));
+ tris.push_back(TriMesh::Face(thisface[i],
+ thisface[(i+2)%4],
+ thisface[(i+3)%4]));
+ return;
+ }
+
+ // 5-gon or higher - just tesselate arbitrarily...
+ for (int i = 2; i < thisface.size(); i++)
+ tris.push_back(TriMesh::Face(thisface[0],
+ thisface[i-1],
+ thisface[i]));
+}
+
+
+// Write mesh to a file
+void TriMesh::write(const char *filename)
+{
+ if (!filename || *filename == '\0')
+ return;
+
+ if (vertices.empty()) {
+ fprintf(stderr, "Empty mesh - nothing to write!\n");
+ return;
+ }
+
+ enum { PLY_ASCII, PLY_BINARY_BE, PLY_BINARY_LE,
+ RAY, OBJ, OFF, SM, CC } filetype;
+ // Set default file type to be native-endian binary ply
+ filetype = we_are_little_endian() ? PLY_BINARY_LE : PLY_BINARY_BE;
+ bool write_norm = false;
+ bool float_color = false;
+
+ // Infer file type from file extension
+ const char *c = strrchr(filename, '.');
+ if (c) {
+ if (!strncasecmp(c, ".ply", 4))
+ filetype = we_are_little_endian() ?
+ PLY_BINARY_LE :
+ PLY_BINARY_BE;
+ else if (!strncasecmp(c, ".ray", 4))
+ filetype = RAY;
+ else if (!strncasecmp(c, ".obj", 4))
+ filetype = OBJ;
+ else if (!strncasecmp(c, ".off", 4))
+ filetype = OFF;
+ else if (!strncasecmp(c, ".sm", 3))
+ filetype = SM;
+ else if (!strncasecmp(c, ".cc", 3))
+ filetype = CC;
+ else if (!strncasecmp(c, ".c++", 4))
+ filetype = CC;
+ else if (!strncasecmp(c, ".cpp", 4))
+ filetype = CC;
+ else if (!strncasecmp(c, ".C", 2))
+ filetype = CC;
+ }
+
+ // Handle filetype:filename.foo constructs
+ while (1) {
+ if (!strncasecmp(filename, "norm:", 5)) {
+ filename += 5;
+ write_norm = true;
+ } else if (!strncasecmp(filename, "cflt:", 5)) {
+ filename += 5;
+ float_color = true;
+ } else if (!strncasecmp(filename, "ply:", 4)) {
+ filename += 4;
+ filetype = we_are_little_endian() ?
+ PLY_BINARY_LE :
+ PLY_BINARY_BE;
+ } else if (!strncasecmp(filename, "ply_binary:", 11)) {
+ filename += 11;
+ filetype = we_are_little_endian() ?
+ PLY_BINARY_LE :
+ PLY_BINARY_BE;
+ } else if (!strncasecmp(filename, "ply_binary_be:", 14)) {
+ filename += 14;
+ filetype = PLY_BINARY_BE;
+ } else if (!strncasecmp(filename, "ply_binary_le:", 14)) {
+ filename += 14;
+ filetype = PLY_BINARY_LE;
+ } else if (!strncasecmp(filename, "ply_ascii:", 10)) {
+ filename += 10;
+ filetype = PLY_ASCII;
+ } else if (!strncasecmp(filename, "ply_asc:", 8)) {
+ filename += 8;
+ filetype = PLY_ASCII;
+ } else if (!strncasecmp(filename, "ascii:", 6)) {
+ filename += 6;
+ filetype = PLY_ASCII;
+ } else if (!strncasecmp(filename, "asc:", 4)) {
+ filename += 4;
+ filetype = PLY_ASCII;
+ } else if (!strncasecmp(filename, "be:", 3)) {
+ filename += 3;
+ filetype = PLY_BINARY_BE;
+ } else if (!strncasecmp(filename, "le:", 3)) {
+ filename += 3;
+ filetype = PLY_BINARY_LE;
+ } else if (!strncasecmp(filename, "ray:", 4)) {
+ filename += 4;
+ filetype = RAY;
+ } else if (!strncasecmp(filename, "obj:", 4)) {
+ filename += 4;
+ filetype = OBJ;
+ } else if (!strncasecmp(filename, "off:", 4)) {
+ filename += 4;
+ filetype = OFF;
+ } else if (!strncasecmp(filename, "sm:", 3)) {
+ filename += 3;
+ filetype = SM;
+ } else {
+ break;
+ }
+ }
+
+
+ FILE *f = NULL;
+
+ if (strcmp(filename, "-") == 0) {
+ f = stdout;
+ filename = "standard output";
+ } else {
+ f = fopen(filename, "wb");
+ if (!f) {
+ perror("fopen");
+ fprintf(stderr, "Error opening %s for writing.\n", filename);
+ return;
+ }
+ }
+
+ dprintf("Writing %s... ", filename);
+
+ switch (filetype) {
+ case PLY_ASCII:
+ write_ply_ascii(this, f, write_norm, float_color);
+ break;
+ case PLY_BINARY_BE:
+ write_ply_binary(this, f,
+ we_are_little_endian(), write_norm, float_color);
+ break;
+ case PLY_BINARY_LE:
+ write_ply_binary(this, f,
+ !we_are_little_endian(), write_norm, float_color);
+ break;
+ case RAY:
+ write_ray(this, f);
+ break;
+ case OBJ:
+ write_obj(this, f);
+ break;
+ case OFF:
+ write_off(this, f);
+ break;
+ case SM:
+ write_sm(this, f);
+ break;
+ case CC:
+ write_cc(this, f, filename, write_norm, float_color);
+ break;
+ }
+ fclose(f);
+ dprintf("Done.\n");
+}
+
+
+// Write a ply header
+static void write_ply_header(TriMesh *mesh, FILE *f, const char *format,
+ bool write_grid, bool write_tstrips,
+ bool write_norm, bool float_color)
+{
+ fprintf(f, "ply\nformat %s 1.0\n", format);
+ if (write_grid) {
+ fprintf(f, "obj_info num_cols %d\n", mesh->grid_width);
+ fprintf(f, "obj_info num_rows %d\n", mesh->grid_height);
+ }
+ fprintf(f, "element vertex %lu\n",
+ (unsigned long) mesh->vertices.size());
+ fprintf(f, "property float x\n");
+ fprintf(f, "property float y\n");
+ fprintf(f, "property float z\n");
+ if (write_norm && !mesh->normals.empty()) {
+ fprintf(f, "property float nx\n");
+ fprintf(f, "property float ny\n");
+ fprintf(f, "property float nz\n");
+ }
+ if (!mesh->colors.empty() && float_color) {
+ fprintf(f, "property float diffuse_red\n");
+ fprintf(f, "property float diffuse_green\n");
+ fprintf(f, "property float diffuse_blue\n");
+ }
+ if (!mesh->colors.empty() && !float_color) {
+ fprintf(f, "property uchar diffuse_red\n");
+ fprintf(f, "property uchar diffuse_green\n");
+ fprintf(f, "property uchar diffuse_blue\n");
+ }
+ if (!mesh->confidences.empty()) {
+ fprintf(f, "property float confidence\n");
+ }
+ if (write_grid) {
+ int ngrid = mesh->grid_width * mesh->grid_height;
+ fprintf(f, "element range_grid %d\n", ngrid);
+ fprintf(f, "property list uchar int vertex_indices\n");
+ } else if (write_tstrips) {
+ fprintf(f, "element tristrips 1\n");
+ fprintf(f, "property list int int vertex_indices\n");
+ } else {
+ fprintf(f, "element face %lu\n",
+ (unsigned long) mesh->faces.size());
+ fprintf(f, "property list uchar int vertex_indices\n");
+ }
+ fprintf(f, "end_header\n");
+}
+
+
+// Write an ASCII ply file
+static void write_ply_ascii(TriMesh *mesh, FILE *f, bool write_norm,
+ bool float_color)
+{
+ if (write_norm)
+ mesh->need_normals();
+
+ bool write_grid = !mesh->grid.empty();
+ bool write_tstrips = !write_grid && !mesh->tstrips.empty();
+
+ write_ply_header(mesh, f, "ascii", write_grid, write_tstrips,
+ write_norm, float_color);
+ write_verts_asc(mesh, f, "", write_norm ? " " : 0, " ",
float_color,
+ " ", "");
+ if (write_grid) {
+ write_grid_asc(mesh, f);
+ } else if (write_tstrips) {
+ fprintf(f, "%lu ", (unsigned long) mesh->tstrips.size());
+ mesh->convert_strips(TriMesh::TSTRIP_TERM);
+ write_strips_asc(mesh, f);
+ mesh->convert_strips(TriMesh::TSTRIP_LENGTH);
+ } else {
+ write_faces_asc(mesh, f, "3 ", "");
+ }
+}
+
+
+// Write a binary ply file
+static void write_ply_binary(TriMesh *mesh, FILE *f,
+ bool need_swap, bool write_norm, bool float_color)
+{
+ if (write_norm)
+ mesh->need_normals();
+ const char *format = (need_swap ^ we_are_little_endian()) ?
+ "binary_little_endian" : "binary_big_endian";
+
+ bool write_grid = !mesh->grid.empty();
+ bool write_tstrips = !write_grid && !mesh->tstrips.empty();
+
+ write_ply_header(mesh, f, format, write_grid, write_tstrips,
+ write_norm, float_color);
+ write_verts_bin(mesh, f, need_swap, write_norm, true, float_color, true);
+ if (write_grid) {
+ write_grid_bin(mesh, f, need_swap);
+ } else if (write_tstrips) {
+ int s = mesh->tstrips.size();
+ if (need_swap)
+ swap_int(s);
+ fwrite(&s, 4, 1, f);
+ mesh->convert_strips(TriMesh::TSTRIP_TERM);
+ write_strips_bin(mesh, f, need_swap);
+ mesh->convert_strips(TriMesh::TSTRIP_LENGTH);
+ } else {
+ char buf[1] = { 3 };
+ write_faces_bin(mesh, f, need_swap, 1, buf, 0, 0);
+ }
+}
+
+
+// Write a ray file
+static void write_ray(TriMesh *mesh, FILE *f)
+{
+ fprintf(f, "#camera 0 0 1 0 0 -1 0 1 0 0.2\n");
+ fprintf(f, "#background 0 0 0\n");
+ fprintf(f, "#ambient 0 0 0\n");
+ fprintf(f, "#material_num 1\n");
+ fprintf(f, "#material 0 0 0 1 1 1 0 0 0 0 0 0 0 0 1 -1 !!\n");
+ fprintf(f, "#vertex_num %lu\n", (unsigned long) mesh->vertices.size());
+ mesh->need_normals();
+ write_verts_asc(mesh, f, "#vertex ", " ", 0, false, 0, " 0
0");
+ mesh->need_faces();
+ write_faces_asc(mesh, f, "#shape_triangle 0 ", "");
+}
+
+
+// Write a obj file
+static void write_obj(TriMesh *mesh, FILE *f)
+{
+ fprintf(f, "# OBJ\n");
+ write_verts_asc(mesh, f, "v ", 0, 0, false, 0, "");
+ mesh->need_faces();
+ for (int i = 0; i < mesh->faces.size(); i++) {
+ mesh->faces[i][0]++;
+ mesh->faces[i][1]++;
+ mesh->faces[i][2]++;
+ }
+ write_faces_asc(mesh, f, "f ", "");
+ for (int i = 0; i < mesh->faces.size(); i++) {
+ mesh->faces[i][0]--;
+ mesh->faces[i][1]--;
+ mesh->faces[i][2]--;
+ }
+}
+
+
+// Write a off file
+static void write_off(TriMesh *mesh, FILE *f)
+{
+ fprintf(f, "OFF\n");
+ mesh->need_faces();
+ fprintf(f, "%lu %lu 0\n", (unsigned long) mesh->vertices.size(),
+ (unsigned long) mesh->faces.size());
+ write_verts_asc(mesh, f, "", 0, 0, false, 0, "");
+ write_faces_asc(mesh, f, "3 ", "");
+}
+
+
+// Write an SM file
+static void write_sm(TriMesh *mesh, FILE *f)
+{
+ fprintf(f, "%lu\n", (unsigned long) mesh->vertices.size());
+ write_verts_asc(mesh, f, "", 0, 0, false, 0, "");
+ mesh->need_faces();
+ fprintf(f, "%lu\n", (unsigned long) mesh->faces.size());
+ write_faces_asc(mesh, f, "", "");
+ fprintf(f, "0 0\n");
+}
+
+
+// Convert colors float -> uchar
+static unsigned char color2uchar(float p)
+{
+ return min(max(int(255.0f * p + 0.5f), 0), 255);
+}
+
+
+// Write C++ code
+static void write_cc(TriMesh *mesh, FILE *f, const char *filename,
+ bool write_norm, bool float_color)
+{
+ mesh->need_faces();
+ if (write_norm)
+ mesh->need_normals();
+
+ char *meshname = new char[strlen(filename)+1];
+ strcpy(meshname, filename);
+ char *c = strrchr(meshname, '.');
+ if (c)
+ *c = '\0';
+ fprintf(f, "#include <string.h>\n");
+ fprintf(f, "#include \"TriMesh.h\"\n\n");
+ fprintf(f, "TriMesh *make_%s()\n{", meshname);
+ delete [] meshname;
+
+ fprintf(f, "\tstatic const float vertdata[][3] = {\n");
+ int nv = mesh->vertices.size(), nf = mesh->faces.size();
+ for (int i = 0; i < nv; i++) {
+ fprintf(f, "\t\t{ %.7g, %.7g, %.7g },\n",
+ mesh->vertices[i][0],
+ mesh->vertices[i][1],
+ mesh->vertices[i][2]);
+ }
+ fprintf(f, "\t};\n");
+ if (write_norm) {
+ fprintf(f, "\tstatic const float normdata[][3] = {\n");
+ for (int i = 0; i < nv; i++) {
+ fprintf(f, "\t\t{ %.7g, %.7g, %.7g },\n",
+ mesh->normals[i][0],
+ mesh->normals[i][1],
+ mesh->normals[i][2]);
+ }
+ fprintf(f, "\t};\n");
+ }
+ if (!mesh->colors.empty() && float_color) {
+ fprintf(f, "\tstatic const float colordata[][3] = {\n");
+ for (int i = 0; i < nv; i++) {
+ fprintf(f, "\t\t{ %.7g, %.7g, %.7g },\n",
+ mesh->colors[i][0],
+ mesh->colors[i][1],
+ mesh->colors[i][2]);
+ }
+ fprintf(f, "\t};\n");
+ }
+ if (!mesh->colors.empty() && !float_color) {
+ fprintf(f, "\tstatic const unsigned char colordata[][3] = {\n");
+ for (int i = 0; i < nv; i++) {
+ fprintf(f, "\t\t{ %d, %d, %d },\n",
+ color2uchar(mesh->colors[i][0]),
+ color2uchar(mesh->colors[i][1]),
+ color2uchar(mesh->colors[i][2]));
+ }
+ fprintf(f, "\t};\n");
+ }
+ fprintf(f, "\tstatic const int facedata[][3] = {\n");
+ for (int i = 0; i < nf; i++) {
+ fprintf(f, "\t\t{ %d, %d, %d },\n",
+ mesh->faces[i][0],
+ mesh->faces[i][1],
+ mesh->faces[i][2]);
+ }
+ fprintf(f, "\t};\n");
+ fprintf(f, "\n\tTriMesh *m = new TriMesh;\n");
+ fprintf(f, "\tm->vertices.resize(%d);\n", nv);
+ fprintf(f, "\tmemcpy(&m->vertices[0][0], vertdata,
sizeof(vertdata));\n");
+ if (!mesh->colors.empty()) {
+ fprintf(f, "\tm->colors.resize(%d);\n", nv);
+ fprintf(f, "\tmemcpy(&m->colors[0][0], colordata,
sizeof(colordata));\n");
+ }
+ if (write_norm) {
+ fprintf(f, "\tm->normals.resize(%d);\n", nv);
+ fprintf(f, "\tmemcpy(&m->normals[0][0], normdata,
sizeof(normdata));\n");
+ }
+ fprintf(f, "\tm->faces.resize(%d);\n", nf);
+ fprintf(f, "\tmemcpy(&m->faces[0][0], facedata,
sizeof(facedata));\n");
+ fprintf(f, "\n\treturn m;\n");
+ fprintf(f, "}\n");
+}
+
+
+// Write a bunch of vertices to an ASCII file
+static void write_verts_asc(TriMesh *mesh, FILE *f,
+ const char *before_vert,
+ const char *before_norm,
+ const char *before_color,
+ bool float_color,
+ const char *before_conf,
+ const char *after_line)
+{
+ for (int i = 0; i < mesh->vertices.size(); i++) {
+ fprintf(f, "%s%.7g %.7g %.7g", before_vert,
+ mesh->vertices[i][0],
+ mesh->vertices[i][1],
+ mesh->vertices[i][2]);
+ if (!mesh->normals.empty() && before_norm)
+ fprintf(f, "%s%.7g %.7g %.7g", before_norm,
+ mesh->normals[i][0],
+ mesh->normals[i][1],
+ mesh->normals[i][2]);
+ if (!mesh->colors.empty() && before_color && float_color)
+ fprintf(f, "%s%.7g %.7g %.7g", before_color,
+ mesh->colors[i][0],
+ mesh->colors[i][1],
+ mesh->colors[i][2]);
+ if (!mesh->colors.empty() && before_color && !float_color)
+ fprintf(f, "%s%d %d %d", before_color,
+ color2uchar(mesh->colors[i][0]),
+ color2uchar(mesh->colors[i][1]),
+ color2uchar(mesh->colors[i][2]));
+ if (!mesh->confidences.empty() && before_conf)
+ fprintf(f, "%s%.7g", before_conf, mesh->confidences[i]);
+ fprintf(f, "%s\n", after_line);
+ }
+}
+
+
+// Write a bunch of vertices to a binary file
+static void write_verts_bin(TriMesh *mesh, FILE *f, bool need_swap,
+ bool write_norm, bool write_color,
+ bool float_color, bool write_conf)
+{
+ if (need_swap) {
+ for (int i = 0; i < mesh->vertices.size(); i++) {
+ swap_float(mesh->vertices[i][0]);
+ swap_float(mesh->vertices[i][1]);
+ swap_float(mesh->vertices[i][2]);
+ }
+ if (!mesh->normals.empty()) {
+ for (int i = 0; i < mesh->normals.size(); i++) {
+ swap_float(mesh->normals[i][0]);
+ swap_float(mesh->normals[i][1]);
+ swap_float(mesh->normals[i][2]);
+ }
+ }
+ if (!mesh->colors.empty() && float_color) {
+ for (int i = 0; i < mesh->normals.size(); i++) {
+ swap_float(mesh->colors[i][0]);
+ swap_float(mesh->colors[i][1]);
+ swap_float(mesh->colors[i][2]);
+ }
+ }
+ if (!mesh->confidences.empty()) {
+ for (int i = 0; i < mesh->confidences.size(); i++)
+ swap_float(mesh->confidences[i]);
+ }
+ }
+ if ((mesh->normals.empty() || !write_norm) &&
+ (mesh->colors.empty() || !write_color) &&
+ (mesh->confidences.empty() || !write_conf)) {
+ // Optimized vertex-only code
+ fwrite(&(mesh->vertices[0][0]), 12*mesh->vertices.size(), 1, f);
+ } else {
+ // Generic code
+ for (int i = 0; i < mesh->vertices.size(); i++) {
+ fwrite(&(mesh->vertices[i][0]), 12, 1, f);
+ if (!mesh->normals.empty() && write_norm)
+ fwrite(&(mesh->normals[i][0]), 12, 1, f);
+ if (!mesh->colors.empty() && write_color && float_color)
+ fwrite(&(mesh->colors[i][0]), 12, 1, f);
+ if (!mesh->colors.empty() && write_color && !float_color) {
+ char c[3] = {
+ color2uchar(mesh->colors[i][0]),
+ color2uchar(mesh->colors[i][1]),
+ color2uchar(mesh->colors[i][2]) };
+ fwrite(&c, 3, 1, f);
+ }
+ if (!mesh->confidences.empty() && write_conf)
+ fwrite(&(mesh->confidences[i]), 4, 1, f);
+ }
+ }
+ if (need_swap) {
+ for (int i = 0; i < mesh->vertices.size(); i++) {
+ swap_float(mesh->vertices[i][0]);
+ swap_float(mesh->vertices[i][1]);
+ swap_float(mesh->vertices[i][2]);
+ }
+ if (!mesh->normals.empty()) {
+ for (int i = 0; i < mesh->normals.size(); i++) {
+ swap_float(mesh->normals[i][0]);
+ swap_float(mesh->normals[i][1]);
+ swap_float(mesh->normals[i][2]);
+ }
+ }
+ if (!mesh->colors.empty() && float_color) {
+ for (int i = 0; i < mesh->normals.size(); i++) {
+ swap_float(mesh->colors[i][0]);
+ swap_float(mesh->colors[i][1]);
+ swap_float(mesh->colors[i][2]);
+ }
+ }
+ if (!mesh->confidences.empty()) {
+ for (int i = 0; i < mesh->confidences.size(); i++)
+ swap_float(mesh->confidences[i]);
+ }
+ }
+}
+
+
+// Write a bunch of faces to an ASCII file
+static void write_faces_asc(TriMesh *mesh, FILE *f,
+ const char *before_face, const char *after_line)
+{
+ mesh->need_faces();
+ for (int i = 0; i < mesh->faces.size(); i++) {
+ fprintf(f, "%s%d %d %d%s\n", before_face, mesh->faces[i][0],
+ mesh->faces[i][1], mesh->faces[i][2], after_line);
+ }
+}
+
+
+// Write a bunch of faces to a binary file
+static void write_faces_bin(TriMesh *mesh, FILE *f, bool need_swap,
+ int before_face_len, const char *before_face,
+ int after_face_len, const char *after_face)
+{
+ mesh->need_faces();
+ if (need_swap) {
+ for (int i = 0; i < mesh->faces.size(); i++) {
+ swap_int(mesh->faces[i][0]);
+ swap_int(mesh->faces[i][1]);
+ swap_int(mesh->faces[i][2]);
+ }
+ }
+ for (int i = 0; i < mesh->faces.size(); i++) {
+ if (before_face_len)
+ fwrite(before_face, before_face_len, 1, f);
+ fwrite(&(mesh->faces[i][0]), 12, 1, f);
+ if (after_face_len)
+ fwrite(after_face, after_face_len, 1, f);
+ }
+ if (need_swap) {
+ for (int i = 0; i < mesh->faces.size(); i++) {
+ swap_int(mesh->faces[i][0]);
+ swap_int(mesh->faces[i][1]);
+ swap_int(mesh->faces[i][2]);
+ }
+ }
+}
+
+
+// Write tstrips to an ASCII file
+static void write_strips_asc(TriMesh *mesh, FILE *f)
+{
+ for (int i = 0; i < mesh->tstrips.size(); i++) {
+ fprintf(f, "%d ", mesh->tstrips[i]);
+ }
+ fprintf(f, "\n");
+}
+
+
+// Write tstrips to a binary file
+static void write_strips_bin(TriMesh *mesh, FILE *f, bool need_swap)
+{
+ if (need_swap) {
+ for (int i = 0; i < mesh->tstrips.size(); i++)
+ swap_int(mesh->tstrips[i]);
+ }
+ fwrite(&(mesh->tstrips[0]), 4*mesh->tstrips.size(), 1, f);
+ if (need_swap) {
+ for (int i = 0; i < mesh->tstrips.size(); i++)
+ swap_int(mesh->tstrips[i]);
+ }
+}
+
+
+// Write range grid to an ASCII file
+static void write_grid_asc(TriMesh *mesh, FILE *f)
+{
+ for (int i = 0; i < mesh->grid.size(); i++) {
+ if (mesh->grid[i] < 0)
+ fprintf(f, "0\n");
+ else
+ fprintf(f, "1 %d\n", mesh->grid[i]);
+ }
+}
+
+
+// Write range grid to a binary file
+static void write_grid_bin(TriMesh *mesh, FILE *f, bool need_swap)
+{
+ unsigned char zero = 0;
+ unsigned char one = 1;
+ for (int i = 0; i < mesh->grid.size(); i++) {
+ if (mesh->grid[i] < 0) {
+ fwrite(&zero, 1, 1, f);
+ } else {
+ fwrite(&one, 1, 1, f);
+ int g = mesh->grid[i];
+ if (need_swap)
+ swap_int(g);
+ fwrite(&g, 4, 1, f);
+ }
+ }
+}
+
+
+// Debugging printout, controllable by a "verbose"ness parameter
+int TriMesh::verbose = 1;
+
+void TriMesh::set_verbose(int verbose_)
+{
+ verbose = verbose_;
+}
+
+int TriMesh::dprintf(const char *format, ...)
+{
+ if (!verbose)
+ return 0;
+
+ va_list ap;
+ va_start(ap, format);
+ int ret = vfprintf(stderr, format, ap);
+ va_end(ap);
+ fflush(stderr);
+ return ret;
+}
+
Index: external/trimesh/libsrc/TriMesh_tstrips.cc
--- external/trimesh/libsrc/TriMesh_tstrips.cc (revision 0)
+++ external/trimesh/libsrc/TriMesh_tstrips.cc (revision 0)
@@ -0,0 +1,245 @@
+/*
+Szymon Rusinkiewicz
+Princeton University
+
+TriMesh_tstrips.cc
+Code for dealing with triangle strips
+*/
+
+#include "TriMesh.h"
+
+
+// Forward declarations
+static void tstrip_build(TriMesh &mesh, int f, vector<signed char>
&face_avail,
+ vector<int> &todo);
+static void collect_tris_in_strips(vector<int> &tstrips);
+
+
+// Convert faces to tstrips
+void TriMesh::need_tstrips()
+{
+ if (faces.empty() || !tstrips.empty())
+ return;
+
+ need_across_edge();
+
+ dprintf("Building triangle strips... ");
+ int nf = faces.size();
+
+ vector<int> todo;
+ vector<signed char> face_avail(nf);
+ for (int i = 0; i < nf; i++) {
+ face_avail[i] = (across_edge[i][0] != -1) +
+ (across_edge[i][1] != -1) +
+ (across_edge[i][2] != -1);
+ if (face_avail[i] == 1)
+ todo.push_back(i);
+ }
+
+ tstrips.reserve(faces.size() * 2);
+
+ int nstrips = 0;
+ int i = 0;
+ while (i < faces.size()) {
+ int next;
+ if (todo.empty()) {
+ next = i++;
+ } else {
+ next = todo.back();
+ todo.pop_back();
+ }
+ if (face_avail[next] < 0)
+ continue;
+ tstrip_build(*this, next, face_avail, todo);
+ nstrips++;
+ }
+
+ convert_strips(TSTRIP_LENGTH);
+
+ dprintf("Done.\n %d strips (Avg. length %.1f)\n",
+ nstrips, (float) faces.size() / nstrips);
+}
+
+
+// Build a triangle strip starting with the given face
+static void tstrip_build(TriMesh &mesh, int f, vector<signed char>
&face_avail,
+ vector<int> &todo)
+{
+ TriMesh::Face &v = mesh.faces[f];
+ if (face_avail[f] == 0) {
+ mesh.tstrips.push_back(v[0]);
+ mesh.tstrips.push_back(v[1]);
+ mesh.tstrips.push_back(v[2]);
+ mesh.tstrips.push_back(-1);
+ face_avail[f] = -1;
+ return;
+ }
+
+ int score[3];
+ for (int i = 0; i < 3; i++) {
+ score[i] = 0;
+ int ae = mesh.across_edge[f][i];
+ if (ae == -1 || face_avail[ae] < 0)
+ continue;
+ score[i]++;
+ int next_edge = mesh.faces[ae].indexof(v[(i+1)%3]);
+ int nae = mesh.across_edge[ae][next_edge];
+ if (nae == -1 || face_avail[nae] < 0)
+ continue;
+ score[i]++;
+ if (face_avail[ae] == 2)
+ score[i]++;
+ }
+
+ int best_score = max(max(score[0], score[1]), score[2]);
+ int best = (score[0] == best_score) ? 0 :
+ (score[1] == best_score) ? 1 : 2;
+
+ int vlast2 = v[ best ];
+ int vlast1 = v[(best+1)%3];
+ int vnext = v[(best+2)%3];
+ int dir = 1;
+ mesh.tstrips.push_back(vlast2);
+ mesh.tstrips.push_back(vlast1);
+
+ while (1) {
+ mesh.tstrips.push_back(vnext);
+ face_avail[f] = -1;
+ for (int j = 0; j < 3; j++) {
+ int ae = mesh.across_edge[f][j];
+ if (ae == -1)
+ continue;
+ if (face_avail[ae] > 0)
+ face_avail[ae]--;
+ if (face_avail[ae] == 1)
+ todo.push_back(ae);
+ }
+
+ f = mesh.across_edge[f][mesh.faces[f].indexof(vlast2)];
+ if (f == -1 || face_avail[f] < 0)
+ break;
+ vlast2 = vlast1;
+ vlast1 = vnext;
+ vnext = mesh.faces[f][(mesh.faces[f].indexof(vlast2)+3+dir)%3];
+ dir = -dir;
+ }
+
+ mesh.tstrips.push_back(-1);
+}
+
+
+// Convert triangle strips to faces
+void TriMesh::unpack_tstrips()
+{
+ if (tstrips.empty() || !faces.empty())
+ return;
+
+ dprintf("Unpacking triangle strips... ");
+ int nfaces = 0;
+ int i = 0;
+ while (i < tstrips.size()) {
+ nfaces += tstrips[i] - 2;
+ i += tstrips[i] + 1;
+ }
+
+ faces.reserve(nfaces);
+
+ int len = 0;
+ bool flip = false;
+ for (i = 0; i < tstrips.size(); i++) {
+ if (len == 0) {
+ len = tstrips[i] - 2;
+ flip = false;
+ i += 2;
+ continue;
+ }
+ if (flip)
+ faces.push_back(Face(tstrips[i-1],
+ tstrips[i-2],
+ tstrips[i]));
+ else
+ faces.push_back(Face(tstrips[i-2],
+ tstrips[i-1],
+ tstrips[i]));
+ flip = !flip;
+ len--;
+ }
+ dprintf("Done.\n %d triangles\n", nfaces);
+}
+
+
+// Convert between "length preceding strip" and "-1 following strip"
+// representations
+void TriMesh::convert_strips(tstrip_rep rep)
+{
+ if (tstrips.empty())
+ return;
+ if (rep == TSTRIP_TERM && tstrips.back() == -1)
+ return;
+ if (rep == TSTRIP_LENGTH && tstrips.back() != -1) {
+ //collect_tris_in_strips(tstrips);
+ return;
+ }
+
+ if (rep == TSTRIP_TERM) {
+ int len = tstrips[0];
+ for (int i = 1; i < tstrips.size(); i++) {
+ if (len) {
+ tstrips[i-1] = tstrips[i];
+ len--;
+ } else {
+ tstrips[i-1] = -1;
+ len = tstrips[i];
+ }
+ }
+ tstrips.back() = -1;
+ } else {
+ int len = 0;
+ for (int i = tstrips.size() - 2; i >= 0; i--) {
+ if (tstrips[i] == -1) {
+ tstrips[i+1] = len;
+ len = 0;
+ } else {
+ tstrips[i+1] = tstrips[i];
+ len++;
+ }
+ }
+ tstrips[0] = len;
+ //collect_tris_in_strips(tstrips);
+ }
+}
+
+
+// Collect all single triangles to be at the end of the list of tstrips
+static void collect_tris_in_strips(vector<int> &tstrips)
+{
+ if (tstrips.empty())
+ return;
+ vector<int> tris;
+
+ int n = 0, offset = 0;
+ bool have_tri = false, bad_strip = false;
+ for (int i = 0; i < tstrips.size(); i++) {
+ if (n == 0) {
+ n = tstrips[i];
+ bad_strip = (n < 3);
+ have_tri = (n == 3);
+ n++;
+ }
+ if (bad_strip) {
+ offset++;
+ } else if (have_tri) {
+ tris.push_back(tstrips[i]);
+ offset++;
+ } else if (offset > 0) {
+ tstrips[i-offset] = tstrips[i];
+ }
+ n--;
+ }
+ if (offset == 0)
+ return;
+ tstrips.erase(tstrips.end() - offset, tstrips.end());
+ tstrips.insert(tstrips.end(), tris.begin(), tris.end());
+
+}
+
Index: external/trimesh/libsrc/TriMesh_normals.cc
--- external/trimesh/libsrc/TriMesh_normals.cc (revision 0)
+++ external/trimesh/libsrc/TriMesh_normals.cc (revision 0)
@@ -0,0 +1,118 @@
+/*
+Szymon Rusinkiewicz
+Princeton University
+
+TriMesh_normals.cc
+Compute per-vertex normals for TriMeshes
+
+For meshes, uses average of per-face normals, weighted according to:
+ Max, N.
+ "Weights for Computing Vertex Normals from Facet Normals,"
+ Journal of Graphics Tools, Vol. 4, No. 2, 1999.
+
+For raw point clouds, fits plane to k nearest neighbors.
+*/
+
+#include <stdio.h>
+#include "TriMesh.h"
+#include "KDtree.h"
+#include "lineqn.h"
+#include <set>
+using std::set;
+
+
+// Helper class for finding k-nearest-neighbors: returns true iff
+// a point is not in the given set of points
+class NotInSet : public KDtree::CompatFunc {
+private:
+ const float *plist;
+ const set<int> &s;
+public:
+ NotInSet(const float *plist_, const set<int> &s_) :
+ plist(plist_), s(s_)
+ {}
+ virtual bool operator () (const float *p) const
+ {
+ int ind = p - plist;
+ return (s.find(ind) == s.end());
+ }
+};
+
+
+// Compute per-vertex normals
+void TriMesh::need_normals()
+{
+ if (normals.size() == vertices.size())
+ return;
+
+ need_faces();
+ int nf = faces.size(), nv = vertices.size();
+
+ dprintf("Computing normals... ");
+ normals.clear();
+ normals.resize(nv);
+
+ if (nf != 0) {
+ // Find normals of a mesh
+#pragma omp parallel for
+ for (int i = 0; i < nf; i++) {
+ const point &p0 = vertices[faces[i][0]];
+ const point &p1 = vertices[faces[i][1]];
+ const point &p2 = vertices[faces[i][2]];
+ vec a = p0-p1, b = p1-p2, c = p2-p0;
+ float l2a = len2(a), l2b = len2(b), l2c = len2(c);
+ vec facenormal = a CROSS b;
+ normals[faces[i][0]] += facenormal * (1.0f / (l2a * l2c));
+ normals[faces[i][1]] += facenormal * (1.0f / (l2b * l2a));
+ normals[faces[i][2]] += facenormal * (1.0f / (l2c * l2b));
+ }
+ } else {
+ // Find normals of a point cloud
+ const int k = 12;
+ const vec ref(0, 0, 1);
+ const float *v0 = &vertices[0][0];
+ KDtree *kd = new KDtree(v0, nv);
+ for (int i = 0; i < nv; i++) {
+ const float *vi = &vertices[i][0];
+ set<int> s;
+ s.insert(vi - v0);
+ for (int j = 0; j < k; j++) {
+ NotInSet ns(v0, s);
+ const float *match =
+ kd->closest_to_pt(vi, 0.0f, &ns);
+ if (!match)
+ break;
+ s.insert(match - v0);
+ }
+ if (s.size() < 4) {
+ printf("Warning: not enough points for vertex %d\n", i);
+ normals[i] = ref;
+ continue;
+ }
+ // Compute covariance
+ float C[3][3] = { {0,0,0}, {0,0,0}, {0,0,0} };
+ for (set<int>::iterator it = s.begin(); it != s.end(); it++) {
+ int ind = *it / 3;
+ if (ind == i)
+ continue;
+ vec d = vertices[ind] - vertices[i];
+ for (int l = 0; l < 3; l++)
+ for (int m = 0; m < 3; m++)
+ C[l][m] += d[l] * d[m];
+ }
+ float e[3];
+ eigdc<float,3>(C, e);
+ normals[i] = vec(C[0][0], C[1][0], C[2][0]);
+ if ((normals[i] DOT ref) < 0.0f)
+ normals[i] = -normals[i];
+ }
+ delete kd;
+ }
+
+#pragma omp parallel for
+ for (int i = 0; i < nv; i++)
+ normalize(normals[i]);
+
+ dprintf("Done.\n");
+}
+
Index: external/trimesh/libsrc/mesh_align.cc
--- external/trimesh/libsrc/mesh_align.cc (revision 0)
+++ external/trimesh/libsrc/mesh_align.cc (revision 0)
@@ -0,0 +1,78 @@
+/*
+Szymon Rusinkiewicz
+Princeton University
+
+mesh_align.cc
+Minimal interface to ICP: register two meshes given an initial guess
+for their alignment.
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "TriMesh.h"
+#include "ICP.h"
+#include <string>
+using std::string;
+
+
+void usage(const char *myname)
+{
+ fprintf(stderr, "Usage: %s [-options] mesh1.ply mesh2.ply\n", myname);
+ fprintf(stderr, "Options:\n");
+ fprintf(stderr, " -a Align using affine xform\n");
+ fprintf(stderr, " -r Align using rigid-body transform (default)\n");
+ fprintf(stderr, " -s Align using rigid + isotropic scale\n");
+ fprintf(stderr, " -v Verbose\n");
+ fprintf(stderr, "Reads transforms in mesh1.xf and mesh2.xf, updates the
latter\n");
+ exit(1);
+}
+
+int main(int argc, char *argv[])
+{
+ int verbose = 1;
+ bool do_scale = false;
+ bool do_affine = false;
+
+ int c;
+ while ((c = getopt(argc, argv, "harsv")) != EOF) {
+ switch (c) {
+ case 'a': do_affine = true; do_scale = false; break;
+ case 'r': do_affine = do_scale = false; break;
+ case 's': do_scale = true; do_affine = false; break;
+ case 'v': verbose = 2; break;
+ default: usage(argv[0]);
+ }
+ }
+ if (argc - optind < 2)
+ usage(argv[0]);
+ const char *filename1 = argv[optind], *filename2 = argv[optind+1];
+
+ TriMesh *mesh1 = TriMesh::read(filename1);
+ if (!mesh1)
+ usage(argv[0]);
+ TriMesh *mesh2 = TriMesh::read(filename2);
+ if (!mesh2)
+ usage(argv[0]);
+
+ xform xf1;
+ string xffilename1 = xfname(filename1);
+ xf1.read(xffilename1);
+
+ xform xf2;
+ string xffilename2 = xfname(filename2);
+ xf2.read(xffilename2);
+
+ float err = ICP(mesh1, mesh2, xf1, xf2, verbose, do_scale, do_affine);
+ if (err >= 0.0f)
+ err = ICP(mesh1, mesh2, xf1, xf2, verbose, do_scale, do_affine);
+
+ if (err < 0.0f) {
+ fprintf(stderr, "ICP failed\n");
+ } else {
+ fprintf(stderr, "ICP succeeded - distance = %f\n", err);
+ xf2.write(xffilename2);
+ }
+}
+
Index: external/trimesh/libsrc/TriMesh_connectivity.cc
--- external/trimesh/libsrc/TriMesh_connectivity.cc (revision 0)
+++ external/trimesh/libsrc/TriMesh_connectivity.cc (revision 0)
@@ -0,0 +1,124 @@
+/*
+Szymon Rusinkiewicz
+Princeton University
+
+TriMesh_connectivity.cc
+Manipulate data structures that describe connectivity between faces and verts.
+*/
+
+
+#include <stdio.h>
+#include "TriMesh.h"
+#include <algorithm>
+using std::find;
+
+
+// Find the direct neighbors of each vertex
+void TriMesh::need_neighbors()
+{
+ if (!neighbors.empty())
+ return;
+ need_faces();
+
+ dprintf("Finding vertex neighbors... ");
+ int nv = vertices.size(), nf = faces.size();
+
+ vector<int> numneighbors(nv);
+ for (int i = 0; i < nf; i++) {
+ numneighbors[faces[i][0]]++;
+ numneighbors[faces[i][1]]++;
+ numneighbors[faces[i][2]]++;
+ }
+
+ neighbors.resize(nv);
+ for (int i = 0; i < nv; i++)
+ neighbors[i].reserve(numneighbors[i]+2); // Slop for boundaries
+
+ for (int i = 0; i < nf; i++) {
+ for (int j = 0; j < 3; j++) {
+ vector<int> &me = neighbors[faces[i][j]];
+ int n1 = faces[i][(j+1)%3];
+ int n2 = faces[i][(j+2)%3];
+ if (find(me.begin(), me.end(), n1) == me.end())
+ me.push_back(n1);
+ if (find(me.begin(), me.end(), n2) == me.end())
+ me.push_back(n2);
+ }
+ }
+
+ dprintf("Done.\n");
+}
+
+
+// Find the faces touching each vertex
+void TriMesh::need_adjacentfaces()
+{
+ if (!adjacentfaces.empty())
+ return;
+ need_faces();
+
+ dprintf("Finding vertex to triangle maps... ");
+ int nv = vertices.size(), nf = faces.size();
+
+ vector<int> numadjacentfaces(nv);
+ for (int i = 0; i < nf; i++) {
+ numadjacentfaces[faces[i][0]]++;
+ numadjacentfaces[faces[i][1]]++;
+ numadjacentfaces[faces[i][2]]++;
+ }
+
+ adjacentfaces.resize(vertices.size());
+ for (int i = 0; i < nv; i++)
+ adjacentfaces[i].reserve(numadjacentfaces[i]);
+
+ for (int i = 0; i < nf; i++) {
+ for (int j = 0; j < 3; j++)
+ adjacentfaces[faces[i][j]].push_back(i);
+ }
+
+ dprintf("Done.\n");
+}
+
+
+// Find the face across each edge from each other face (-1 on boundary)
+// If topology is bad, not necessarily what one would expect...
+void TriMesh::need_across_edge()
+{
+ if (!across_edge.empty())
+ return;
+ need_adjacentfaces();
+
+ dprintf("Finding across-edge maps... ");
+
+ int nf = faces.size();
+ across_edge.resize(nf, Face(-1,-1,-1));
+
+ for (int i = 0; i < nf; i++) {
+ for (int j = 0; j < 3; j++) {
+ if (across_edge[i][j] != -1)
+ continue;
+ int v1 = faces[i][(j+1)%3];
+ int v2 = faces[i][(j+2)%3];
+ const vector<int> &a1 = adjacentfaces[v1];
+ const vector<int> &a2 = adjacentfaces[v2];
+ for (int k1 = 0; k1 < a1.size(); k1++) {
+ int other = a1[k1];
+ if (other == i)
+ continue;
+ vector<int>::const_iterator it =
+ find(a2.begin(), a2.end(), other);
+ if (it == a2.end())
+ continue;
+ int ind = (faces[other].indexof(v1)+1)%3;
+ if (faces[other][(ind+1)%3] != v2)
+ continue;
+ across_edge[i][j] = other;
+ across_edge[other][ind] = i;
+ break;
+ }
+ }
+ }
+
+ dprintf("Done.\n");
+}
+
Index: external/trimesh/libsrc/faceflip.cc
--- external/trimesh/libsrc/faceflip.cc (revision 0)
+++ external/trimesh/libsrc/faceflip.cc (revision 0)
@@ -0,0 +1,30 @@
+/*
+Szymon Rusinkiewicz
+Princeton University
+
+faceflip.cc
+Flip the order of vertices in each face. Turns the mesh inside out.
+*/
+
+#include <stdio.h>
+#include "TriMesh.h"
+#include "TriMesh_algo.h"
+
+
+void faceflip(TriMesh *mesh)
+{
+ bool had_tstrips = !mesh->tstrips.empty();
+ mesh->need_faces();
+ mesh->tstrips.clear();
+
+ TriMesh::dprintf("Flipping faces... ");
+ int nf = mesh->faces.size();
+#pragma omp parallel for
+ for (int i = 0; i < nf; i++)
+ swap(mesh->faces[i][0], mesh->faces[i][2]);
+ TriMesh::dprintf("Done.\n");
+
+ if (had_tstrips)
+ mesh->need_tstrips();
+}
+
Index: external/trimesh/libsrc/GLCamera.cc
--- external/trimesh/libsrc/GLCamera.cc (revision 0)
+++ external/trimesh/libsrc/GLCamera.cc (revision 0)
@@ -0,0 +1,378 @@
+/*
+Szymon Rusinkiewicz
+Princeton University
+
+GLCamera.cc
+Manages OpenGL camera and trackball/arcball interaction
+*/
+
+#ifdef __APPLE__
+ #include <OpenGL/gl.h>
+ #include <OpenGL/glu.h>
+#else
+ #ifdef _WIN32
+ #include <windows.h>
+ #undef min
+ #undef max
+ #endif
+ #include <GL/gl.h>
+ #include <GL/glu.h>
+#endif
+
+#include "GLCamera.h"
+
+
+#ifndef M_PI
+# define M_PI 3.14159265358979323846
+#endif
+
+#define DOF 10.0f
+#define MAXDOF 10000.0f
+#define SPIN_TIME 0.1f
+#define SPIN_SPEED 0.05f
+#define TRACKBALL_R 0.8f
+#define DEPTH_FUDGE (1.0f + 0.2f * field_of_view)
+#define MOVEZ_MULT 5.0f
+#define WHEEL_MOVE 0.2f
+#define MAX_LIGHT M_PI
+
+
+// Read back the framebuffer at the given pixel, and determine
+// the 3D point there. If there's nothing there, reads back a
+// number of pixels farther and farther away.
+bool GLCamera::read_depth(int x, int y, point &p) const
+{
+ GLdouble M[16], P[16]; GLint V[4];
+ glGetDoublev(GL_MODELVIEW_MATRIX, M);
+ glGetDoublev(GL_PROJECTION_MATRIX, P);
+ glGetIntegerv(GL_VIEWPORT, V);
+
+ static const float dx[] =
+ { 0, 1,-1,-1, 1, 3,-3, 0, 0, 6,-6,-6, 6, 25,-25, 0, 0 };
+ static const float dy[] =
+ { 0, 1, 1,-1,-1, 0, 0, 3,-3, 6, 6,-6,-6, 0, 0, 25,-25 };
+ const float scale = 0.01f;
+ const int displacements = sizeof(dx) / sizeof(float);
+
+ int xmin = V[0], xmax = V[0]+V[2]-1, ymin = V[1], ymax = V[1]+V[3]-1;
+
+ for (int i = 0 ; i < displacements; i++) {
+ int xx = min(max(x + int(dx[i]*scale*V[2]), xmin), xmax);
+ int yy = min(max(y + int(dy[i]*scale*V[3]), ymin), ymax);
+ float d;
+ glReadPixels(xx, yy, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &d);
+
+ static float maxd = 0.0f;
+ if (!maxd) {
+ glScissor(xx, yy, 1, 1);
+ glEnable(GL_SCISSOR_TEST);
+ glClearDepth(1);
+ glClear(GL_DEPTH_BUFFER_BIT);
+ glReadPixels(xx, yy, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &maxd);
+ if (maxd) {
+ glClearDepth(d / maxd);
+ glClear(GL_DEPTH_BUFFER_BIT);
+ }
+ glDisable(GL_SCISSOR_TEST);
+ glClearDepth(1);
+ if (!maxd)
+ return false;
+ }
+
+ d /= maxd;
+ if (d > 0.0001f && d < 0.9999f) {
+ GLdouble X, Y, Z;
+ gluUnProject(xx, yy, d, M, P, V, &X, &Y, &Z);
+ p = point((float)X, (float)Y, (float)Z);
+ return true;
+ }
+ }
+ return false;
+}
+
+
+// Mouse helper - decide whether to start auto-spin
+void GLCamera::startspin()
+{
+ float dt = now() - last_time;
+ if (dt < SPIN_TIME && fabs(spinspeed) > SPIN_SPEED)
+ dospin = true;
+}
+
+
+// Mouse rotation helper - compute trackball position from mouse pos
+vec GLCamera::mouse2tb(float x, float y)
+{
+ float r2 = x*x + y*y;
+ float t = 0.5f * sqr(TRACKBALL_R);
+
+ vec pos(x, y, 0);
+ if (r2 < t)
+ pos[2] = sqrt(2*t - r2);
+ else
+ pos[2] = t / sqrt(r2);
+ return pos;
+}
+
+// Mouse helper - rotate
+void GLCamera::rotate(int mousex, int mousey, xform &xf)
+{
+ float ox = (lastmousex - tb_screen_x) / tb_screen_size;
+ float oy = (lastmousey - tb_screen_y) / tb_screen_size;
+ float nx = ( mousex - tb_screen_x) / tb_screen_size;
+ float ny = ( mousey - tb_screen_y) / tb_screen_size;
+
+ vec pos1 = mouse2tb(ox, oy);
+ vec pos2 = mouse2tb(nx, ny);
+ spinaxis = pos1 CROSS pos2;
+ float spinamount = sqrt(sqr(nx-ox)+sqr(ny-oy));
+
+ xf = xform::trans(spincenter) * xform::rot(spinamount, spinaxis) *
+ xform::trans(-spincenter) * xf;
+
+ float dt = now() - last_time;
+ if (dt > SPIN_TIME)
+ spinspeed = spinamount / SPIN_TIME;
+ else
+ spinspeed = (spinamount / SPIN_TIME) +
+ (1.0f-dt/SPIN_TIME)*spinspeed;
+}
+
+
+// Mouse helper - translate
+void GLCamera::movexy(int mousex, int mousey, xform &xf)
+{
+ float dx = pixscale * click_depth * (mousex - lastmousex);
+ float dy = pixscale * click_depth * (mousey - lastmousey);
+ xf = xform::trans(dx, dy, 0) * xf;
+}
+
+
+// Mouse helper - translate in Z
+// In order to be extra-clever, though, this actually translates along the
+// direction of the center of the trackball
+void GLCamera::movez(int mousex, int mousey, xform &xf)
+{
+ float delta = MOVEZ_MULT / field_of_view * pixscale *
+ ((mousex-lastmousex) - (mousey-lastmousey));
+ float dz = click_depth * (exp(-delta) - 1.0f);
+ //xf = xform::trans(0, 0, -dz) * xf;
+ xf = xform::trans(dz * spincenter / len(spincenter)) * xf;
+
+ surface_depth += dz;
+ if (surface_depth < 0)
+ surface_depth = 0;
+ click_depth += dz;
+ if (click_depth < 0)
+ click_depth = 0;
+}
+
+
+// Mouse helper - wheel motion
+void GLCamera::wheel(Mouse::button updown, xform &xf)
+{
+ float dz = click_depth * WHEEL_MOVE;
+ if (updown == Mouse::WHEELUP)
+ dz = -dz;
+ xf = xform::trans(0, 0, dz) * xf;
+
+ surface_depth -= dz;
+ if (surface_depth < 0)
+ surface_depth = 0;
+ click_depth -= dz;
+ if (click_depth < 0)
+ click_depth = 0;
+}
+
+
+// Mouse helper - change lighting direction
+void GLCamera::relight(int mousex, int mousey)
+{
+ GLint V[4];
+ glGetIntegerv(GL_VIEWPORT, V);
+
+ float x = 2.0f * float(mousex - V[0]) / float(V[2]) - 1.0f;
+ float y = 2.0f * float(mousey - V[1]) / float(V[3]) - 1.0f;
+
+ float theta = (float)MAX_LIGHT * min(sqrt(x*x+y*y), 1.0f);
+ float phi = atan2(y, x);
+
+ lightdir[0] = sin(theta)*cos(phi);
+ lightdir[1] = sin(theta)*sin(phi);
+ lightdir[2] = cos(theta);
+}
+
+
+// Handle a mouse click - sets up rotation center, pixscale, and click_depth
+void GLCamera::mouse_click(int mousex, int mousey,
+ const point &scene_center, float scene_size)
+{
+ GLdouble M[16], P[16]; GLint V[4];
+#if 0
+ glGetDoublev(GL_MODELVIEW_MATRIX, M);
+#else
+ M[0] = M[5] = M[10] = M[15] = 1.0;
+ M[1] = M[2] = M[3] = M[4] =
+ M[6] = M[7] = M[8] = M[9] =
+ M[11] = M[12] = M[13] = M[14] = 0;
+#endif
+ glGetDoublev(GL_PROJECTION_MATRIX, P);
+ glGetIntegerv(GL_VIEWPORT, V);
+
+ // Assume glFrustum only...
+ pixscale = 2.0f / float(max(P[0]*V[2], P[5]*V[3]));
+
+
+ point surface_point;
+ if (read_depth(mousex, mousey, surface_point))
+ click_depth = -surface_point[2];
+ else
+ click_depth = surface_depth;
+
+
+ GLdouble cx, cy, cz;
+ gluProject(scene_center[0], scene_center[1], scene_center[2],
+ M, P, V,
+ &cx, &cy, &cz);
+
+ double csize = max(V[2], V[3]);
+ int xmin = V[0], xmax = V[0]+V[2], ymin = V[1], ymax = V[1]+V[3];
+ if (scene_center[2] < 0 && len(scene_center) > scene_size) {
+ csize = -scene_size / scene_center[2] / pixscale;
+ xmin = min(max((GLint) (cx - csize), V[0]), V[0]+V[2]);
+ xmax = min(max((GLint) (cx + csize), V[0]), V[0]+V[2]);
+ ymin = min(max((GLint) (cy - csize), V[1]), V[1]+V[3]);
+ ymax = min(max((GLint) (cy + csize), V[1]), V[1]+V[3]);
+ }
+
+ GLdouble s[3];
+ gluUnProject((xmin+xmax)/2, (ymin+ymax)/2, 1,
+ M, P, V,
+ &s[0], &s[1], &s[2]);
+ spincenter = vec(s);
+ normalize(spincenter);
+ if (read_depth((xmin+xmax)/2, (ymin+ymax)/2, surface_point))
+ spincenter *= DEPTH_FUDGE * surface_point[2] / spincenter[2];
+ else
+ spincenter *= -DEPTH_FUDGE * click_depth / spincenter[2];
+
+ float f = (float)csize / max(V[2], V[3]);
+ f = min(max(2.0f * f - 1.0f, 0.0f), 1.0f);
+ spincenter = f * spincenter + (1.0f - f) * scene_center;
+
+ gluProject(spincenter[0], spincenter[1], spincenter[2],
+ M, P, V,
+ &cx, &cy, &cz);
+ tb_screen_x = (float)cx;
+ tb_screen_y = (float)cy;
+ tb_screen_size = (float)csize;
+ tb_screen_size = min(tb_screen_size, 0.7f * min(V[2], V[3]));
+ tb_screen_size = max(tb_screen_size, 0.3f * min(V[2], V[3]));
+}
+
+
+// Handle a mouse event
+void GLCamera::mouse(int mousex, int mousey, Mouse::button b,
+ const point &scene_center, float scene_size,
+ xform &xf)
+{
+ if (b == Mouse::NONE && lastb == Mouse::NONE)
+ return;
+
+ GLint V[4];
+ glGetIntegerv(GL_VIEWPORT, V);
+ mousey = V[1] + V[3] - 1 - mousey;
+
+ dospin = false;
+ if ((b != lastb) && (b != Mouse::NONE))
+ mouse_click(mousex, mousey, scene_center, scene_size);
+
+ // Handle rotation
+ if ((b == Mouse::ROTATE) && (lastb == Mouse::NONE))
+ spinspeed = 0;
+ if ((b == Mouse::ROTATE) && (lastb == Mouse::ROTATE))
+ rotate(mousex, mousey, xf);
+ if ((b == Mouse::NONE) && (lastb == Mouse::ROTATE))
+ startspin();
+
+ // Handle translation
+ if ((b == Mouse::MOVEXY) && (lastb == Mouse::MOVEXY))
+ movexy(mousex, mousey, xf);
+ if ((b == Mouse::MOVEZ) && (lastb == Mouse::MOVEZ))
+ movez(mousex, mousey, xf);
+ if (b == Mouse::WHEELUP || b == Mouse::WHEELDOWN)
+ wheel(b, xf);
+
+ // Handle lighting
+ if (b == Mouse::LIGHT)
+ relight(mousex, mousey);
+
+
+ lastmousex = mousex; lastmousey = mousey; lastb = b;
+ last_time = now();
+}
+
+
+// Idle loop - handles auto-rotate. Returns true iff auto-rotating
+bool GLCamera::autospin(xform &xf)
+{
+ if (!dospin)
+ return false;
+
+ float dt = now() - last_time;
+ float spinamount = spinspeed * dt;
+
+ xf = xform::trans(spincenter) * xform::rot(spinamount, spinaxis) *
+ xform::trans(-spincenter) * xf;
+
+ last_time = now();
+ return true;
+}
+
+
+// Set up the OpenGL camera for rendering
+void GLCamera::setupGL(const point &scene_center, float scene_size) const
+{
+ GLint V[4];
+ glGetIntegerv(GL_VIEWPORT, V);
+ int width = V[2], height = V[3];
+
+ point surface_point;
+ if (read_depth(width/2, height/2, surface_point))
+ surface_depth = -surface_point[2];
+
+ float fardist = max(-(scene_center[2] - scene_size),
+ scene_size / DOF);
+ float neardist = max(-(scene_center[2] + scene_size),
+ scene_size / MAXDOF);
+ surface_depth = min(surface_depth, fardist);
+ surface_depth = max(surface_depth, neardist);
+ surface_depth = max(surface_depth, fardist / MAXDOF);
+ neardist = max(neardist, surface_depth / DOF);
+
+ float diag = sqrt(float(sqr(width) + sqr(height)));
+ float top = (float) height/diag * 0.5f*field_of_view * neardist;
+ float bottom = -top;
+ float right = (float) width/diag * 0.5f*field_of_view * neardist;
+ float left = -right;
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glFrustum(left, right, bottom, top, neardist, fardist);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ GLfloat light0_position[] = { lightdir[0], lightdir[1], lightdir[2], 0 };
+ GLfloat light1_position[] = { -lightdir[0], -lightdir[1], -lightdir[2], 0 };
+ GLfloat light2_position[] = { lightdir[2], 0, -lightdir[0], 0 };
+ GLfloat light3_position[] = { -lightdir[2], 0, lightdir[0], 0 };
+ GLfloat light4_position[] = { 0, lightdir[2], -lightdir[1], 0 };
+ GLfloat light5_position[] = { 0, -lightdir[2], lightdir[1], 0 };
+ glLightfv(GL_LIGHT0, GL_POSITION, light0_position);
+ glLightfv(GL_LIGHT1, GL_POSITION, light1_position);
+ glLightfv(GL_LIGHT2, GL_POSITION, light2_position);
+ glLightfv(GL_LIGHT3, GL_POSITION, light3_position);
+ glLightfv(GL_LIGHT4, GL_POSITION, light4_position);
+ glLightfv(GL_LIGHT5, GL_POSITION, light5_position);
+}
+
Index: external/trimesh/libsrc/ICP.cc
--- external/trimesh/libsrc/ICP.cc (revision 0)
+++ external/trimesh/libsrc/ICP.cc (revision 0)
@@ -0,0 +1,858 @@
+/*
+Szymon Rusinkiewicz
+Princeton University
+
+ICP.cc
+Routines for doing ICP.
+*/
+
+#include <cmath>
+#include <algorithm>
+#include <stdio.h>
+#include "ICP.h"
+#include "KDtree.h"
+#include "timestamp.h"
+#include "lineqn.h"
+using namespace std;
+
+
+#define MAX_ITERS 100
+#define MIN_PAIRS 25
+#define DESIRED_PAIRS 500
+#define DESIRED_PAIRS_EARLY 50
+#define DESIRED_PAIRS_FINAL 2000
+#define COMPAT_THRESH 0.7f
+#define TERM_THRESH 5
+#define TERM_HIST 7
+#define EIG_THRESH 0.01f
+
+
+// One or both of the following can be #defined
+#define USE_GRID_FOR_OVERLAPS
+#undef USE_KD_FOR_OVERLAPS
+
+
+// Quick 'n dirty portable random number generator
+static inline float tinyrnd()
+{
+ static unsigned trand = 0;
+ trand = 1664525u * trand + 1013904223u;
+ return (float) trand / 4294967296.0f;
+}
+
+
+// A pair of points, with an associated normal
+struct PtPair {
+ point p1, p2;
+ vec norm;
+ PtPair(const point &p1_, const point &p2_, const vec &norm_) :
+ p1(p1_), p2(p2_), norm(norm_)
+ {}
+};
+
+
+// A class for evaluating compatibility of normals during KDtree searches
+class NormCompat : public KDtree::CompatFunc {
+private:
+ const vec n;
+ TriMesh *m;
+ bool pointcloud;
+
+public:
+ NormCompat(const vec &n_, TriMesh *m_, bool &p_):
+ n(n_), m(m_), pointcloud(p_)
+ {}
+ virtual bool operator () (const float *p) const
+ {
+ int idx = (const point *)p - (const point *)&(m->vertices[0]);
+ if (pointcloud)
+ return fabs(n DOT m->normals[idx]) > COMPAT_THRESH;
+ else if (m->is_bdy(idx))
+ return true;
+ else
+ return (n DOT m->normals[idx]) > COMPAT_THRESH;
+ }
+};
+
+
+// Find the median squared distance between points
+static float median_dist2(const vector<PtPair> &pairs)
+{
+ size_t n = pairs.size();
+ if (!n)
+ return 0.0f;
+
+ vector<float> distances2;
+ distances2.reserve(n);
+ for (size_t i = 0; i < n; i++)
+ distances2.push_back(dist2(pairs[i].p1, pairs[i].p2));
+
+ size_t pos = n / 2;
+ nth_element(distances2.begin(),
+ distances2.begin() + pos,
+ distances2.end());
+ return distances2[pos];
+}
+
+
+// A spatial grid datastructure for fast overlap computation
+class Grid {
+public:
+ enum { GRID_SHIFT = 4, GRID_MAX = (1 << GRID_SHIFT) - 1 };
+ float xmin, xmax, ymin, ymax, zmin, zmax, scale;
+ char g[1 << 3*GRID_SHIFT];
+ bool valid(const point &p)
+ {
+ return p[0] > xmin && p[1] > ymin && p[2] > zmin &&
+ p[0] < xmax && p[1] < ymax && p[2] < zmax;
+ }
+ int ind(const point &p)
+ {
+ int x = min(int(scale * (p[0] - xmin)), int(GRID_MAX));
+ int y = min(int(scale * (p[1] - ymin)), int(GRID_MAX));
+ int z = min(int(scale * (p[2] - zmin)), int(GRID_MAX));
+ return (x << (2*GRID_SHIFT)) + (y << GRID_SHIFT) + z;
+ }
+ bool overlaps(const point &p) { return valid(p) && g[ind(p)]; }
+ Grid(const vector<point> &pts);
+};
+
+
+// Compute a Grid from a list of points
+Grid::Grid(const vector<point> &pts)
+{
+ memset(g, 0, sizeof(g));
+ xmin = xmax = pts[0][0];
+ ymin = ymax = pts[0][1];
+ zmin = zmax = pts[0][2];
+ for (size_t i = 1; i < pts.size(); i++) {
+ if (pts[i][0] < xmin) xmin = pts[i][0];
+ if (pts[i][0] > xmax) xmax = pts[i][0];
+ if (pts[i][1] < ymin) ymin = pts[i][1];
+ if (pts[i][1] > ymax) ymax = pts[i][1];
+ if (pts[i][2] < zmin) zmin = pts[i][2];
+ if (pts[i][2] > zmax) zmax = pts[i][2];
+ }
+ scale = 1.0f / max(max(xmax-xmin, ymax-ymin), zmax-zmin);
+ scale *= float(1 << GRID_SHIFT);
+ for (size_t i = 0; i < pts.size(); i++)
+ g[ind(pts[i])] = 1;
+}
+
+
+// Determine which points on s1 and s2 overlap the other, filling in o1 and o2
+// Also fills in maxdist, if it is <= 0 on input
+void compute_overlaps(TriMesh *s1, TriMesh *s2,
+ const xform &xf1, const xform &xf2,
+ const KDtree *kd1, const KDtree *kd2,
+ vector<float> &o1, vector<float> &o2,
+ float &maxdist, int verbose)
+{
+ s1->need_normals(); s2->need_normals();
+ size_t nv1 = s1->vertices.size(), nv2 = s2->vertices.size();
+
+ timestamp t = now();
+ Grid g1(s1->vertices);
+ Grid g2(s2->vertices);
+ xform xf12 = inv(xf2) * xf1;
+ xform xf21 = inv(xf1) * xf2;
+ if (maxdist <= 0.0f)
+ maxdist = min(1.0f / g1.scale, 1.0f / g2.scale);
+ float maxdist2 = sqr(maxdist);
+
+ bool pointcloud1 = (s1->faces.empty() && s1->tstrips.empty());
+ bool pointcloud2 = (s2->faces.empty() && s2->tstrips.empty());
+
+ o1.resize(nv1);
+ for (size_t i = 0; i < nv1; i++) {
+ o1[i] = 0;
+ point p = xf12 * s1->vertices[i];
+#ifdef USE_GRID_FOR_OVERLAPS
+ if (!g2.overlaps(p))
+ continue;
+#endif
+#ifdef USE_KD_FOR_OVERLAPS
+ const float *match = kd2->closest_to_pt(p, maxdist2);
+ if (!match)
+ continue;
+ if (!pointcloud2 &&
+ s2->is_bdy((match - (const float *) &s2->vertices[0][0]) / 3))
+ continue;
+#endif
+ o1[i] = 1;
+ }
+
+ o2.resize(nv2);
+ for (size_t i = 0; i < nv2; i++) {
+ o2[i] = 0;
+ point p = xf21 * s2->vertices[i];
+#ifdef USE_GRID_FOR_OVERLAPS
+ if (!g1.overlaps(p))
+ continue;
+#endif
+#ifdef USE_KD_FOR_OVERLAPS
+ const float *match = kd1->closest_to_pt(p, maxdist2);
+ if (!match)
+ continue;
+ if (!pointcloud1 &&
+ s1->is_bdy((match - (const float *) &s1->vertices[0][0]) / 3))
+ continue;
+#endif
+ o2[i] = 1;
+ }
+ if (verbose > 1) {
+ fprintf(stderr, "Computed overlaps in %.2f msec.\n",
+ (now() - t) * 1000.0f);
+ }
+}
+
+
+// Select a number of points and find correspondences
+static void select_and_match(TriMesh *s1, TriMesh *s2,
+ const xform &xf1, const xform &xf2,
+ const KDtree *kd2, const vector<float> &sampcdf1,
+ float incr, float maxdist, int verbose,
+ vector<PtPair> &pairs, bool flip)
+{
+ xform xf1r = norm_xf(xf1);
+ xform xf2r = norm_xf(xf2);
+ xform xf12 = inv(xf2) * xf1;
+ xform xf12r = norm_xf(xf12);
+ float maxdist2 = sqr(maxdist);
+
+ size_t i = 0;
+ float cval = 0.0f;
+ while (1) {
+ cval += incr * tinyrnd();
+ if (cval >= 1.0f)
+ break;
+ while (sampcdf1[i] <= cval)
+ i++;
+ cval = sampcdf1[i];
+
+ point p = xf12 * s1->vertices[i];
+ vec n = xf12r * s1->normals[i];
+
+ // Do the matching
+ bool pointcloud2 = (s2->faces.empty() && s2->tstrips.empty());
+ NormCompat nc(n, s2, pointcloud2);
+
+ const float *match = kd2->closest_to_pt(p, maxdist2, &nc);
+ if (!match)
+ continue;
+ int imatch = (match - (const float *) &(s2->vertices[0][0])) / 3;
+ if (!pointcloud2 && s2->is_bdy(imatch))
+ continue;
+
+ // Project both points into world coords and save
+ if (flip) {
+ pairs.push_back(PtPair(xf2 * s2->vertices[imatch],
+ xf1 * s1->vertices[i],
+ xf2r * s2->normals[imatch]));
+ } else {
+ pairs.push_back(PtPair(xf1 * s1->vertices[i],
+ xf2 * s2->vertices[imatch],
+ xf1r * s1->normals[i]));
+ }
+ }
+}
+
+
+// Compute ICP alignment matrix, including eigenvector decomposition
+static void compute_ICPmatrix(const vector<PtPair> &pairs,
+ float evec[6][6], float eval[6], float b[6],
+ point ¢roid, float &scale, float &err)
+{
+ size_t n = pairs.size();
+
+ centroid = point(0,0,0);
+ for (size_t i = 0; i < n; i++)
+ centroid += pairs[i].p2;
+ centroid /= float(n);
+
+ scale = 0.0f;
+ for (size_t i = 0; i < n; i++)
+ scale += dist2(pairs[i].p2, centroid);
+ scale /= float(n);
+ scale = 1.0f / sqrt(scale);
+
+ memset(&evec[0][0], 0, 6*6*sizeof(float));
+ memset(&b[0], 0, 6*sizeof(float));
+
+ err = 0.0f;
+ for (size_t i = 0; i < n; i++) {
+ const point &p1 = pairs[i].p1;
+ const point &p2 = pairs[i].p2;
+ const vec &n = pairs[i].norm;
+
+ float d = (p1 - p2) DOT n;
+ d *= scale;
+ vec p2c = p2 - centroid;
+ p2c *= scale;
+ vec c = p2c CROSS n;
+
+ err += d * d;
+ float x[6] = { c[0], c[1], c[2], n[0], n[1], n[2] };
+ for (int j = 0; j < 6; j++) {
+ b[j] += d * x[j];
+ for (int k = 0; k < 6; k++)
+ evec[j][k] += x[j] * x[k];
+ }
+ }
+
+ err /= float(n);
+ err = sqrt(err) / scale;
+ eigdc<float,6>(evec, eval);
+}
+
+
+// Compute ICP alignment, given matrix computed by compute_ICPmatrix
+static void compute_alignxf(float evec[6][6], float eval[6], float b[6],
+ point ¢roid, float scale, xform &alignxf)
+{
+ float einv[6];
+ for (int i = 0; i < 6; i++) {
+ if (eval[i] < EIG_THRESH * eval[5])
+ einv[i] = 0.0f;
+ else
+ einv[i] = 1.0f / eval[i];
+ }
+ float x[6];
+ eigmult<float,6>(evec, einv, b, x);
+
+ // Interpret results
+ float sx = min(max(x[0], -1.0f), 1.0f);
+ float sy = min(max(x[1], -1.0f), 1.0f);
+ float sz = min(max(x[2], -1.0f), 1.0f);
+ float cx = sqrt(1.0f - sx*sx);
+ float cy = sqrt(1.0f - sy*sy);
+ float cz = sqrt(1.0f - sz*sz);
+
+ alignxf[0] = cy*cz;
+ alignxf[1] = sx*sy*cz + cx*sz;
+ alignxf[2] = -cx*sy*cz + sx*sz;
+ alignxf[3] = 0;
+ alignxf[4] = -cy*sz;
+ alignxf[5] = -sx*sy*sz + cx*cz;
+ alignxf[6] = cx*sy*sz + sx*cz;
+ alignxf[7] = 0;
+ alignxf[8] = sy;
+ alignxf[9] = -sx*cy;
+ alignxf[10] = cx*cy;
+ alignxf[11] = 0;
+ alignxf[12] = x[3] / scale + centroid[0] - alignxf[0]*centroid[0] -
+ alignxf[4]*centroid[1] - alignxf[8]*centroid[2];
+ alignxf[13] = x[4] / scale + centroid[1] - alignxf[1]*centroid[0] -
+ alignxf[5]*centroid[1] - alignxf[9]*centroid[2];
+ alignxf[14] = x[5] / scale + centroid[2] - alignxf[2]*centroid[0] -
+ alignxf[6]*centroid[1] - alignxf[10]*centroid[2];
+ alignxf[15] = 1;
+}
+
+
+// Compute isotropic or anisotropic scale
+void compute_scale(const vector<PtPair> &pairs, xform &alignxf,
+ int verbose, bool do_affine)
+{
+ int n = pairs.size();
+
+ // Compute COM
+ point centroid;
+ for (int i = 0; i < n; i++)
+ centroid += pairs[i].p1 + pairs[i].p2;
+ centroid /= 2.0f * n;
+ xform txf = xform::trans(centroid);
+
+ // Compute covariance matrices
+ double cov1[3][3] = { {0,0,0}, {0,0,0}, {0,0,0} };
+ double cov2[3][3] = { {0,0,0}, {0,0,0}, {0,0,0} };
+ for (int i = 0; i < n; i++) {
+ vec p = pairs[i].p1 - centroid;
+ for (int j = 0; j < 3; j++)
+ for (int k = 0; k < 3; k++)
+ cov1[j][k] += p[j]*p[k];
+ p = pairs[i].p2 - centroid;
+ for (int j = 0; j < 3; j++)
+ for (int k = 0; k < 3; k++)
+ cov2[j][k] += p[j]*p[k];
+ }
+
+ // Compute eigenstuff of cov
+ double eval1[3], eval2[3];
+ eigdc<double,3>(cov1, eval1);
+ eigdc<double,3>(cov2, eval2);
+
+ if (!do_affine) {
+ // Just uniform scale
+ float s1 = (float)sqrt(eval1[0] + eval1[1] + eval1[2]);
+ float s2 = (float)sqrt(eval2[0] + eval2[1] + eval2[2]);
+ alignxf = txf * xform::scale(s1, s1, s1) *
+ inv(xform::scale(s2, s2, s2)) * inv(txf);
+ return;
+ }
+
+ // Compute sqrt of covariance
+ double csqrt1[3][3] = { {1,0,0}, {0,1,0}, {0,0,1} };
+ double csqrt2[3][3] = { {1,0,0}, {0,1,0}, {0,0,1} };
+ for (int i = 0; i < 3; i++)
+ eval1[i] = sqrt(eval1[i] / n);
+ for (int i = 0; i < 3; i++)
+ eigmult<double,3>(cov1, eval1, csqrt1[i], csqrt1[i]);
+ for (int i = 0; i < 3; i++)
+ eval2[i] = sqrt(eval2[i] / n);
+ for (int i = 0; i < 3; i++)
+ eigmult<double,3>(cov2, eval2, csqrt2[i], csqrt2[i]);
+
+ if (verbose > 1) {
+ fprintf(stderr, "sqrt covariance 1 =");
+ for (int j = 0; j < 3; j++) {
+ fprintf(stderr, "\n\t");
+ for (int k = 0; k < 3; k++)
+ fprintf(stderr, "%10.3f ", csqrt1[j][k]);
+ }
+ fprintf(stderr, "\nsqrt covariance 2 =");
+ for (int j = 0; j < 3; j++) {
+ fprintf(stderr, "\n\t");
+ for (int k = 0; k < 3; k++)
+ fprintf(stderr, "%10.3f ", csqrt2[j][k]);
+ }
+ fprintf(stderr, "\n");
+ }
+
+
+ xform cxf1 = xform(csqrt1[0][0], csqrt1[1][0], csqrt1[2][0], 0,
+ csqrt1[0][1], csqrt1[1][1], csqrt1[2][1], 0,
+ csqrt1[0][2], csqrt1[1][2], csqrt1[2][2], 0,
+ 0, 0, 0, 1);
+ xform cxf2 = xform(csqrt2[0][0], csqrt2[1][0], csqrt2[2][0], 0,
+ csqrt2[0][1], csqrt2[1][1], csqrt2[2][1], 0,
+ csqrt2[0][2], csqrt2[1][2], csqrt2[2][2], 0,
+ 0, 0, 0, 1);
+
+ alignxf = txf * cxf1 * inv(cxf2) * inv(txf);
+}
+
+
+// Do one iteration of ICP
+static float ICP_iter(TriMesh *s1, TriMesh *s2, const xform &xf1, xform &xf2,
+ const KDtree *kd1, const KDtree *kd2,
+ const vector<float> &weights1, const vector<float>
&weights2,
+ float &maxdist, int verbose,
+ vector<float> &sampcdf1, vector<float> &sampcdf2,
+ float &incr, bool update_cdfs,
+ bool do_scale, bool do_affine)
+{
+ // Compute pairs
+ timestamp t1 = now();
+ if (verbose > 1)
+ fprintf(stderr, "maxdist = %f\n", maxdist);
+ vector<PtPair> pairs;
+ select_and_match(s1, s2, xf1, xf2, kd2, sampcdf1, incr,
+ maxdist, verbose, pairs, false);
+ select_and_match(s2, s1, xf2, xf1, kd1, sampcdf2, incr,
+ maxdist, verbose, pairs, true);
+
+ timestamp t2 = now();
+ size_t np = pairs.size();
+ if (verbose > 1) {
+ fprintf(stderr, "Generated %lu pairs in %.2f msec.\n",
+ (unsigned long) np, (t2-t1) * 1000.0f);
+ }
+
+ // Reject pairs with distance > 2.5 sigma
+ float thresh = 13.73818f * median_dist2(pairs);
+ if (verbose > 1)
+ fprintf(stderr, "Rejecting pairs > %f\n", sqrt(thresh));
+ size_t next = 0;
+ for (size_t i = 0; i < np; i++) {
+ if (dist2(pairs[i].p1, pairs[i].p2) <= thresh)
+ pairs[next++] = pairs[i];
+ }
+ pairs.erase(pairs.begin() + next, pairs.end());
+
+ timestamp t3 = now();
+ if (verbose > 1) {
+ fprintf(stderr, "Rejected %lu pairs in %.2f msec.\n",
+ (unsigned long) (np - pairs.size()), (t3-t2) * 1000.0f);
+ }
+ if (pairs.size() < MIN_PAIRS) {
+ if (verbose)
+ fprintf(stderr, "Too few point pairs.\n");
+ return -1.0f;
+ }
+
+ // Update incr and maxdist based on what happened here
+ incr *= (float) pairs.size() / DESIRED_PAIRS;
+ maxdist = max(2.0f * sqrt(thresh), 0.7f * maxdist);
+
+ // Do the minimization
+ float evec[6][6], eval[6], b[6], scale, err;
+ point centroid;
+ xform alignxf;
+ compute_ICPmatrix(pairs, evec, eval, b, centroid, scale, err);
+ if (verbose > 1) {
+ fprintf(stderr, "RMS point-to-plane error = %f\n", err);
+ for (int i = 0; i < 5; i++)
+ if (eval[i] < EIG_THRESH * eval[5])
+ fprintf(stderr, "Small eigenvalue %f (largest is %f)\n", eval[i],
eval[5]);
+ }
+ compute_alignxf(evec, eval, b, centroid, scale, alignxf);
+ xf2 = alignxf * xf2;
+
+ if (do_scale || do_affine) {
+ for (size_t i = 0; i < pairs.size(); i++)
+ pairs[i].p2 = alignxf * pairs[i].p2;
+ compute_scale(pairs, alignxf, verbose, do_affine);
+ xf2 = alignxf * xf2;
+ }
+
+ timestamp t4 = now();
+ if (verbose > 1) {
+ fprintf(stderr, "Computed xform in %.2f msec.\n",
+ (t4-t3) * 1000.0f);
+ }
+
+ // Update CDFs, if necessary
+ if (!update_cdfs)
+ return err;
+
+ float einv[6];
+ for (int i = 0; i < 6; i++)
+ einv[i] = 1.0f / max(eval[i], EIG_THRESH * eval[5]);
+ float Cinv[6][6];
+ for (int i = 0; i < 6; i++) {
+ float x[6];
+ for (int j = 0; j < 6; j++)
+ x[j] = (j == i) ? 1.0f : 0.0f;
+ eigmult<float,6>(evec, einv, x, x);
+ for (int j = 0; j < 6; j++)
+ Cinv[i][j] = x[j];
+ }
+
+ xform xf1r = norm_xf(xf1);
+ size_t n1 = s1->vertices.size();
+ for (size_t i = 0; i < n1; i++) {
+ sampcdf1[i] = 0.0;
+ if (!weights1[i])
+ continue;
+ point p = xf1 * s1->vertices[i];
+ p -= centroid;
+ p *= scale;
+ vec n = xf1r * s1->normals[i];
+ vec c = p CROSS n;
+ for (int j = 0; j < 6; j++) {
+ float tmp = Cinv[j][0] * c[0] + Cinv[j][1] * c[1] +
+ Cinv[j][2] * c[2] + Cinv[j][3] * n[0] +
+ Cinv[j][4] * n[1] + Cinv[j][5] * n[2];
+ if (j < 3)
+ sampcdf1[i] += tmp * c[j];
+ else
+ sampcdf1[i] += tmp * n[j-3];
+ }
+ sampcdf1[i] *= weights1[i];
+ }
+ for (size_t i = 1; i < n1; i++)
+ sampcdf1[i] += sampcdf1[i-1];
+ if (!sampcdf1[n1-1]) {
+ if (verbose)
+ fprintf(stderr, "No overlap.\n");
+ return -1.0f;
+ }
+ float cscale = 1.0f / sampcdf1[n1-1];
+ for (size_t i = 0; i < n1-1; i++)
+ sampcdf1[i] *= cscale;
+ sampcdf1[n1-1] = 1.0f;
+
+ xform xf2r = norm_xf(xf2);
+ size_t n2 = s2->vertices.size();
+ for (size_t i = 0; i < n2; i++) {
+ sampcdf2[i] = 0.0;
+ if (!weights2[i])
+ continue;
+ point p = xf2 * s2->vertices[i];
+ p -= centroid;
+ p *= scale;
+ vec n = xf2r * s2->normals[i];
+ vec c = p CROSS n;
+ for (int j = 0; j < 6; j++) {
+ float tmp = Cinv[j][0] * c[0] + Cinv[j][1] * c[1] +
+ Cinv[j][2] * c[2] + Cinv[j][3] * n[0] +
+ Cinv[j][4] * n[1] + Cinv[j][5] * n[2];
+ if (j < 3)
+ sampcdf2[i] += tmp * c[j];
+ else
+ sampcdf2[i] += tmp * n[j-3];
+ }
+ sampcdf2[i] *= weights2[i];
+ }
+ for (size_t i = 1; i < n2; i++)
+ sampcdf2[i] += sampcdf2[i-1];
+ cscale = 1.0f / sampcdf2[n2-1];
+ if (!sampcdf2[n2-1]) {
+ if (verbose)
+ fprintf(stderr, "No overlap.\n");
+ return -1.0f;
+ }
+ for (size_t i = 0; i < n2-1; i++)
+ sampcdf2[i] *= cscale;
+ sampcdf2[n2-1] = 1.0f;
+
+ timestamp t5 = now();
+ if (verbose > 1) {
+ fprintf(stderr, "Updated CDFs in %.2f msec.\n",
+ (t5-t4) * 1000.0f);
+ }
+
+ return err;
+}
+
+
+// Do one iteration of point-to-point ICP (this is done in the early stages
+// to assure stability)
+static float ICP_p2pt(TriMesh *s1, TriMesh *s2, const xform &xf1, xform &xf2,
+ const KDtree *kd1, const KDtree *kd2,
+ float &maxdist, int verbose,
+ vector<float> &sampcdf1, vector<float> &sampcdf2,
+ float &incr, bool trans_only)
+{
+ // Compute pairs
+ timestamp t1 = now();
+ if (verbose > 1)
+ fprintf(stderr, "maxdist = %f\n", maxdist);
+ vector<PtPair> pairs;
+ select_and_match(s1, s2, xf1, xf2, kd2, sampcdf1, incr,
+ maxdist, verbose, pairs, false);
+ select_and_match(s2, s1, xf2, xf1, kd1, sampcdf2, incr,
+ maxdist, verbose, pairs, true);
+
+ timestamp t2 = now();
+ size_t np = pairs.size();
+ if (verbose > 1) {
+ fprintf(stderr, "Generated %lu pairs in %.2f msec.\n",
+ (unsigned long) np, (t2-t1) * 1000.0f);
+ }
+
+ // Reject pairs with distance > 3 sigma
+ float thresh = 19.782984f * median_dist2(pairs);
+ if (verbose > 1)
+ fprintf(stderr, "Rejecting pairs > %f\n", sqrt(thresh));
+ size_t next = 0;
+ for (size_t i = 0; i < np; i++) {
+ if (dist2(pairs[i].p1, pairs[i].p2) <= thresh)
+ pairs[next++] = pairs[i];
+ }
+ pairs.erase(pairs.begin() + next, pairs.end());
+
+ timestamp t3 = now();
+ if (verbose > 1) {
+ fprintf(stderr, "Rejected %lu pairs in %.2f msec.\n",
+ (unsigned long) (np - pairs.size()), (t3-t2) * 1000.0f);
+ }
+ if (pairs.size() < (trans_only ? 1 : MIN_PAIRS)) {
+ if (verbose)
+ fprintf(stderr, "Too few point pairs.\n");
+ return -1.0f;
+ }
+
+ // Update incr and maxdist based on what happened here
+ incr *= (float) pairs.size() / DESIRED_PAIRS_EARLY;
+ maxdist = max(1.5f * sqrt(thresh), 0.7f * maxdist);
+
+ // Do the minimization
+ point centroid1, centroid2;
+ for (size_t i = 0; i < pairs.size(); i++) {
+ centroid1 += pairs[i].p1;
+ centroid2 += pairs[i].p2;
+ }
+ centroid1 /= (float) pairs.size();
+ centroid2 /= (float) pairs.size();
+
+ xform alignxf = xform::trans(centroid1 - centroid2);
+
+ double A[3][3] = { {0,0,0}, {0,0,0}, {0,0,0} };
+ double B[3] = {0,0,0};
+ double sum = 0;
+ for (size_t i = 0; i < pairs.size(); i++) {
+ vec p12 = pairs[i].p1 - pairs[i].p2;
+ vec p2c = pairs[i].p2 - centroid2;
+ vec c = p2c CROSS p12;
+ sum += len2(p12);
+ B[0] += c[0]; B[1] += c[1]; B[2] += c[2];
+ A[0][0] += sqr(p2c[1]) + sqr(p2c[2]);
+ A[0][1] -= p2c[0] * p2c[1];
+ A[0][2] -= p2c[0] * p2c[2];
+ A[1][1] += sqr(p2c[0]) + sqr(p2c[2]);
+ A[1][2] -= p2c[1] * p2c[2];
+ A[2][2] += sqr(p2c[0]) + sqr(p2c[1]);
+ }
+ float err = (float)sqrt(sum / pairs.size());
+ if (verbose > 1)
+ fprintf(stderr, "RMS point-to-point error = %f\n", err);
+
+ if (!trans_only) {
+ double diag[3];
+ ldltdc<double,3>(A, diag);
+ ldltsl<double,3>(A, diag, B, B);
+ alignxf = xform::trans(centroid1) *
+ xform::rot(B[0], 1, 0, 0) *
+ xform::rot(B[1], 0, 1, 0) *
+ xform::rot(B[2], 0, 0, 1) *
+ xform::trans(-centroid2);
+ }
+
+ xf2 = alignxf * xf2;
+
+ timestamp t4 = now();
+ if (verbose > 1) {
+ fprintf(stderr, "Computed xform in %.2f msec.\n",
+ (t4-t3) * 1000.0f);
+ }
+ return err;
+}
+
+
+// Do ICP. Aligns mesh s2 to s1, updating xf2 with the new transform.
+// Returns alignment error, or -1 on failure
+float ICP(TriMesh *s1, TriMesh *s2, const xform &xf1, xform &xf2,
+ const KDtree *kd1, const KDtree *kd2,
+ vector<float> &weights1, vector<float> &weights2,
+ float maxdist /* = 0.0f */, int verbose /* = 0 */,
+ bool do_scale /* = false */, bool do_affine /* = false */)
+{
+ // Make sure we have everything precomputed
+ s1->need_normals(); s2->need_normals();
+ if (!s1->faces.empty() || !s1->tstrips.empty()) {
+ s1->need_neighbors();
+ s1->need_adjacentfaces();
+ }
+ if (!s2->faces.empty() || !s2->tstrips.empty()) {
+ s2->need_neighbors();
+ s2->need_adjacentfaces();
+ }
+ size_t nv1 = s1->vertices.size(), nv2 = s2->vertices.size();
+
+ timestamp t = now();
+
+ if (maxdist <= 0.0f) {
+ s1->need_bbox();
+ s2->need_bbox();
+ maxdist = 0.5f * min(len(s1->bbox.size()), len(s2->bbox.size()));
+ }
+ // Compute initial CDFs
+ vector<float> sampcdf1(nv1), sampcdf2(nv2);
+ for (size_t i = 0; i < nv1-1; i++)
+ sampcdf1[i] = (float) (i+1) / nv1;
+ sampcdf1[nv1-1] = 1.0f;
+ for (size_t i = 0; i < nv2-1; i++)
+ sampcdf2[i] = (float) (i+1) / nv2;
+ sampcdf2[nv2-1] = 1.0f;
+
+ // Do a few p2pt iterations
+ float incr = 4.0f / DESIRED_PAIRS_EARLY;
+ for (int i = 0; i < 2; i++) {
+ if (ICP_p2pt(s1, s2, xf1, xf2, kd1, kd2, maxdist, verbose,
+ sampcdf1, sampcdf2, incr, true) < 0.0f)
+ return -1.0f;
+ }
+ for (int i = 0; i < 5; i++) {
+ if (ICP_p2pt(s1, s2, xf1, xf2, kd1, kd2, maxdist, verbose,
+ sampcdf1, sampcdf2, incr, false) < 0.0f)
+ return -1.0f;
+ }
+
+ // Do a point-to-plane iteration and update CDFs
+ if (weights1.size() != nv1 || weights2.size() != nv2)
+ compute_overlaps(s1, s2, xf1, xf2, kd1, kd2,
+ weights1, weights2, maxdist, verbose);
+ float err = ICP_iter(s1, s2, xf1, xf2, kd1, kd2, weights1, weights2,
+ maxdist, verbose, sampcdf1, sampcdf2,
+ incr, true, false, false);
+ if (verbose > 1) {
+ timestamp tnow = now();
+ fprintf(stderr, "Time for initial iterations: %.2f msec.\n\n",
+ (tnow-t) * 1000.0f);
+ t = tnow;
+ }
+ if (err < 0.0f)
+ return err;
+
+ bool rigid_only = true;
+ int iters = 0;
+ vector<int> err_delta_history(TERM_HIST);
+ do {
+ float lasterr = err;
+ if (verbose > 1)
+ fprintf(stderr, "Using incr = %f\n", incr);
+ bool recompute = (iters % 10 == 9);
+ if (recompute)
+ compute_overlaps(s1, s2, xf1, xf2, kd1, kd2,
+ weights1, weights2, maxdist, verbose);
+ err = ICP_iter(s1, s2, xf1, xf2, kd1, kd2, weights1, weights2,
+ maxdist, verbose, sampcdf1, sampcdf2, incr,
+ recompute, do_scale && !rigid_only,
+ do_affine && !rigid_only);
+ if (verbose > 1) {
+ timestamp tnow = now();
+ fprintf(stderr, "Time for this iteration: %.2f msec.\n\n",
+ (tnow-t) * 1000.0f);
+ t = tnow;
+ }
+ if (err < 0.0f)
+ return err;
+
+ // Check whether the error's been going up or down lately.
+ // Specifically, we break out if error has gone up in
+ // TERM_THRESH out of the last TERM_HIST iterations.
+ for (int i = 0; i < TERM_HIST - 1; i++)
+ err_delta_history[i] = err_delta_history[i+1];
+ err_delta_history[TERM_HIST - 1] = (err >= lasterr);
+ int nincreases = 0;
+ for (int i = 0; i < TERM_HIST; i++)
+ nincreases += err_delta_history[i];
+ if (nincreases >= TERM_THRESH) {
+ if (!rigid_only || (!do_scale && !do_affine))
+ break;
+ err_delta_history.clear();
+ err_delta_history.resize(TERM_HIST);
+ rigid_only = false;
+ }
+ } while (++iters < MAX_ITERS);
+
+ if (verbose > 1)
+ fprintf(stderr, "Did %d iterations\n\n", iters);
+
+ // One final iteration at a higher sampling rate...
+ if (verbose > 1)
+ fprintf(stderr, "Last iteration...\n");
+ incr *= (float) DESIRED_PAIRS / DESIRED_PAIRS_FINAL;
+ if (verbose > 1)
+ fprintf(stderr, "Using incr = %f\n", incr);
+ err = ICP_iter(s1, s2, xf1, xf2, kd1, kd2, weights1, weights2,
+ maxdist, verbose, sampcdf1, sampcdf2, incr,
+ false, do_scale, do_affine);
+ if (verbose > 1) {
+ timestamp tnow = now();
+ fprintf(stderr, "Time for this iteration: %.2f msec.\n\n",
+ (tnow-t) * 1000.0f);
+ t = tnow;
+ }
+ return err;
+}
+
+
+// Easier-to-use interface to ICP
+float ICP(TriMesh *s1, TriMesh *s2, const xform &xf1, xform &xf2,
+ int verbose /* = 0 */,
+ bool do_scale /* = false */, bool do_affine /* = false */)
+{
+ KDtree *kd1 = new KDtree(s1->vertices);
+ KDtree *kd2 = new KDtree(s2->vertices);
+ vector<float> weights1, weights2;
+ float icperr = ICP(s1, s2, xf1, xf2, kd1, kd2,
+ weights1, weights2, 0.0f, verbose,
+ do_scale, do_affine);
+ delete kd2;
+ delete kd1;
+ return icperr;
+}
+
Index: external/trimesh/libsrc/TriMesh_curvature.cc
--- external/trimesh/libsrc/TriMesh_curvature.cc (revision 0)
+++ external/trimesh/libsrc/TriMesh_curvature.cc (revision 0)
@@ -0,0 +1,325 @@
+/*
+Szymon Rusinkiewicz
+Princeton University
+
+TriMesh_curvature.cc
+Computation of per-vertex principal curvatures and directions.
+
+Uses algorithm from
+ Rusinkiewicz, Szymon.
+ "Estimating Curvatures and Their Derivatives on Triangle Meshes,"
+ Proc. 3DPVT, 2004.
+*/
+
+#include <stdio.h>
+#include "TriMesh.h"
+#include "TriMesh_algo.h"
+#include "lineqn.h"
+
+
+// i+1 and i-1 modulo 3
+// This way of computing it tends to be faster than using %
+#define NEXT(i) ((i)<2 ? (i)+1 : (i)-2)
+#define PREV(i) ((i)>0 ? (i)-1 : (i)+2)
+
+
+// Rotate a coordinate system to be perpendicular to the given normal
+static void rot_coord_sys(const vec &old_u, const vec &old_v,
+ const vec &new_norm,
+ vec &new_u, vec &new_v)
+{
+ new_u = old_u;
+ new_v = old_v;
+ vec old_norm = old_u CROSS old_v;
+ float ndot = old_norm DOT new_norm;
+ if (unlikely(ndot <= -1.0f)) {
+ new_u = -new_u;
+ new_v = -new_v;
+ return;
+ }
+ vec perp_old = new_norm - ndot * old_norm;
+ vec dperp = 1.0f / (1 + ndot) * (old_norm + new_norm);
+ new_u -= dperp * (new_u DOT perp_old);
+ new_v -= dperp * (new_v DOT perp_old);
+}
+
+
+// Reproject a curvature tensor from the basis spanned by old_u and old_v
+// (which are assumed to be unit-length and perpendicular) to the
+// new_u, new_v basis.
+void proj_curv(const vec &old_u, const vec &old_v,
+ float old_ku, float old_kuv, float old_kv,
+ const vec &new_u, const vec &new_v,
+ float &new_ku, float &new_kuv, float &new_kv)
+{
+ vec r_new_u, r_new_v;
+ rot_coord_sys(new_u, new_v, old_u CROSS old_v, r_new_u, r_new_v);
+
+ float u1 = r_new_u DOT old_u;
+ float v1 = r_new_u DOT old_v;
+ float u2 = r_new_v DOT old_u;
+ float v2 = r_new_v DOT old_v;
+ new_ku = old_ku * u1*u1 + old_kuv * (2.0f * u1*v1) + old_kv * v1*v1;
+ new_kuv = old_ku * u1*u2 + old_kuv * (u1*v2 + u2*v1) + old_kv * v1*v2;
+ new_kv = old_ku * u2*u2 + old_kuv * (2.0f * u2*v2) + old_kv * v2*v2;
+}
+
+
+// Like the above, but for dcurv
+void proj_dcurv(const vec &old_u, const vec &old_v,
+ const Vec<4> old_dcurv,
+ const vec &new_u, const vec &new_v,
+ Vec<4> &new_dcurv)
+{
+ vec r_new_u, r_new_v;
+ rot_coord_sys(new_u, new_v, old_u CROSS old_v, r_new_u, r_new_v);
+
+ float u1 = r_new_u DOT old_u;
+ float v1 = r_new_u DOT old_v;
+ float u2 = r_new_v DOT old_u;
+ float v2 = r_new_v DOT old_v;
+
+ new_dcurv[0] = old_dcurv[0]*u1*u1*u1 +
+ old_dcurv[1]*3.0f*u1*u1*v1 +
+ old_dcurv[2]*3.0f*u1*v1*v1 +
+ old_dcurv[3]*v1*v1*v1;
+ new_dcurv[1] = old_dcurv[0]*u1*u1*u2 +
+ old_dcurv[1]*(u1*u1*v2 + 2.0f*u2*u1*v1) +
+ old_dcurv[2]*(u2*v1*v1 + 2.0f*u1*v1*v2) +
+ old_dcurv[3]*v1*v1*v2;
+ new_dcurv[2] = old_dcurv[0]*u1*u2*u2 +
+ old_dcurv[1]*(u2*u2*v1 + 2.0f*u1*u2*v2) +
+ old_dcurv[2]*(u1*v2*v2 + 2.0f*u2*v2*v1) +
+ old_dcurv[3]*v1*v2*v2;
+ new_dcurv[3] = old_dcurv[0]*u2*u2*u2 +
+ old_dcurv[1]*3.0f*u2*u2*v2 +
+ old_dcurv[2]*3.0f*u2*v2*v2 +
+ old_dcurv[3]*v2*v2*v2;
+}
+
+
+// Given a curvature tensor, find principal directions and curvatures
+// Makes sure that pdir1 and pdir2 are perpendicular to normal
+void diagonalize_curv(const vec &old_u, const vec &old_v,
+ float ku, float kuv, float kv,
+ const vec &new_norm,
+ vec &pdir1, vec &pdir2, float &k1, float &k2)
+{
+ vec r_old_u, r_old_v;
+ rot_coord_sys(old_u, old_v, new_norm, r_old_u, r_old_v);
+
+ float c = 1, s = 0, tt = 0;
+ if (likely(kuv != 0.0f)) {
+ // Jacobi rotation to diagonalize
+ float h = 0.5f * (kv - ku) / kuv;
+ tt = (h < 0.0f) ?
+ 1.0f / (h - sqrt(1.0f + h*h)) :
+ 1.0f / (h + sqrt(1.0f + h*h));
+ c = 1.0f / sqrt(1.0f + tt*tt);
+ s = tt * c;
+ }
+
+ k1 = ku - tt * kuv;
+ k2 = kv + tt * kuv;
+
+ if (fabs(k1) >= fabs(k2)) {
+ pdir1 = c*r_old_u - s*r_old_v;
+ } else {
+ swap(k1, k2);
+ pdir1 = s*r_old_u + c*r_old_v;
+ }
+ pdir2 = new_norm CROSS pdir1;
+}
+
+
+// Compute principal curvatures and directions.
+void TriMesh::need_curvatures()
+{
+ if (curv1.size() == vertices.size())
+ return;
+ need_faces();
+ need_normals();
+ need_pointareas();
+
+ dprintf("Computing curvatures... ");
+
+ // Resize the arrays we'll be using
+ int nv = vertices.size(), nf = faces.size();
+ curv1.clear(); curv1.resize(nv); curv2.clear(); curv2.resize(nv);
+ pdir1.clear(); pdir1.resize(nv); pdir2.clear(); pdir2.resize(nv);
+ vector<float> curv12(nv);
+
+ // Set up an initial coordinate system per vertex
+#pragma omp parallel for
+ for (int i = 0; i < nf; i++) {
+ pdir1[faces[i][0]] = vertices[faces[i][1]] -
+ vertices[faces[i][0]];
+ pdir1[faces[i][1]] = vertices[faces[i][2]] -
+ vertices[faces[i][1]];
+ pdir1[faces[i][2]] = vertices[faces[i][0]] -
+ vertices[faces[i][2]];
+ }
+#pragma omp parallel for
+ for (int i = 0; i < nv; i++) {
+ pdir1[i] = pdir1[i] CROSS normals[i];
+ normalize(pdir1[i]);
+ pdir2[i] = normals[i] CROSS pdir1[i];
+ }
+
+ // Compute curvature per-face
+#pragma omp parallel for
+ for (int i = 0; i < nf; i++) {
+ // Edges
+ vec e[3] = { vertices[faces[i][2]] - vertices[faces[i][1]],
+ vertices[faces[i][0]] - vertices[faces[i][2]],
+ vertices[faces[i][1]] - vertices[faces[i][0]] };
+
+ // N-T-B coordinate system per face
+ vec t = e[0];
+ normalize(t);
+ vec n = e[0] CROSS e[1];
+ vec b = n CROSS t;
+ normalize(b);
+
+ // Estimate curvature based on variation of normals
+ // along edges
+ float m[3] = { 0, 0, 0 };
+ float w[3][3] = { {0,0,0}, {0,0,0}, {0,0,0} };
+ for (int j = 0; j < 3; j++) {
+ float u = e[j] DOT t;
+ float v = e[j] DOT b;
+ w[0][0] += u*u;
+ w[0][1] += u*v;
+ //w[1][1] += v*v + u*u;
+ //w[1][2] += u*v;
+ w[2][2] += v*v;
+ vec dn = normals[faces[i][PREV(j)]] -
+ normals[faces[i][NEXT(j)]];
+ float dnu = dn DOT t;
+ float dnv = dn DOT b;
+ m[0] += dnu*u;
+ m[1] += dnu*v + dnv*u;
+ m[2] += dnv*v;
+ }
+ w[1][1] = w[0][0] + w[2][2];
+ w[1][2] = w[0][1];
+
+ // Least squares solution
+ float diag[3];
+ if (!ldltdc<float,3>(w, diag)) {
+ //fprintf(stderr, "ldltdc failed!\n");
+ continue;
+ }
+ ldltsl<float,3>(w, diag, m, m);
+
+ // Push it back out to the vertices
+ for (int j = 0; j < 3; j++) {
+ int vj = faces[i][j];
+ float c1, c12, c2;
+ proj_curv(t, b, m[0], m[1], m[2],
+ pdir1[vj], pdir2[vj], c1, c12, c2);
+ float wt = cornerareas[i][j] / pointareas[vj];
+ curv1[vj] += wt * c1;
+ curv12[vj] += wt * c12;
+ curv2[vj] += wt * c2;
+ }
+ }
+
+ // Compute principal directions and curvatures at each vertex
+#pragma omp parallel for
+ for (int i = 0; i < nv; i++)
+ diagonalize_curv(pdir1[i], pdir2[i],
+ curv1[i], curv12[i], curv2[i],
+ normals[i], pdir1[i], pdir2[i],
+ curv1[i], curv2[i]);
+ dprintf("Done.\n");
+}
+
+
+// Compute derivatives of curvature.
+void TriMesh::need_dcurv()
+{
+ if (dcurv.size() == vertices.size())
+ return;
+ need_curvatures();
+
+ dprintf("Computing dcurv... ");
+
+ // Resize the arrays we'll be using
+ int nv = vertices.size(), nf = faces.size();
+ dcurv.clear(); dcurv.resize(nv);
+
+ // Compute dcurv per-face
+#pragma omp parallel for
+ for (int i = 0; i < nf; i++) {
+ // Edges
+ vec e[3] = { vertices[faces[i][2]] - vertices[faces[i][1]],
+ vertices[faces[i][0]] - vertices[faces[i][2]],
+ vertices[faces[i][1]] - vertices[faces[i][0]] };
+
+ // N-T-B coordinate system per face
+ vec t = e[0];
+ normalize(t);
+ vec n = e[0] CROSS e[1];
+ vec b = n CROSS t;
+ normalize(b);
+
+ // Project curvature tensor from each vertex into this
+ // face's coordinate system
+ vec fcurv[3];
+ for (int j = 0; j < 3; j++) {
+ int vj = faces[i][j];
+ proj_curv(pdir1[vj], pdir2[vj], curv1[vj], 0, curv2[vj],
+ t, b, fcurv[j][0], fcurv[j][1], fcurv[j][2]);
+
+ }
+
+ // Estimate dcurv based on variation of curvature along edges
+ float m[4] = { 0, 0, 0, 0 };
+ float w[4][4] = { {0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0} };
+ for (int j = 0; j < 3; j++) {
+ // Variation of curvature along each edge
+ vec dfcurv = fcurv[PREV(j)] - fcurv[NEXT(j)];
+ float u = e[j] DOT t;
+ float v = e[j] DOT b;
+ float u2 = u*u, v2 = v*v, uv = u*v;
+ w[0][0] += u2;
+ w[0][1] += uv;
+ //w[1][1] += 2.0f*u2 + v2;
+ //w[1][2] += 2.0f*uv;
+ //w[2][2] += u2 + 2.0f*v2;
+ //w[2][3] += uv;
+ w[3][3] += v2;
+ m[0] += u*dfcurv[0];
+ m[1] += v*dfcurv[0] + 2.0f*u*dfcurv[1];
+ m[2] += 2.0f*v*dfcurv[1] + u*dfcurv[2];
+ m[3] += v*dfcurv[2];
+ }
+ w[1][1] = 2.0f * w[0][0] + w[3][3];
+ w[1][2] = 2.0f * w[0][1];
+ w[2][2] = w[0][0] + 2.0f * w[3][3];
+ w[2][3] = w[0][1];
+
+ // Least squares solution
+ float d[4];
+ if (!ldltdc<float,4>(w, d)) {
+ //fprintf(stderr, "ldltdc failed!\n");
+ continue;
+ }
+ ldltsl<float,4>(w, d, m, m);
+ Vec<4> face_dcurv(m);
+
+ // Push it back out to each vertex
+ for (int j = 0; j < 3; j++) {
+ int vj = faces[i][j];
+ Vec<4> this_vert_dcurv;
+ proj_dcurv(t, b, face_dcurv,
+ pdir1[vj], pdir2[vj], this_vert_dcurv);
+ float wt = cornerareas[i][j] / pointareas[vj];
+ dcurv[vj] += wt * this_vert_dcurv;
+ }
+ }
+
+ dprintf("Done.\n");
+}
+
Index: external/trimesh/libsrc/KDtree.cc
--- external/trimesh/libsrc/KDtree.cc (revision 0)
+++ external/trimesh/libsrc/KDtree.cc (revision 0)
@@ -0,0 +1,299 @@
+/*
+Szymon Rusinkiewicz
+Princeton University
+
+KDtree.cc
+A K-D tree for points, with limited capabilities (find nearest point to
+a given point, or to a ray).
+*/
+
+#include <cmath>
+#include <string.h>
+#include "KDtree.h"
+#include "mempool.h"
+#include <vector>
+#include <algorithm>
+using std::vector;
+using std::swap;
+using std::sqrt;
+
+
+// Small utility fcns
+static inline float sqr(float x)
+{
+ return x*x;
+}
+
+static inline float dist2(const float *x, const float *y)
+{
+ return sqr(x[0]-y[0]) + sqr(x[1]-y[1]) + sqr(x[2]-y[2]);
+}
+
+static inline float dist2ray2(const float *x, const float *p, const float *d)
+{
+ float xp0 = x[0]-p[0], xp1 = x[1]-p[1], xp2 = x[2]-p[2];
+ return sqr(xp0) + sqr(xp1) + sqr(xp2) -
+ sqr(xp0*d[0] + xp1*d[1] + xp2*d[2]);
+}
+
+
+// Class for nodes in the K-D tree
+class KDtree::Node {
+private:
+ static PoolAlloc memPool;
+
+public:
+ // A place to put all the stuff required while traversing the K-D
+ // tree, so we don't have to pass tons of variables at each fcn call
+ struct Traversal_Info {
+ const float *p, *dir;
+ const float *closest;
+ float closest_d, closest_d2;
+ const KDtree::CompatFunc *iscompat;
+ };
+
+ enum { MAX_PTS_PER_NODE = 7 };
+
+
+ // The node itself
+
+ int npts; // If this is 0, intermediate node. If nonzero, leaf.
+
+ union {
+ struct {
+ float center[3];
+ float r;
+ int splitaxis;
+ Node *child1, *child2;
+ } node;
+ struct {
+ const float *p[MAX_PTS_PER_NODE];
+ } leaf;
+ };
+
+ Node(const float **pts, int n);
+ ~Node();
+
+ void find_closest_to_pt(Traversal_Info &k) const;
+ void find_closest_to_ray(Traversal_Info &k) const;
+
+ void *operator new(size_t n) { return memPool.alloc(n); }
+ void operator delete(void *p, size_t n) { memPool.free(p,n); }
+};
+
+
+// Class static variable
+PoolAlloc KDtree::Node::memPool(sizeof(KDtree::Node));
+
+
+// Create a KD tree from the points pointed to by the array pts
+KDtree::Node::Node(const float **pts, int n)
+{
+ // Leaf nodes
+ if (n <= MAX_PTS_PER_NODE) {
+ npts = n;
+ memcpy(leaf.p, pts, n * sizeof(float *));
+ return;
+ }
+
+
+ // Else, interior nodes
+ npts = 0;
+
+ // Find bbox
+ float xmin = pts[0][0], xmax = pts[0][0];
+ float ymin = pts[0][1], ymax = pts[0][1];
+ float zmin = pts[0][2], zmax = pts[0][2];
+ for (int i = 1; i < n; i++) {
+ if (pts[i][0] < xmin) xmin = pts[i][0];
+ if (pts[i][0] > xmax) xmax = pts[i][0];
+ if (pts[i][1] < ymin) ymin = pts[i][1];
+ if (pts[i][1] > ymax) ymax = pts[i][1];
+ if (pts[i][2] < zmin) zmin = pts[i][2];
+ if (pts[i][2] > zmax) zmax = pts[i][2];
+ }
+
+ // Find node center and size
+ node.center[0] = 0.5f * (xmin+xmax);
+ node.center[1] = 0.5f * (ymin+ymax);
+ node.center[2] = 0.5f * (zmin+zmax);
+ float dx = xmax-xmin;
+ float dy = ymax-ymin;
+ float dz = zmax-zmin;
+ node.r = 0.5f * sqrt(sqr(dx) + sqr(dy) + sqr(dz));
+
+ // Find longest axis
+ node.splitaxis = 2;
+ if (dx > dy) {
+ if (dx > dz)
+ node.splitaxis = 0;
+ } else {
+ if (dy > dz)
+ node.splitaxis = 1;
+ }
+
+ // Partition
+ const float splitval = node.center[node.splitaxis];
+ const float **left = pts, **right = pts + n - 1;
+ while (1) {
+ while ((*left)[node.splitaxis] < splitval)
+ left++;
+ while ((*right)[node.splitaxis] >= splitval)
+ right--;
+ if (right < left)
+ break;
+ swap(*left, *right);
+ left++; right--;
+ }
+
+
+ // Build subtrees
+ node.child1 = new Node(pts, left-pts);
+ node.child2 = new Node(left, n-(left-pts));
+}
+
+
+// Destroy a KD tree node
+KDtree::Node::~Node()
+{
+ if (!npts) {
+ delete node.child1;
+ delete node.child2;
+ }
+}
+
+
+// Crawl the KD tree
+void KDtree::Node::find_closest_to_pt(KDtree::Node::Traversal_Info &k) const
+{
+ // Leaf nodes
+ if (npts) {
+ for (int i = 0; i < npts; i++) {
+ float myd2 = dist2(leaf.p[i], k.p);
+ if ((myd2 < k.closest_d2) &&
+ (!k.iscompat || (*k.iscompat)(leaf.p[i]))) {
+ k.closest_d2 = myd2;
+ k.closest_d = sqrt(k.closest_d2);
+ k.closest = leaf.p[i];
+ }
+ }
+ return;
+ }
+
+
+ // Check whether to abort
+ if (dist2(node.center, k.p) >= sqr(node.r + k.closest_d))
+ return;
+
+ // Recursive case
+ float myd = node.center[node.splitaxis] - k.p[node.splitaxis];
+ if (myd >= 0.0f) {
+ node.child1->find_closest_to_pt(k);
+ if (myd < k.closest_d)
+ node.child2->find_closest_to_pt(k);
+ } else {
+ node.child2->find_closest_to_pt(k);
+ if (-myd < k.closest_d)
+ node.child1->find_closest_to_pt(k);
+ }
+}
+
+
+// Crawl the KD tree to look for the closest point to
+// the line going through k.p in the direction k.dir
+void KDtree::Node::find_closest_to_ray(KDtree::Node::Traversal_Info &k) const
+{
+ // Leaf nodes
+ if (npts) {
+ for (int i = 0; i < npts; i++) {
+ float myd2 = dist2ray2(leaf.p[i], k.p, k.dir);
+ if ((myd2 < k.closest_d2) &&
+ (!k.iscompat || (*k.iscompat)(leaf.p[i]))) {
+ k.closest_d2 = myd2;
+ k.closest_d = sqrt(k.closest_d2);
+ k.closest = leaf.p[i];
+ }
+ }
+ return;
+ }
+
+
+ // Check whether to abort
+ if (dist2ray2(node.center, k.p, k.dir) >= sqr(node.r + k.closest_d))
+ return;
+
+ // Recursive case
+ if (k.p[node.splitaxis] < node.center[node.splitaxis] ) {
+ node.child1->find_closest_to_ray(k);
+ node.child2->find_closest_to_ray(k);
+ } else {
+ node.child2->find_closest_to_ray(k);
+ node.child1->find_closest_to_ray(k);
+ }
+}
+
+
+// Create a KDtree from a list of points (i.e., ptlist is a list of 3*n floats)
+void KDtree::build(const float *ptlist, int n)
+{
+ vector<const float *> pts(n);
+ for (int i = 0; i < n; i++)
+ pts[i] = ptlist + i * 3;
+
+ root = new Node(&(pts[0]), n);
+}
+
+
+// Delete a KDtree
+KDtree::~KDtree()
+{
+ delete root;
+}
+
+
+// Return the closest point in the KD tree to p
+const float *KDtree::closest_to_pt(const float *p, float maxdist2,
+ const CompatFunc *iscompat /* = NULL */) const
+{
+ Node::Traversal_Info k;
+
+ k.p = p;
+ k.iscompat = iscompat;
+ k.closest = NULL;
+ if (maxdist2 <= 0.0f)
+ maxdist2 = sqr(root->node.r);
+ k.closest_d2 = maxdist2;
+ k.closest_d = sqrt(k.closest_d2);
+
+ root->find_closest_to_pt(k);
+
+ return k.closest;
+}
+
+
+// Return the closest point in the KD tree to the line
+// going through p in the direction dir
+const float *KDtree::closest_to_ray(const float *p, const float *dir,
+ float maxdist2,
+ const CompatFunc *iscompat /* = NULL */) const
+{
+ Node::Traversal_Info k;
+
+ float one_over_dir_len = 1.0f / sqrt(sqr(dir[0])+sqr(dir[1])+sqr(dir[2]));
+ float normalized_dir[3] = { dir[0] * one_over_dir_len,
+ dir[1] * one_over_dir_len,
+ dir[2] * one_over_dir_len };
+ k.dir = normalized_dir;
+ k.p = p;
+ k.iscompat = iscompat;
+ k.closest = NULL;
+ if (maxdist2 <= 0.0f)
+ maxdist2 = sqr(root->node.r);
+ k.closest_d2 = maxdist2;
+ k.closest_d = sqrt(k.closest_d2);
+
+ root->find_closest_to_ray(k);
+
+ return k.closest;
+}
+
Index: external/trimesh/libsrc/edgeflip.cc
--- external/trimesh/libsrc/edgeflip.cc (revision 0)
+++ external/trimesh/libsrc/edgeflip.cc (revision 0)
@@ -0,0 +1,176 @@
+/*
+Szymon Rusinkiewicz
+Princeton University
+
+edgeflip.cc
+Optimally re-triangulate a mesh by doing edge flips
+*/
+
+#include <stdio.h>
+#include "TriMesh.h"
+#include "TriMesh_algo.h"
+#include <utility>
+#include <queue>
+using std::pair;
+using std::make_pair;
+using std::priority_queue;
+
+typedef pair<int,int> TriMeshEdge; // (face, edge) pair
+typedef pair<float, TriMeshEdge> TriMeshEdgeWithBenefit;
+
+
+// Cosine of the maximum angle in triangle (v1,v2,v3)
+static float cosmaxangle(const point &v1, const point &v2, const point &v3)
+{
+ float a = dist(v2,v3);
+ float b = dist(v3,v1);
+ float c = dist(v1,v2);
+ float A = a * (b*b + c*c - a*a);
+ float B = b * (c*c + a*a - b*b);
+ float C = c * (a*a + b*b - c*c);
+ return 0.5f * min(min(A,B),C) / (a*b*c); // min cosine == max angle
+}
+
+
+/*
+ v1 v4 v1 v4
+ +-------+ +-------+
+ \ . \ ? \ . \
+ \ . \ ---> \ . \
+ \ . \ \ . \
+ +-------+ +-------+
+ v2 v3 v2 v3
+
+ Given a pair of triangles (v1,v2,v3) and (v1,v3,v4), what is the benefit
+ of re-triangulating as (v1,v2,v4) and (v2,v3,v4)?
+ In the current incarnation, makes sure we don't create a kink
+ (a dihedral angle smaller than 90 degrees), then tries to minimize the
+ maximum angle (which seems to work better than minimizing length of the
+ diagonal and maximizing minimum angle (Delaunay)). Note that, unlike
+ the Delaunay case, this isn't guaranteed to converge to the global optimum.
+*/
+static float flip_benefit(const point &v1, const point &v2,
+ const point &v3, const point &v4)
+{
+ vec n124 = (v4 - v2) CROSS (v1 - v2);
+ vec n234 = (v3 - v2) CROSS (v4 - v2);
+ if ((n124 DOT n234) <= 0.0f)
+ return 0.0f;
+
+ return max(-cosmaxangle(v1,v2,v3), -cosmaxangle(v1,v3,v4)) -
+ max(-cosmaxangle(v1,v2,v4), -cosmaxangle(v2,v3,v4));
+}
+
+
+// Given a mesh edge defined as a (face, whichedge) pair, figure out whether
+// it is possible and desirable to do an edge flip. This does some sanity
+// checks, figures out the four vertices involved, then calls the above
+// function to actually compute the benefit.
+static float flip_benefit(const TriMesh *mesh, int f, int e)
+{
+ int ae = mesh->across_edge[f][e];
+ if (ae < 0)
+ return 0;
+
+ int v2 = mesh->faces[f][e];
+ int v3 = mesh->faces[f][(e+1)%3];
+ int v1 = mesh->faces[f][(e+2)%3];
+ int faei3 = mesh->faces[ae].indexof(v3);
+ if (mesh->across_edge[ae][(faei3+1)%3] != f) {
+ fprintf(stderr, "AAAAAAARGH!\n");
+ fprintf(stderr, "f = %d: %d %d %d\n", f, v1, v2, v3);
+ fprintf(stderr, "ae = %d\n", ae);
+ fprintf(stderr, "aef = %d %d %d\n", mesh->faces[ae][0],
mesh->faces[ae][1], mesh->faces[ae][2]);
+ fprintf(stderr, "faei3 = %d\n", faei3);
+ fprintf(stderr, "aeae = %d %d %d\n", mesh->across_edge[ae][0],
mesh->across_edge[ae][1], mesh->across_edge[ae][2]);
+ return 0; // Topological weirdness...
+ }
+ int v4 = mesh->faces[ae][(faei3+1)%3];
+ if (v2 == v4)
+ return 0;
+ return flip_benefit(mesh->vertices[v1], mesh->vertices[v2],
+ mesh->vertices[v3], mesh->vertices[v4]);
+}
+
+
+// Do an edge flip of edge e on face f, updating the across_edge map.
+// Returns the other face involved in the flip.
+static int edge_flip(TriMesh *mesh, int f1, int e)
+{
+ int f2 = mesh->across_edge[f1][e];
+
+ int v2 = mesh->faces[f1][e];
+ int v3 = mesh->faces[f1][(e+1)%3];
+ int f2i3 = mesh->faces[f2].indexof(v3);
+ int v4 = mesh->faces[f2][(f2i3+1)%3];
+
+ int ae14 = mesh->across_edge[f2][f2i3];
+ int ae23 = mesh->across_edge[f1][(e+2)%3];
+
+ mesh->faces[f1][(e+1)%3] = v4;
+ mesh->faces[f2][(f2i3+2)%3] = v2;
+ mesh->across_edge[f1][e] = ae14;
+ mesh->across_edge[f1][(e+2)%3] = f2;
+ mesh->across_edge[f2][f2i3] = f1;
+ mesh->across_edge[f2][(f2i3+1)%3] = ae23;
+
+ int ae14iv4 = (ae14 >= 0) ? mesh->faces[ae14].indexof(v4) : -1;
+ if (ae14iv4 >= 0 && mesh->across_edge[ae14][(ae14iv4+1)%3] == f2)
+ mesh->across_edge[ae14][(ae14iv4+1)%3] = f1;
+ int ae23iv2 = (ae23 >= 0) ? mesh->faces[ae23].indexof(v2) : -1;
+ if (ae23iv2 >= 0 && mesh->across_edge[ae23][(ae23iv2+1)%3] == f1)
+ mesh->across_edge[ae23][(ae23iv2+1)%3] = f2;
+
+ return f2;
+}
+
+
+// Do as many edge flips as necessary...
+void edgeflip(TriMesh *mesh)
+{
+ mesh->need_faces();
+ mesh->tstrips.clear();
+ mesh->grid.clear();
+ mesh->need_across_edge();
+
+ TriMesh::dprintf("Flipping edges... ");
+
+ // Find edges that need to be flipped, and insert them into
+ // the to-do list
+ int nf = mesh->faces.size();
+ priority_queue<TriMeshEdgeWithBenefit> todo;
+ for (int i = 0; i < nf; i++) {
+ for (int j = 0; j < 3; j++) {
+ float b = flip_benefit(mesh, i, j);
+ if (b > 0.0f)
+ todo.push(make_pair(b, make_pair(i, j)));
+ }
+ }
+
+
+ // Process things in order of decreasing benefit
+ while (!todo.empty()) {
+ int f = todo.top().second.first;
+ int e = todo.top().second.second;
+ todo.pop();
+ // Re-check in case the mesh has changed under us
+ if (flip_benefit(mesh, f, e) <= 0.0f)
+ continue;
+ // OK, do the edge flip
+ int f2 = edge_flip(mesh, f, e);
+ // Insert new edges into queue, if necessary
+ for (int j = 0; j < 3; j++) {
+ float b = flip_benefit(mesh, f, j);
+ if (b > 0.0f)
+ todo.push(make_pair(b, make_pair(f, j)));
+ }
+ for (int j = 0; j < 3; j++) {
+ float b = flip_benefit(mesh, f2, j);
+ if (b > 0.0f)
+ todo.push(make_pair(b, make_pair(f2, j)));
+ }
+ }
+
+ TriMesh::dprintf("Done.\n");
+}
+
Index: external/trimesh/libsrc/TriMesh_grid.cc
--- external/trimesh/libsrc/TriMesh_grid.cc (revision 0)
+++ external/trimesh/libsrc/TriMesh_grid.cc (revision 0)
@@ -0,0 +1,109 @@
+/*
+Szymon Rusinkiewicz
+Princeton University
+
+TriMesh_grid.cc
+Code for dealing with range grids
+*/
+
+#include "TriMesh.h"
+#include "TriMesh_algo.h"
+
+
+// Helper function - make a face with the 3 given vertices from the grid
+static void mkface(TriMesh *mesh, int v1, int v2, int v3)
+{
+ mesh->faces.push_back(TriMesh::Face(
+ mesh->grid[v1], mesh->grid[v2], mesh->grid[v3]));
+}
+
+
+// Triangulate a range grid
+void TriMesh::triangulate_grid()
+{
+ dprintf("Triangulating... ");
+
+ int nv = vertices.size();
+ int ngrid = grid_width * grid_height;
+
+ // Work around broken files that have a vertex position of (0,0,0)
+ // but mark the vertex as valid, or random broken grid indices
+ for (int i = 0; i < ngrid; i++) {
+ if (grid[i] >= 0) {
+ if (grid[i] >= nv)
+ grid[i] = GRID_INVALID;
+ else if (!vertices[grid[i]])
+ grid[i] = GRID_INVALID;
+ } else if (grid[i] < 0) {
+ if (grid[i] != GRID_INVALID)
+ grid[i] = GRID_INVALID;
+ } else { // Some evil people like NaNs
+ grid[i] = GRID_INVALID;
+ }
+ }
+
+ // Count valid faces
+ int ntris = 0;
+ for (int j = 0; j < grid_height - 1; j++) {
+ for (int i = 0; i < grid_width - 1; i++) {
+ int ll = i + j * grid_width;
+ int lr = ll + 1;
+ int ul = ll + grid_width;
+ int ur = ul + 1;
+ int nvalid = (grid[ll] >= 0) + (grid[lr] >= 0) +
+ (grid[ul] >= 0) + (grid[ur] >= 0);
+ if (nvalid == 4)
+ ntris += 2;
+ else if (nvalid == 3)
+ ntris += 1;
+ }
+ }
+
+ // Actually make the faces
+ int old_nfaces = faces.size();
+ int new_nfaces = old_nfaces + ntris;
+ faces.reserve(new_nfaces);
+
+ for (int j = 0; j < grid_height - 1; j++) {
+ for (int i = 0; i < grid_width - 1; i++) {
+ int ll = i + j * grid_width;
+ int lr = ll + 1;
+ int ul = ll + grid_width;
+ int ur = ul + 1;
+ int nvalid = (grid[ll] >= 0) + (grid[lr] >= 0) +
+ (grid[ul] >= 0) + (grid[ur] >= 0);
+ if (nvalid < 3)
+ continue;
+ if (nvalid == 4) {
+ // Triangulate in the direction that
+ // gives the shorter diagonal
+ float ll_ur = dist2(vertices[grid[ll]],
+ vertices[grid[ur]]);
+ float lr_ul = dist2(vertices[grid[lr]],
+ vertices[grid[ul]]);
+ if (ll_ur < lr_ul) {
+ mkface(this, ll, lr, ur);
+ mkface(this, ll, ur, ul);
+ } else {
+ mkface(this, ll, lr, ul);
+ mkface(this, lr, ur, ul);
+ }
+ continue;
+ }
+ // nvalid == 3
+ if (grid[ll] < 0)
+ mkface(this, lr, ur, ul);
+ else if (grid[lr] < 0)
+ mkface(this, ll, ur, ul);
+ else if (grid[ul] < 0)
+ mkface(this, ll, lr, ur);
+ else
+ mkface(this, ll, lr, ul);
+ }
+ }
+
+ dprintf("%lu faces.\n ", ntris);
+ remove_sliver_faces(this);
+ dprintf(" ");
+}
+
Index: external/trimesh/libsrc/filter.cc
--- external/trimesh/libsrc/filter.cc (revision 0)
+++ external/trimesh/libsrc/filter.cc (revision 0)
@@ -0,0 +1,491 @@
+/*
+Szymon Rusinkiewicz
+Princeton University
+
+filter.cc
+Miscellaneous filtering operations on trimeshes
+*/
+
+
+#include <stdio.h>
+#include "TriMesh.h"
+#include "TriMesh_algo.h"
+#include "lineqn.h"
+#include <numeric>
+using namespace std;
+
+
+// Quick 'n dirty portable random number generator
+static inline float tinyrnd()
+{
+ static unsigned trand = 0;
+ trand = 1664525u * trand + 1013904223u;
+ return (float) trand / 4294967296.0f;
+}
+
+
+// Create an offset surface from a mesh. Dumb - just moves along the
+// normal by the given distance, making no attempt to avoid self-intersection.
+// Eventually, this could/should be extended to use the method in
+// Peng, J., Kristjansson, D., and Zorin, D.
+// "Interactive Modeling of Topologically Complex Geometric Detail"
+// Proc. SIGGRAPH, 2004.
+void inflate(TriMesh *mesh, float amount)
+{
+ mesh->need_normals();
+
+ TriMesh::dprintf("Creating offset surface... ");
+ int nv = mesh->vertices.size();
+#pragma omp parallel for
+ for (int i = 0; i < nv; i++)
+ mesh->vertices[i] += amount * mesh->normals[i];
+ TriMesh::dprintf("Done.\n");
+ mesh->bbox.valid = false;
+ mesh->bsphere.valid = false;
+}
+
+
+// Transform the mesh by the given matrix
+void apply_xform(TriMesh *mesh, const xform &xf)
+{
+ int nv = mesh->vertices.size();
+ for (int i = 0; i < nv; i++)
+ mesh->vertices[i] = xf * mesh->vertices[i];
+ if (!mesh->normals.empty()) {
+ xform nxf = norm_xf(xf);
+ for (int i = 0; i < nv; i++) {
+ mesh->normals[i] = nxf * mesh->normals[i];
+ normalize(mesh->normals[i]);
+ }
+ }
+}
+
+
+// Translate the mesh
+void trans(TriMesh *mesh, const vec &transvec)
+{
+ apply_xform(mesh, xform::trans(transvec));
+}
+
+
+// Rotate the mesh by r radians
+void rot(TriMesh *mesh, float r, const vec &axis)
+{
+ apply_xform(mesh, xform::rot(r, axis));
+}
+
+
+// Scale the mesh - isotropic
+void scale(TriMesh *mesh, float s)
+{
+ apply_xform(mesh, xform::scale(s));
+}
+
+
+// Scale the mesh - anisotropic in X, Y, Z
+void scale(TriMesh *mesh, float sx, float sy, float sz)
+{
+ apply_xform(mesh, xform::scale(sx, sy, sz));
+}
+
+
+// Scale the mesh - anisotropic in an arbitrary direction
+void scale(TriMesh *mesh, float s, const vec &d)
+{
+ apply_xform(mesh, xform::scale(s, d));
+}
+
+
+// Clip mesh to the given bounding box
+void clip(TriMesh *mesh, const TriMesh::BBox &b)
+{
+ int nv = mesh->vertices.size();
+ vector<bool> toremove(nv, false);
+ for (int i = 0; i < nv; i++)
+ if (mesh->vertices[i][0] < b.min[0] ||
+ mesh->vertices[i][0] > b.max[0] ||
+ mesh->vertices[i][1] < b.min[1] ||
+ mesh->vertices[i][1] > b.max[1] ||
+ mesh->vertices[i][2] < b.min[2] ||
+ mesh->vertices[i][2] > b.max[2])
+ toremove[i] = true;
+
+ remove_vertices(mesh, toremove);
+}
+
+
+// Find center of mass of a bunch of points
+point point_center_of_mass(const vector<point> &pts)
+{
+ point com = accumulate(pts.begin(), pts.end(), point());
+ return com / (float) pts.size();
+}
+
+
+// Find (area-weighted) center of mass of a mesh
+point mesh_center_of_mass(TriMesh *mesh)
+{
+ if (mesh->faces.empty() && mesh->tstrips.empty())
+ return point_center_of_mass(mesh->vertices);
+
+ point com;
+ float totwt = 0;
+
+ mesh->need_faces();
+ int nf = mesh->faces.size();
+ for (int i = 0; i < nf; i++) {
+ const point &v0 = mesh->vertices[mesh->faces[i][0]];
+ const point &v1 = mesh->vertices[mesh->faces[i][1]];
+ const point &v2 = mesh->vertices[mesh->faces[i][2]];
+
+ point face_com = (v0+v1+v2) / 3.0f;
+ float wt = len(trinorm(v0,v1,v2));
+ com += wt * face_com;
+ totwt += wt;
+ }
+ return com / totwt;
+}
+
+
+// Compute covariance of a bunch of points
+void point_covariance(const vector<point> &pts, float C[3][3])
+{
+ for (int j = 0; j < 3; j++)
+ for (int k = 0; k < 3; k++)
+ C[j][k] = 0.0f;
+
+ int n = pts.size();
+ for (int i = 0; i < n; i++) {
+ for (int j = 0; j < 3; j++)
+ for (int k = j; k < 3; k++)
+ C[j][k] += pts[i][j] * pts[i][k];
+ }
+
+ for (int j = 0; j < 3; j++)
+ for (int k = j; k < 3; k++)
+ C[j][k] /= pts.size();
+
+ C[1][0] = C[0][1];
+ C[2][0] = C[0][2];
+ C[2][1] = C[1][2];
+}
+
+
+// Compute covariance of faces (area-weighted) in a mesh
+void mesh_covariance(TriMesh *mesh, float C[3][3])
+{
+ if (mesh->faces.empty() && mesh->tstrips.empty()) {
+ point_covariance(mesh->vertices, C);
+ return;
+ }
+
+ mesh->need_faces();
+
+ for (int j = 0; j < 3; j++)
+ for (int k = 0; k < 3; k++)
+ C[j][k] = 0.0f;
+
+ float totarea = 0.0f;
+ const vector<point> &p = mesh->vertices;
+ int n = mesh->faces.size();
+ for (int i = 0; i < n; i++) {
+ const TriMesh::Face &f = mesh->faces[i];
+ point c = (p[f[0]] + p[f[1]] + p[f[2]]) / 3.0f;
+ float area = len(trinorm(p[f[0]], p[f[1]], p[f[2]]));
+ totarea += area;
+
+ // Covariance of triangle relative to centroid
+ float vweight = area / 12.0f;
+ for (int v = 0; v < 3; v++) {
+ point pc = p[f[v]] - c;
+ for (int j = 0; j < 3; j++)
+ for (int k = j; k < 3; k++)
+ C[j][k] += vweight * pc[j] * pc[k];
+ }
+
+ // Covariance of centroid
+ for (int j = 0; j < 3; j++)
+ for (int k = j; k < 3; k++)
+ C[j][k] += area * c[j] * c[k];
+ }
+
+ for (int j = 0; j < 3; j++)
+ for (int k = j; k < 3; k++)
+ C[j][k] /= totarea;
+
+ C[1][0] = C[0][1];
+ C[2][0] = C[0][2];
+ C[2][1] = C[1][2];
+}
+
+
+// Scale the mesh so that mean squared distance from center of mass is 1
+void normalize_variance(TriMesh *mesh)
+{
+ point com = mesh_center_of_mass(mesh);
+ trans(mesh, -com);
+
+ float C[3][3];
+ mesh_covariance(mesh, C);
+
+ float s = 1.0f / sqrt(C[0][0] + C[1][1] + C[2][2]);
+ scale(mesh, s);
+
+ trans(mesh, com);
+}
+
+
+// Rotate model so that first principal axis is along +X (using
+// forward weighting), and the second is along +Y
+void pca_rotate(TriMesh *mesh)
+{
+ point com = mesh_center_of_mass(mesh);
+ trans(mesh, -com);
+
+ float C[3][3];
+ mesh_covariance(mesh, C);
+ float e[3];
+ eigdc<float,3>(C, e);
+
+ // Sorted in order from smallest to largest, so grab third column
+ vec first(C[0][2], C[1][2], C[2][2]);
+ int npos = 0;
+ int nv = mesh->vertices.size();
+ for (int i = 0; i < nv; i++)
+ if ((mesh->vertices[i] DOT first) > 0.0f)
+ npos++;
+ if (npos < nv/2)
+ first = -first;
+
+ vec second(C[0][1], C[1][1], C[2][1]);
+ npos = 0;
+ for (int i = 0; i < nv; i++)
+ if ((mesh->vertices[i] DOT second) > 0.0f)
+ npos++;
+ if (npos < nv/2)
+ second = -second;
+
+ vec third = first CROSS second;
+
+ xform xf;
+ xf[0] = first[0]; xf[1] = first[1]; xf[2] = first[2];
+ xf[4] = second[0]; xf[5] = second[1]; xf[6] = second[2];
+ xf[8] = third[0]; xf[9] = third[1]; xf[10] = third[2];
+
+ invert(xf);
+ apply_xform(mesh, xf);
+
+ trans(mesh, com);
+}
+
+
+// As above, but only rotate by 90/180/etc. degrees w.r.t. original
+void pca_snap(TriMesh *mesh)
+{
+ point com = mesh_center_of_mass(mesh);
+ trans(mesh, -com);
+
+ float C[3][3];
+ mesh_covariance(mesh, C);
+ float e[3];
+ eigdc<float,3>(C, e);
+
+ // Sorted in order from smallest to largest, so grab third column
+ vec first(C[0][2], C[1][2], C[2][2]);
+ int npos = 0;
+ int nv = mesh->vertices.size();
+ for (int i = 0; i < nv; i++)
+ if ((mesh->vertices[i] DOT first) > 0.0f)
+ npos++;
+ if (npos < nv/2)
+ first = -first;
+ if (fabs(first[0]) > fabs(first[1])) {
+ if (fabs(first[0]) > fabs(first[2])) {
+ first[1] = first[2] = 0;
+ first[0] /= fabs(first[0]);
+ } else {
+ first[0] = first[1] = 0;
+ first[2] /= fabs(first[2]);
+ }
+ } else {
+ if (fabs(first[1]) > fabs(first[2])) {
+ first[0] = first[2] = 0;
+ first[1] /= fabs(first[1]);
+ } else {
+ first[0] = first[1] = 0;
+ first[2] /= fabs(first[2]);
+ }
+ }
+
+ vec second(C[0][1], C[1][1], C[2][1]);
+ npos = 0;
+ for (int i = 0; i < nv; i++)
+ if ((mesh->vertices[i] DOT second) > 0.0f)
+ npos++;
+ if (npos < nv/2)
+ second = -second;
+ second -= first * (first DOT second);
+ if (fabs(second[0]) > fabs(second[1])) {
+ if (fabs(second[0]) > fabs(second[2])) {
+ second[1] = second[2] = 0;
+ second[0] /= fabs(second[0]);
+ } else {
+ second[0] = second[1] = 0;
+ second[2] /= fabs(second[2]);
+ }
+ } else {
+ if (fabs(second[1]) > fabs(second[2])) {
+ second[0] = second[2] = 0;
+ second[1] /= fabs(second[1]);
+ } else {
+ second[0] = second[1] = 0;
+ second[2] /= fabs(second[2]);
+ }
+ }
+
+ vec third = first CROSS second;
+
+ xform xf;
+ xf[0] = first[0]; xf[1] = first[1]; xf[2] = first[2];
+ xf[4] = second[0]; xf[5] = second[1]; xf[6] = second[2];
+ xf[8] = third[0]; xf[9] = third[1]; xf[10] = third[2];
+
+ invert(xf);
+ apply_xform(mesh, xf);
+
+ trans(mesh, com);
+}
+
+
+// Helper function: return the largest X coord for this face
+static float max_x(const TriMesh *mesh, int i)
+{
+ return max(max(mesh->vertices[mesh->faces[i][0]][0],
+ mesh->vertices[mesh->faces[i][1]][0]),
+ mesh->vertices[mesh->faces[i][2]][0]);
+}
+
+
+// Flip faces so that orientation among touching faces is consistent
+void orient(TriMesh *mesh)
+{
+ mesh->need_faces();
+ mesh->tstrips.clear();
+ mesh->need_adjacentfaces();
+
+ mesh->flags.clear();
+ const unsigned NONE = ~0u;
+ mesh->flags.resize(mesh->faces.size(), NONE);
+
+ TriMesh::dprintf("Auto-orienting mesh... ");
+ unsigned cc = 0;
+ vector<int> cc_farthest;
+ for (int i = 0; i < mesh->faces.size(); i++) {
+ if (mesh->flags[i] != NONE)
+ continue;
+ mesh->flags[i] = cc;
+ cc_farthest.push_back(i);
+ float farthest_val = max_x(mesh, i);
+
+ vector<int> q;
+ q.push_back(i);
+ while (!q.empty()) {
+ int f = q.back();
+ q.pop_back();
+ for (int j = 0; j < 3; j++) {
+ int v0 = mesh->faces[f][j];
+ int v1 = mesh->faces[f][(j+1)%3];
+ const vector<int> &a = mesh->adjacentfaces[v0];
+ for (int k = 0; k < a.size(); k++) {
+ int f1 = a[k];
+ if (mesh->flags[f1] != NONE)
+ continue;
+ int i0 = mesh->faces[f1].indexof(v0);
+ int i1 = mesh->faces[f1].indexof(v1);
+ if (i0 < 0 || i1 < 0)
+ continue;
+ if (i1 == (i0 + 1) % 3)
+ swap(mesh->faces[f1][1],
+ mesh->faces[f1][2]);
+ mesh->flags[f1] = cc;
+ if (max_x(mesh, f1) > farthest_val) {
+ farthest_val = max_x(mesh, f1);
+ cc_farthest[cc] = f1;
+ }
+ q.push_back(f1);
+ }
+ }
+ }
+ cc++;
+ }
+
+ vector<bool> cc_flip(cc, false);
+ for (int i = 0; i < cc; i++) {
+ int f = cc_farthest[i];
+ const point &v0 = mesh->vertices[mesh->faces[f][0]];
+ const point &v1 = mesh->vertices[mesh->faces[f][1]];
+ const point &v2 = mesh->vertices[mesh->faces[f][2]];
+ int j = 0;
+ if (v1[0] > v0[0])
+ if (v2[0] > v1[0]) j = 2; else j = 1;
+ else
+ if (v2[0] > v0[0]) j = 2;
+ int v = mesh->faces[f][j];
+ const vector<int> &a = mesh->adjacentfaces[v];
+ vec n;
+ for (int k = 0; k < a.size(); k++) {
+ int f1 = a[k];
+ const point &v0 = mesh->vertices[mesh->faces[f1][0]];
+ const point &v1 = mesh->vertices[mesh->faces[f1][1]];
+ const point &v2 = mesh->vertices[mesh->faces[f1][2]];
+ n += trinorm(v0, v1, v2);
+ }
+ if (n[0] < 0.0f)
+ cc_flip[i] = true;
+ }
+
+ for (int i = 0; i < mesh->faces.size(); i++) {
+ if (cc_flip[mesh->flags[i]])
+ swap(mesh->faces[i][1], mesh->faces[i][2]);
+ }
+ TriMesh::dprintf("Done.\n");
+}
+
+
+// Remove boundary vertices (and faces that touch them)
+void erode(TriMesh *mesh)
+{
+ int nv = mesh->vertices.size();
+ vector<bool> bdy(nv);
+ for (int i = 0; i < nv; i++)
+ bdy[i] = mesh->is_bdy(i);
+ remove_vertices(mesh, bdy);
+}
+
+
+// Add a bit of noise to the mesh
+void noisify(TriMesh *mesh, float amount)
+{
+ mesh->need_normals();
+ mesh->need_neighbors();
+ int nv = mesh->vertices.size();
+ vector<vec> disp(nv);
+
+ for (int i = 0; i < nv; i++) {
+ point &v = mesh->vertices[i];
+ // Tangential
+ for (int j = 0; j < mesh->neighbors[i].size(); j++) {
+ const point &n = mesh->vertices[mesh->neighbors[i][j]];
+ float scale = amount / (amount + len(n-v));
+ disp[i] += (float) tinyrnd() * scale * (n-v);
+ }
+ if (mesh->neighbors[i].size())
+ disp[i] /= (float) mesh->neighbors[i].size();
+ // Normal
+ disp[i] += (2.0f * (float) tinyrnd() - 1.0f) *
+ amount * mesh->normals[i];
+ }
+ for (int i = 0; i < nv; i++)
+ mesh->vertices[i] += disp[i];
+}
+
Index: external/trimesh/libsrc/diffuse.cc
--- external/trimesh/libsrc/diffuse.cc (revision 0)
+++ external/trimesh/libsrc/diffuse.cc (revision 0)
@@ -0,0 +1,353 @@
+/*
+Szymon Rusinkiewicz
+Princeton University
+
+diffuse.cc
+Smoothing of meshes and per-vertex fields
+*/
+
+#include <stdio.h>
+#include "TriMesh.h"
+#include "TriMesh_algo.h"
+#include "timestamp.h"
+#include <cmath>
+using namespace std;
+
+
+// Approximation to Gaussian... Used in filtering
+static inline float wt(const point &p1, const point &p2, float invsigma2)
+{
+ float d2 = invsigma2 * dist2(p1, p2);
+ return (d2 >= 9.0f) ? 0.0f : exp(-0.5f*d2);
+ //return (d2 >= 25.0f) ? 0.0f : exp(-0.5f*d2);
+}
+static inline float wt(const TriMesh *themesh, int v1, int v2, float invsigma2)
+{
+ return wt(themesh->vertices[v1], themesh->vertices[v2], invsigma2);
+}
+
+
+// Functor classes for adding vector or tensor fields on the surface
+struct AccumVec {
+ const vector<vec> &field;
+ AccumVec(const vector<vec> &field_) : field(field_)
+ {}
+ void operator() (const TriMesh *themesh, int v0, vec &f,
+ float w, int v)
+ {
+ f += w * field[v];
+ }
+};
+
+struct AccumCurv {
+ void operator() (const TriMesh *themesh, int v0, vec &c,
+ float w, int v)
+ {
+ vec ncurv;
+ proj_curv(themesh->pdir1[v], themesh->pdir2[v],
+ themesh->curv1[v], 0, themesh->curv2[v],
+ themesh->pdir1[v0], themesh->pdir2[v0],
+ ncurv[0], ncurv[1], ncurv[2]);
+ c += w * ncurv;
+ }
+};
+
+struct AccumDCurv {
+ void operator() (const TriMesh *themesh, int v0, Vec<4> &d,
+ float w, int v)
+ {
+ Vec<4> ndcurv;
+ proj_dcurv(themesh->pdir1[v], themesh->pdir2[v],
+ themesh->dcurv[v],
+ themesh->pdir1[v0], themesh->pdir2[v0],
+ ndcurv);
+ d += w * ndcurv;
+ }
+};
+
+
+// Diffuse a vector field at 1 vertex, weighted by
+// a Gaussian of width 1/sqrt(invsigma2)
+template <class ACCUM, class T>
+static void diffuse_vert_field(TriMesh *themesh, ACCUM accum,
+ int v, float invsigma2, T &flt)
+{
+ if (themesh->neighbors[v].empty()) {
+ flt = T();
+ accum(themesh, v, flt, 1.0f, v);
+ return;
+ }
+
+ flt = T();
+ accum(themesh, v, flt, themesh->pointareas[v], v);
+ float sum_w = themesh->pointareas[v];
+ const vec &nv = themesh->normals[v];
+
+ unsigned &flag = themesh->flag_curr;
+ flag++;
+ themesh->flags[v] = flag;
+ vector<int> boundary = themesh->neighbors[v];
+ while (!boundary.empty()) {
+ int n = boundary.back();
+ boundary.pop_back();
+ if (themesh->flags[n] == flag)
+ continue;
+ themesh->flags[n] = flag;
+ if ((nv DOT themesh->normals[n]) <= 0.0f)
+ continue;
+ // Gaussian weight
+ float w = wt(themesh, n, v, invsigma2);
+ if (w == 0.0f)
+ continue;
+ // Downweight things pointing in different directions
+ w *= nv DOT themesh->normals[n];
+ // Surface area "belonging" to each point
+ w *= themesh->pointareas[n];
+ // Accumulate weight times field at neighbor
+ accum(themesh, v, flt, w, n);
+ sum_w += w;
+ for (int i = 0; i < themesh->neighbors[n].size(); i++) {
+ int nn = themesh->neighbors[n][i];
+ if (themesh->flags[nn] == flag)
+ continue;
+ boundary.push_back(nn);
+ }
+ }
+ flt /= sum_w;
+}
+
+
+// Smooth the mesh geometry.
+// XXX - this is perhaps not a great way to do this,
+// but it seems to work better than most other things I've tried...
+void smooth_mesh(TriMesh *themesh, float sigma)
+{
+ themesh->need_faces();
+ diffuse_normals(themesh, 0.5f * sigma);
+ int nv = themesh->vertices.size();
+
+ TriMesh::dprintf("\rSmoothing... ");
+ timestamp t = now();
+
+ float invsigma2 = 1.0f / sqr(sigma);
+
+ vector<point> dflt(nv);
+ for (int i = 0; i < nv; i++) {
+ diffuse_vert_field(themesh, AccumVec(themesh->vertices),
+ i, invsigma2, dflt[i]);
+ // Just keep the displacement
+ dflt[i] -= themesh->vertices[i];
+ }
+
+ // Slightly better small-neighborhood approximation
+ int nf = themesh->faces.size();
+#pragma omp parallel for
+ for (int i = 0; i < nf; i++) {
+ point c = themesh->vertices[themesh->faces[i][0]] +
+ themesh->vertices[themesh->faces[i][1]] +
+ themesh->vertices[themesh->faces[i][2]];
+ c /= 3.0f;
+ for (int j = 0; j < 3; j++) {
+ int v = themesh->faces[i][j];
+ vec d = 0.5f * (c - themesh->vertices[v]);
+ dflt[v] += themesh->cornerareas[i][j] /
+ themesh->pointareas[themesh->faces[i][j]] *
+ exp(-0.5f * invsigma2 * len2(d)) * d;
+ }
+ }
+
+ // Filter displacement field
+ vector<point> dflt2(nv);
+ for (int i = 0; i < nv; i++) {
+ diffuse_vert_field(themesh, AccumVec(dflt),
+ i, invsigma2, dflt2[i]);
+ }
+
+ // Update vertex positions
+#pragma omp parallel for
+ for (int i = 0; i < nv; i++)
+ themesh->vertices[i] += dflt[i] - dflt2[i]; // second Laplacian
+
+ TriMesh::dprintf("Done. Filtering took %f sec.\n", now() - t);
+}
+
+
+// Filter a vertex using the method of [Jones et al. 2003]
+// For pass 1, do simple smoothing and write to mpoints
+// For pass 2, do bilateral, using mpoints, and write to themesh->vertices
+static void jones_filter(TriMesh *themesh, int v,
+ float invsigma2_1, float invsigma2_2, bool pass1,
+ vector<point> &mpoints)
+{
+ const point &p = pass1 ? themesh->vertices[v] : mpoints[v];
+ point &flt = pass1 ? mpoints[v] : themesh->vertices[v];
+
+ flt = point();
+ float sum_w = 0.0f;
+
+ unsigned &flag = themesh->flag_curr;
+ flag++;
+ vector<int> boundary = themesh->adjacentfaces[v];
+ while (!boundary.empty()) {
+ int f = boundary.back();
+ boundary.pop_back();
+ if (themesh->flags[f] == flag)
+ continue;
+ themesh->flags[f] = flag;
+
+ int v0 = themesh->faces[f][0];
+ int v1 = themesh->faces[f][1];
+ int v2 = themesh->faces[f][2];
+ const point &p0 = themesh->vertices[v0];
+ const point &p1 = themesh->vertices[v1];
+ const point &p2 = themesh->vertices[v2];
+ point c = (p0 + p1 + p2) * (1.0f / 3.0f);
+
+ float w = wt(p, c, invsigma2_1);
+ if (w == 0.0f)
+ continue;
+ w *= len(trinorm(p0, p1, p2));
+
+ if (pass1) {
+ flt += w * c;
+ sum_w += w;
+ } else {
+ vec fn = trinorm(mpoints[v0], mpoints[v1], mpoints[v2]);
+ normalize(fn);
+ point prediction = p - fn * ((p - c) DOT fn);
+ w *= wt(p, prediction, invsigma2_2);
+ if (w == 0.0f)
+ continue;
+ flt += w * prediction;
+ sum_w += w;
+ }
+
+ for (int i = 0; i < 3; i++) {
+ int ae = themesh->across_edge[f][i];
+ if (ae < 0 || themesh->flags[ae] == flag)
+ continue;
+ boundary.push_back(ae);
+ }
+ }
+ if (sum_w == 0.0f)
+ flt = p;
+ else
+ flt *= 1.0f / sum_w;
+}
+
+
+// Bilateral smoothing using the method of [Jones et al. 2003]
+void bilateral_smooth_mesh(TriMesh *themesh, float sigma1, float sigma2)
+{
+ themesh->need_faces();
+ themesh->need_adjacentfaces();
+ themesh->need_across_edge();
+ int nv = themesh->vertices.size(), nf = themesh->faces.size();
+ if (themesh->flags.size() != nf)
+ themesh->flags.resize(nf);
+
+ TriMesh::dprintf("\rSmoothing... ");
+ timestamp t = now();
+
+ float sigma3 = 0.5f * sigma1;
+ float invsigma2_1 = 1.0f / sqr(sigma1);
+ float invsigma2_2 = 1.0f / sqr(sigma2);
+ float invsigma2_3 = 1.0f / sqr(sigma3);
+
+ // Pass I: mollification
+ vector<point> mpoints(nv);
+ for (int i = 0; i < nv; i++)
+ jones_filter(themesh, i, invsigma2_3, 0.0f, true, mpoints);
+
+ // Pass II: bilateral
+ for (int i = 0; i < nv; i++)
+ jones_filter(themesh, i, invsigma2_1, invsigma2_2, false, mpoints);
+
+ TriMesh::dprintf("Done. Filtering took %f sec.\n", now() - t);
+}
+
+
+// Diffuse the normals across the mesh
+void diffuse_normals(TriMesh *themesh, float sigma)
+{
+ themesh->need_normals();
+ themesh->need_pointareas();
+ themesh->need_neighbors();
+ int nv = themesh->vertices.size();
+ if (themesh->flags.size() != nv)
+ themesh->flags.resize(nv);
+
+ TriMesh::dprintf("\rSmoothing normals... ");
+ timestamp t = now();
+
+ float invsigma2 = 1.0f / sqr(sigma);
+
+ vector<vec> nflt(nv);
+ for (int i = 0; i < nv; i++) {
+ diffuse_vert_field(themesh, AccumVec(themesh->normals),
+ i, invsigma2, nflt[i]);
+ normalize(nflt[i]);
+ }
+
+ themesh->normals = nflt;
+
+ TriMesh::dprintf("Done. Filtering took %f sec.\n", now() - t);
+}
+
+
+// Diffuse the curvatures across the mesh
+void diffuse_curv(TriMesh *themesh, float sigma)
+{
+ themesh->need_normals();
+ themesh->need_pointareas();
+ themesh->need_curvatures();
+ themesh->need_neighbors();
+ int nv = themesh->vertices.size();
+ if (themesh->flags.size() != nv)
+ themesh->flags.resize(nv);
+
+ TriMesh::dprintf("\rSmoothing curvatures... ");
+ timestamp t = now();
+
+ float invsigma2 = 1.0f / sqr(sigma);
+
+ vector<vec> cflt(nv);
+ for (int i = 0; i < nv; i++)
+ diffuse_vert_field(themesh, AccumCurv(), i, invsigma2, cflt[i]);
+#pragma omp parallel for
+ for (int i = 0; i < nv; i++)
+ diagonalize_curv(themesh->pdir1[i], themesh->pdir2[i],
+ cflt[i][0], cflt[i][1], cflt[i][2],
+ themesh->normals[i],
+ themesh->pdir1[i], themesh->pdir2[i],
+ themesh->curv1[i], themesh->curv2[i]);
+
+ TriMesh::dprintf("Done. Filtering took %f sec.\n", now() - t);
+}
+
+
+// Diffuse the curvature derivatives across the mesh
+void diffuse_dcurv(TriMesh *themesh, float sigma)
+{
+ themesh->need_normals();
+ themesh->need_pointareas();
+ themesh->need_curvatures();
+ themesh->need_dcurv();
+ themesh->need_neighbors();
+ int nv = themesh->vertices.size();
+ if (themesh->flags.size() != nv)
+ themesh->flags.resize(nv);
+
+ TriMesh::dprintf("\rSmoothing curvature derivatives... ");
+ timestamp t = now();
+
+ float invsigma2 = 1.0f / sqr(sigma);
+
+ vector< Vec<4> > dflt(nv);
+ for (int i = 0; i < nv; i++)
+ diffuse_vert_field(themesh, AccumDCurv(), i, invsigma2, dflt[i]);
+
+ themesh->dcurv = dflt;
+ TriMesh::dprintf("Done. Filtering took %f sec.\n", now() - t);
+}
+
Index: external/trimesh/libsrc/reorder_verts.cc
--- external/trimesh/libsrc/reorder_verts.cc (revision 0)
+++ external/trimesh/libsrc/reorder_verts.cc (revision 0)
@@ -0,0 +1,210 @@
+/*
+Szymon Rusinkiewicz
+Princeton University
+
+reorder_verts.cc
+Reorder and remap vertices.
+*/
+
+#include <stdio.h>
+#include "TriMesh.h"
+#include "TriMesh_algo.h"
+#include <vector>
+
+
+// Remap vertices according to the given table
+//
+// Faces are renumbered to reflect the new numbering of vertices, and any
+// faces that included a vertex that went away will also be removed.
+//
+// Any per-vertex properties are renumbered along with the vertices.
+void remap_verts(TriMesh *mesh, const std::vector<int> &remap_table)
+{
+ int nv = mesh->vertices.size();
+ if (remap_table.size() != nv) {
+ fprintf(stderr, "remap_verts called with wrong table size!\n");
+ return;
+ }
+
+ // Check what we're doing
+ bool removing_any = false;
+ int last = -1;
+ for (int i = 0; i < nv; i++) {
+ if (remap_table[i] < 0)
+ removing_any = true;
+ else if (remap_table[i] > last)
+ last = remap_table[i];
+ }
+
+ // Figure out what we have sitting around, so we can remap/recompute
+ bool have_faces = !mesh->faces.empty();
+ bool have_tstrips = !mesh->tstrips.empty();
+ bool have_grid = !mesh->grid.empty();
+ if (have_grid && removing_any)
+ mesh->faces.clear();
+ if (removing_any)
+ mesh->tstrips.clear();
+
+ bool have_col = !mesh->colors.empty();
+ bool have_conf = !mesh->confidences.empty();
+ bool have_flags = !mesh->flags.empty();
+ bool have_normals = !mesh->normals.empty();
+ bool have_pdir1 = !mesh->pdir1.empty();
+ bool have_pdir2 = !mesh->pdir2.empty();
+ bool have_curv1 = !mesh->curv1.empty();
+ bool have_curv2 = !mesh->curv2.empty();
+ bool have_dcurv = !mesh->dcurv.empty();
+
+ // Remap the vertices and per-vertex properties
+ TriMesh *oldmesh = new TriMesh;
+ *oldmesh = *mesh;
+
+#define REMAP(property) mesh->property[remap_table[i]] = oldmesh->property[i]
+ for (int i = 0; i < nv; i++) {
+ if (remap_table[i] < 0 || remap_table[i] == i)
+ continue;
+ REMAP(vertices);
+ if (have_col) REMAP(colors);
+ if (have_conf) REMAP(confidences);
+ if (have_flags) REMAP(flags);
+ if (have_normals) REMAP(normals);
+ if (have_pdir1) REMAP(pdir1);
+ if (have_pdir2) REMAP(pdir2);
+ if (have_curv1) REMAP(curv1);
+ if (have_curv2) REMAP(curv2);
+ if (have_dcurv) REMAP(dcurv);
+ }
+
+#define ERASE(property) mesh->property.erase(mesh->property.begin()+last+1, \
+ mesh->property.end())
+ ERASE(vertices);
+ if (have_col) ERASE(colors);
+ if (have_conf) ERASE(confidences);
+ if (have_flags) ERASE(flags);
+ if (have_normals) ERASE(normals);
+ if (have_pdir1) ERASE(pdir1);
+ if (have_pdir2) ERASE(pdir2);
+ if (have_curv1) ERASE(curv1);
+ if (have_curv2) ERASE(curv2);
+ if (have_dcurv) ERASE(dcurv);
+
+ // Renumber faces
+ int nextface = 0;
+ for (int i = 0; i < mesh->faces.size(); i++) {
+ int n0 = (mesh->faces[nextface][0] = remap_table[oldmesh->faces[i][0]]);
+ int n1 = (mesh->faces[nextface][1] = remap_table[oldmesh->faces[i][1]]);
+ int n2 = (mesh->faces[nextface][2] = remap_table[oldmesh->faces[i][2]]);
+ if ((n0 != -1) && (n1 != -1) && (n2 != -1))
+ nextface++;
+ }
+ mesh->faces.erase(mesh->faces.begin() + nextface, mesh->faces.end());
+
+ // Renumber grid
+ if (have_grid) {
+ for (int i = 0; i < mesh->grid.size(); i++) {
+ if (mesh->grid[i] >= 0)
+ mesh->grid[i] = remap_table[oldmesh->grid[i]];
+ }
+ if (have_faces && mesh->faces.empty())
+ mesh->need_faces();
+ }
+
+ // Renumber or recompute tstrips
+ if (have_tstrips && mesh->tstrips.empty()) {
+ // Removing vertices: recompute tstrips
+ mesh->need_tstrips();
+ } else if (have_tstrips) {
+ // Just shuffling vertices: keep tstrips and renumber
+ oldmesh->convert_strips(TriMesh::TSTRIP_TERM);
+ for (int i = 0; i < mesh->tstrips.size(); i++) {
+ if (oldmesh->tstrips[i] < 0)
+ mesh->tstrips[i] = -1;
+ else
+ mesh->tstrips[i] = remap_table[oldmesh->tstrips[i]];
+ }
+ mesh->convert_strips(TriMesh::TSTRIP_LENGTH);
+ }
+
+ // Recompute whatever needs recomputing...
+ if (!mesh->pointareas.empty() || !mesh->cornerareas.empty()) {
+ mesh->pointareas.clear();
+ mesh->cornerareas.clear();
+ mesh->need_pointareas();
+ }
+ if (mesh->bbox.valid) {
+ mesh->bbox.valid = false;
+ mesh->need_bbox();
+ }
+ if (mesh->bsphere.valid) {
+ mesh->bsphere.valid = false;
+ mesh->need_bsphere();
+ }
+ if (!mesh->neighbors.empty()) {
+ mesh->neighbors.clear();
+ mesh->need_neighbors();
+ }
+ if (!mesh->adjacentfaces.empty()) {
+ mesh->adjacentfaces.clear();
+ mesh->need_adjacentfaces();
+ }
+ if (!mesh->across_edge.empty()) {
+ mesh->across_edge.clear();
+ mesh->need_across_edge();
+ }
+
+ if (!have_faces)
+ mesh->faces.clear();
+
+ delete oldmesh;
+}
+
+
+// Reorder vertices in a mesh according to the order in which
+// they are referenced by the grid, tstrips, or faces.
+void reorder_verts(TriMesh *mesh)
+{
+ TriMesh::dprintf("Reordering vertices... ");
+
+ int nv = mesh->vertices.size();
+ vector<int> remap(nv, -1);
+ int next = 0;
+ if (!mesh->grid.empty()) {
+ for (int i = 0; i < mesh->grid.size(); i++) {
+ int v = mesh->grid[i];
+ if (v == -1)
+ continue;
+ if (remap[v] == -1)
+ remap[v] = next++;
+ }
+ } else if (!mesh->tstrips.empty()) {
+ mesh->convert_strips(TriMesh::TSTRIP_TERM);
+ for (int i = 0; i < mesh->tstrips.size(); i++) {
+ int v = mesh->tstrips[i];
+ if (v == -1)
+ continue;
+ if (remap[v] == -1)
+ remap[v] = next++;
+ }
+ mesh->convert_strips(TriMesh::TSTRIP_LENGTH);
+ } else {
+ for (int i = 0; i < mesh->faces.size(); i++) {
+ for (int j = 0; j < 3; j++) {
+ int v = mesh->faces[i][j];
+ if (remap[v] == -1)
+ remap[v] = next++;
+ }
+ }
+ }
+
+ if (next != nv) {
+ // Unreferenced vertices... Just stick them at the end.
+ for (int i = 0; i < nv; i++)
+ if (remap[i] == -1)
+ remap[i] = next++;
+ }
+
+ remap_verts(mesh, remap);
+
+ TriMesh::dprintf("Done.\n");
+}
+
Index: external/trimesh/libsrc/mesh_view.cc
--- external/trimesh/libsrc/mesh_view.cc (revision 0)
+++ external/trimesh/libsrc/mesh_view.cc (revision 0)
@@ -0,0 +1,599 @@
+/*
+Szymon Rusinkiewicz
+Princeton University
+
+mesh_view.cc
+Simple viewer
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "TriMesh.h"
+#include "XForm.h"
+#include "GLCamera.h"
+#include "ICP.h"
+#include <GL/glut.h>
+#include <string>
+using std::string;
+
+
+// Globals
+vector<TriMesh *> meshes;
+vector<xform> xforms;
+vector<bool> visible;
+vector<string> xffilenames;
+
+TriMesh::BSphere global_bsph;
+xform global_xf;
+GLCamera camera;
+
+int current_mesh = -1;
+
+bool draw_edges = false;
+bool draw_2side = false;
+bool draw_shiny = true;
+bool draw_lit = true;
+bool draw_falsecolor = false;
+bool draw_index = false;
+bool white_bg = false;
+
+
+// Make some mesh current
+void set_current(int i)
+{
+ if (i >= 0 && i < meshes.size() && visible[i])
+ current_mesh = i;
+ else
+ current_mesh = -1;
+ camera.stopspin();
+}
+
+
+// Change visiblility of a mesh
+void toggle_vis(int i)
+{
+ if (i >= 0 && i < meshes.size())
+ visible[i] = !visible[i];
+ if (current_mesh == i && !visible[i])
+ set_current(-1);
+}
+
+
+// Signal a redraw
+void need_redraw()
+{
+ glutPostRedisplay();
+}
+
+
+// Clear the screen
+void cls()
+{
+ glDisable(GL_DITHER);
+ glDisable(GL_BLEND);
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_NORMALIZE);
+ glDisable(GL_LIGHTING);
+ glDisable(GL_NORMALIZE);
+ glDisable(GL_COLOR_MATERIAL);
+ if (white_bg)
+ glClearColor(1, 1, 1, 0);
+ else
+ glClearColor(0.08, 0.08, 0.08, 0);
+ glClearDepth(1);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+}
+
+
+// Set up lights and materials
+void setup_lighting(int id)
+{
+ Color c(1.0f);
+ if (draw_falsecolor)
+ c = Color::hsv(-3.88 * id, 0.6 + 0.2 * sin(0.42 * id), 1.0);
+ glColor3fv(c);
+
+ if (!draw_lit || meshes[id]->normals.empty()) {
+ glDisable(GL_LIGHTING);
+ return;
+ }
+
+ GLfloat mat_specular[4] = { 0.18, 0.18, 0.18, 0.18 };
+ if (!draw_shiny) {
+ mat_specular[0] = mat_specular[1] =
+ mat_specular[2] = mat_specular[3] = 0.0f;
+ }
+ GLfloat mat_shininess[] = { 64 };
+ GLfloat global_ambient[] = { 0.02, 0.02, 0.05, 0.05 };
+ GLfloat light0_ambient[] = { 0, 0, 0, 0 };
+ GLfloat light0_diffuse[] = { 0.85, 0.85, 0.8, 0.85 };
+ if (current_mesh >= 0 && id != current_mesh) {
+ light0_diffuse[0] *= 0.5f;
+ light0_diffuse[1] *= 0.5f;
+ light0_diffuse[2] *= 0.5f;
+ }
+ GLfloat light1_diffuse[] = { -0.01, -0.01, -0.03, -0.03 };
+ GLfloat light0_specular[] = { 0.85, 0.85, 0.85, 0.85 };
+ glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
+ glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient);
+ glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
+ glLightfv(GL_LIGHT0, GL_SPECULAR, light0_specular);
+ glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_diffuse);
+ glLightModelfv(GL_LIGHT_MODEL_AMBIENT, global_ambient);
+ glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_FALSE);
+ glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, draw_2side);
+ glEnable(GL_LIGHTING);
+ glEnable(GL_LIGHT0);
+ glEnable(GL_LIGHT1);
+ glEnable(GL_COLOR_MATERIAL);
+ glEnable(GL_NORMALIZE);
+}
+
+
+// Draw triangle strips. They are stored as length followed by values.
+void draw_tstrips(const TriMesh *themesh)
+{
+ const int *t = &themesh->tstrips[0];
+ const int *end = t + themesh->tstrips.size();
+ while (likely(t < end)) {
+ int striplen = *t++;
+ glDrawElements(GL_TRIANGLE_STRIP, striplen, GL_UNSIGNED_INT, t);
+ t += striplen;
+ }
+}
+
+
+// Draw the mesh
+void draw_mesh(int i)
+{
+ const TriMesh *themesh = meshes[i];
+
+ glPushMatrix();
+ glMultMatrixd(xforms[i]);
+
+ glDepthFunc(GL_LESS);
+ glEnable(GL_DEPTH_TEST);
+
+ if (draw_2side) {
+ glDisable(GL_CULL_FACE);
+ } else {
+ glCullFace(GL_BACK);
+ glEnable(GL_CULL_FACE);
+ }
+
+ // Vertices
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(3, GL_FLOAT,
+ sizeof(themesh->vertices[0]),
+ &themesh->vertices[0][0]);
+
+ // Normals
+ if (!themesh->normals.empty() && !draw_index) {
+ glEnableClientState(GL_NORMAL_ARRAY);
+ glNormalPointer(GL_FLOAT,
+ sizeof(themesh->normals[0]),
+ &themesh->normals[0][0]);
+ } else {
+ glDisableClientState(GL_NORMAL_ARRAY);
+ }
+
+ // Colors
+ if (!themesh->colors.empty() && !draw_falsecolor && !draw_index) {
+ glEnableClientState(GL_COLOR_ARRAY);
+ glColorPointer(3, GL_FLOAT,
+ sizeof(themesh->colors[0]),
+ &themesh->colors[0][0]);
+ } else {
+ glDisableClientState(GL_COLOR_ARRAY);
+ }
+
+ // Main drawing pass
+ if (themesh->tstrips.empty()) {
+ // No triangles - draw as points
+ glPointSize(1);
+ glDrawArrays(GL_POINTS, 0, themesh->vertices.size());
+ glPopMatrix();
+ return;
+ }
+
+ if (draw_edges) {
+ glPolygonOffset(10.0f, 10.0f);
+ glEnable(GL_POLYGON_OFFSET_FILL);
+ }
+
+ draw_tstrips(themesh);
+ glDisable(GL_POLYGON_OFFSET_FILL);
+
+ // Edge drawing pass
+ if (draw_edges) {
+ glPolygonMode(GL_FRONT, GL_LINE);
+ glDisableClientState(GL_COLOR_ARRAY);
+ glDisable(GL_COLOR_MATERIAL);
+ GLfloat global_ambient[] = { 0.2, 0.2, 0.2, 1.0 };
+ GLfloat light0_diffuse[] = { 0.8, 0.8, 0.8, 0.0 };
+ GLfloat light1_diffuse[] = { -0.2, -0.2, -0.2, 0.0 };
+ GLfloat light0_specular[] = { 0.0f, 0.0f, 0.0f, 0.0f };
+ glLightModelfv(GL_LIGHT_MODEL_AMBIENT, global_ambient);
+ glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
+ glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_diffuse);
+ glLightfv(GL_LIGHT0, GL_SPECULAR, light0_specular);
+ GLfloat mat_diffuse[4] = { 0.0f, 0.0f, 1.0f, 1.0f };
+ glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_diffuse);
+ glColor3f(0, 0, 1); // Used iff unlit
+ draw_tstrips(themesh);
+ glPolygonMode(GL_FRONT, GL_FILL);
+ }
+
+ glPopMatrix();
+}
+
+
+// Draw the scene
+void redraw()
+{
+ timestamp t = now();
+ camera.setupGL(global_xf * global_bsph.center, global_bsph.r);
+ glPushMatrix();
+ glMultMatrixd(global_xf);
+ cls();
+ for (int i = 0; i < meshes.size(); i++) {
+ if (!visible[i])
+ continue;
+ setup_lighting(i);
+ draw_mesh(i);
+ }
+
+ glPopMatrix();
+ glutSwapBuffers();
+ printf("\r \r%.1f msec.", 1000.0f * (now() - t));
+ fflush(stdout);
+}
+
+
+// Update global bounding sphere.
+void update_bsph()
+{
+ point boxmin(1e38, 1e38, 1e38);
+ point boxmax(-1e38, -1e38, -1e38);
+ bool some_vis = false;
+ for (int i = 0; i < meshes.size(); i++) {
+ if (!visible[i])
+ continue;
+ some_vis = true;
+ point c = xforms[i] * meshes[i]->bsphere.center;
+ float r = meshes[i]->bsphere.r;
+ for (int j = 0; j < 3; j++) {
+ boxmin[j] = min(boxmin[j], c[j]-r);
+ boxmax[j] = max(boxmax[j], c[j]+r);
+ }
+ }
+ if (!some_vis)
+ return;
+ point &gc = global_bsph.center;
+ float &gr = global_bsph.r;
+ gc = 0.5f * (boxmin + boxmax);
+ gr = 0.0f;
+ for (int i = 0; i < meshes.size(); i++) {
+ if (!visible[i])
+ continue;
+ point c = xforms[i] * meshes[i]->bsphere.center;
+ float r = meshes[i]->bsphere.r;
+ gr = max(gr, dist(c, gc) + r);
+ }
+}
+
+
+// Set the view...
+void resetview()
+{
+ camera.stopspin();
+ for (int i = 0; i < meshes.size(); i++)
+ if (!xforms[i].read(xffilenames[i]))
+ xforms[i] = xform();
+ update_bsph();
+ global_xf = xform::trans(0, 0, -5.0f * global_bsph.r) *
+ xform::trans(-global_bsph.center);
+
+ // Special case for 1 mesh
+ if (meshes.size() == 1 && xforms[0].read(xffilenames[0])) {
+ global_xf = xforms[0];
+ xforms[0] = xform();
+ }
+}
+
+
+// Save the current image to a PPM file.
+// Uses the next available filename matching filenamepattern
+void dump_image()
+{
+ // Find first non-used filename
+ const char filenamepattern[] = "img%d.ppm";
+ int imgnum = 0;
+ FILE *f;
+ while (1) {
+ char filename[1024];
+ sprintf(filename, filenamepattern, imgnum++);
+ f = fopen(filename, "rb");
+ if (!f) {
+ f = fopen(filename, "wb");
+ printf("\n\nSaving image %s... ", filename);
+ fflush(stdout);
+ break;
+ }
+ fclose(f);
+ }
+
+ // Read pixels
+ GLint V[4];
+ glGetIntegerv(GL_VIEWPORT, V);
+ GLint width = V[2], height = V[3];
+ char *buf = new char[width*height*3];
+ glPixelStorei(GL_PACK_ALIGNMENT, 1);
+ glReadPixels(V[0], V[1], width, height, GL_RGB, GL_UNSIGNED_BYTE, buf);
+
+ // Flip top-to-bottom
+ for (int i = 0; i < height/2; i++) {
+ char *row1 = buf + 3 * width * i;
+ char *row2 = buf + 3 * width * (height - 1 - i);
+ for (int j = 0; j < 3 * width; j++)
+ swap(row1[j], row2[j]);
+ }
+
+ // Write out file
+ fprintf(f, "P6\n#\n%d %d\n255\n", width, height);
+ fwrite(buf, width*height*3, 1, f);
+ fclose(f);
+ delete [] buf;
+
+ printf("Done.\n\n");
+}
+
+
+// Save all transforms
+void save_xforms()
+{
+ if (xforms.size() == 1) {
+ printf("Writing %s\n", xffilenames[0].c_str());
+ global_xf.write(xffilenames[0]);
+ return;
+ }
+ for (int i = 0; i < xforms.size(); i++) {
+ printf("Writing %s\n", xffilenames[i].c_str());
+ xforms[i].write(xffilenames[i]);
+ }
+}
+
+
+// ICP
+void do_icp(int n)
+{
+ camera.stopspin();
+
+ if (current_mesh < 0 || current_mesh >= meshes.size())
+ return;
+ if (n < 0 || n >= meshes.size())
+ return;
+ if (!visible[n] || !visible[current_mesh] || n == current_mesh)
+ return;
+ ICP(meshes[n], meshes[current_mesh], xforms[n], xforms[current_mesh], 2);
+ update_bsph();
+ need_redraw();
+}
+
+
+// Handle mouse button and motion events
+static unsigned buttonstate = 0;
+
+void doubleclick(int button, int x, int y)
+{
+ // Render and read back ID reference image
+ camera.setupGL(global_xf * global_bsph.center, global_bsph.r);
+ glDisable(GL_BLEND);
+ glDisable(GL_LIGHTING);
+ glClearColor(1,1,1,1);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glEnable(GL_DEPTH_TEST);
+ draw_index = true;
+ glPushMatrix();
+ glMultMatrixd(global_xf);
+ for (int i = 0; i < meshes.size(); i++) {
+ if (!visible[i])
+ continue;
+ glColor3ub((i >> 16) & 0xff,
+ (i >> 8) & 0xff,
+ i & 0xff);
+ draw_mesh(i);
+ }
+ glPopMatrix();
+ draw_index = false;
+ GLint V[4];
+ glGetIntegerv(GL_VIEWPORT, V);
+ y = int(V[1] + V[3]) - 1 - y;
+ unsigned char pix[3];
+ glReadPixels(x, y, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, pix);
+ int n = (pix[0] << 16) + (pix[1] << 8) + pix[2];
+
+ if (button == 0 || buttonstate == (1 << 0)) {
+ // Double left click - select a mesh
+ set_current(n);
+ } else if (button == 2 || buttonstate == (1 << 2)) {
+ // Double right click - ICP current to clicked-on
+ do_icp(n);
+ }
+}
+
+void mousemotionfunc(int x, int y)
+{
+ static const Mouse::button physical_to_logical_map[] = {
+ Mouse::NONE, Mouse::ROTATE, Mouse::MOVEXY, Mouse::MOVEZ,
+ Mouse::MOVEZ, Mouse::MOVEXY, Mouse::MOVEXY, Mouse::MOVEXY,
+ };
+
+ Mouse::button b = Mouse::NONE;
+ if (buttonstate & (1 << 3))
+ b = Mouse::WHEELUP;
+ else if (buttonstate & (1 << 4))
+ b = Mouse::WHEELDOWN;
+ else if (buttonstate & (1 << 30))
+ b = Mouse::LIGHT;
+ else
+ b = physical_to_logical_map[buttonstate & 7];
+
+ if (current_mesh < 0) {
+ camera.mouse(x, y, b,
+ global_xf * global_bsph.center, global_bsph.r,
+ global_xf);
+ } else {
+ xform tmp_xf = global_xf * xforms[current_mesh];
+ camera.mouse(x, y, b,
+ tmp_xf * meshes[current_mesh]->bsphere.center,
+ meshes[current_mesh]->bsphere.r,
+ tmp_xf);
+ xforms[current_mesh] = inv(global_xf) * tmp_xf;
+ update_bsph();
+ }
+ if (b != Mouse::NONE)
+ need_redraw();
+}
+
+void mousebuttonfunc(int button, int state, int x, int y)
+{
+ static timestamp last_click_time;
+ static unsigned last_click_buttonstate = 0;
+ static float doubleclick_threshold = 0.25f;
+
+ if (glutGetModifiers() & GLUT_ACTIVE_CTRL)
+ buttonstate |= (1 << 30);
+ else
+ buttonstate &= ~(1 << 30);
+
+ if (state == GLUT_DOWN) {
+ buttonstate |= (1 << button);
+ if (buttonstate == last_click_buttonstate &&
+ now() - last_click_time < doubleclick_threshold) {
+ doubleclick(button, x, y);
+ last_click_buttonstate = 0;
+ } else {
+ last_click_time = now();
+ last_click_buttonstate = buttonstate;
+ }
+ } else {
+ buttonstate &= ~(1 << button);
+ }
+
+ mousemotionfunc(x, y);
+}
+
+
+// Idle callback
+void idle()
+{
+ xform tmp_xf = global_xf;
+ if (current_mesh >= 0)
+ tmp_xf = global_xf * xforms[current_mesh];
+
+ if (camera.autospin(tmp_xf))
+ need_redraw();
+ else
+ usleep(10000);
+
+ if (current_mesh >= 0) {
+ xforms[current_mesh] = inv(global_xf) * tmp_xf;
+ update_bsph();
+ } else {
+ global_xf = tmp_xf;
+ }
+}
+
+
+// Keyboard
+#define Ctrl (1-'a')
+void keyboardfunc(unsigned char key, int x, int y)
+{
+ switch (key) {
+ case ' ':
+ if (current_mesh < 0)
+ resetview();
+ else
+ set_current(-1);
+ break;
+ case '@': // Shift-2
+ draw_2side = !draw_2side; break;
+ case 'e':
+ draw_edges = !draw_edges; break;
+ case 'f':
+ draw_falsecolor = !draw_falsecolor; break;
+ case 'l':
+ draw_lit = !draw_lit; break;
+ case 's':
+ draw_shiny = !draw_shiny; break;
+ case 'w':
+ white_bg = !white_bg; break;
+ case 'I':
+ dump_image(); break;
+ case Ctrl+'x':
+ save_xforms();
+ break;
+ case '\033': // Esc
+ case Ctrl+'q':
+ case 'Q':
+ case 'q':
+ exit(0);
+ default:
+ if (key >= '1' && key <= '9') {
+ int m = key - '1';
+ toggle_vis(m);
+ }
+ }
+ need_redraw();
+}
+
+
+void usage(const char *myname)
+{
+ fprintf(stderr, "Usage: %s infile...\n", myname);
+ exit(1);
+}
+
+int main(int argc, char *argv[])
+{
+ glutInitWindowSize(512, 512);
+ glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
+ glutInit(&argc, argv);
+
+ if (argc < 2)
+ usage(argv[0]);
+
+ for (int i = 1; i < argc; i++) {
+ const char *filename = argv[i];
+ TriMesh *themesh = TriMesh::read(filename);
+ if (!themesh)
+ usage(argv[0]);
+ themesh->need_normals();
+ themesh->need_tstrips();
+ themesh->need_bsphere();
+ meshes.push_back(themesh);
+
+ string xffilename = xfname(filename);
+ xffilenames.push_back(xffilename);
+printf("%s %s\n", filename, xffilename.c_str());
+
+ xforms.push_back(xform());
+ visible.push_back(true);
+ }
+
+ glutCreateWindow(argv[1]);
+ glutDisplayFunc(redraw);
+ glutMouseFunc(mousebuttonfunc);
+ glutMotionFunc(mousemotionfunc);
+ glutKeyboardFunc(keyboardfunc);
+ glutIdleFunc(idle);
+
+ resetview();
+
+ glutMainLoop();
+}
+
Index: external/trimesh/libsrc/TriMesh_stats.cc
--- external/trimesh/libsrc/TriMesh_stats.cc (revision 0)
+++ external/trimesh/libsrc/TriMesh_stats.cc (revision 0)
@@ -0,0 +1,46 @@
+/*
+Szymon Rusinkiewicz
+Princeton University
+
+TriMesh_stats.cc
+Computation of various statistics on the mesh.
+*/
+
+#include "TriMesh.h"
+#include <algorithm>
+using namespace std;
+
+
+// A characteristic "feature size" for the mesh. Computed as an approximation
+// to the median edge length
+float TriMesh::feature_size()
+{
+ need_faces();
+ if (faces.empty())
+ return 0.0f;
+
+ int nf = faces.size();
+ int nsamp = min(nf / 2, 333);
+
+ vector<float> samples;
+ samples.reserve(nsamp * 3);
+
+ for (int i = 0; i < nsamp; i++) {
+ // Quick 'n dirty portable random number generator
+ static unsigned randq = 0;
+ randq = unsigned(1664525) * randq + unsigned(1013904223);
+
+ int ind = randq % nf;
+ const point &p0 = vertices[faces[ind][0]];
+ const point &p1 = vertices[faces[ind][1]];
+ const point &p2 = vertices[faces[ind][2]];
+ samples.push_back(dist2(p0,p1));
+ samples.push_back(dist2(p1,p2));
+ samples.push_back(dist2(p2,p0));
+ }
+ nth_element(samples.begin(),
+ samples.begin() + samples.size()/2,
+ samples.end());
+ return sqrt(samples[samples.size()/2]);
+}
+
Index: external/trimesh/libsrc/Makefile
--- external/trimesh/libsrc/Makefile (revision 0)
+++ external/trimesh/libsrc/Makefile (revision 0)
@@ -0,0 +1,45 @@
+# DEBUG = y
+MAKERULESDIR = ..
+DESTDIR = ../lib.$(UNAME)
+INCLUDES = -I../include
+
+include $(MAKERULESDIR)/Makerules
+
+CCFILES = TriMesh_bounding.cc \
+ TriMesh_connectivity.cc \
+ TriMesh_curvature.cc \
+ TriMesh_io.cc \
+ TriMesh_grid.cc \
+ TriMesh_normals.cc \
+ TriMesh_pointareas.cc \
+ TriMesh_stats.cc \
+ TriMesh_tstrips.cc \
+ GLCamera.cc \
+ ICP.cc \
+ KDtree.cc \
+ diffuse.cc \
+ edgeflip.cc \
+ faceflip.cc \
+ filter.cc \
+ lmsmooth.cc \
+ remove.cc \
+ reorder_verts.cc \
+ subdiv.cc
+
+
+OFILES = $(addprefix $(OBJDIR)/,$(CCFILES:.cc=.o))
+LIB = $(DESTDIR)/libtrimesh.a
+default: $(LIB)
+
+$(LIB): $(OFILES)
+ $(STATICLIB)
+
+clean:
+ -rm -f $(OFILES) $(OBJDIR)/Makedepend $(OBJDIR)/*.d
+ -rm -rf $(OBJDIR)/ii_files
+ -rmdir $(OBJDIR)
+
+spotless: clean
+ -rm -f $(LIB)
+ -rmdir $(DESTDIR)
+
Index: external/README
--- external/README (revision 0)
+++ external/README (revision 0)
@@ -0,0 +1,60 @@
+External dependencies -*- outline -*-
+
+This directory contains external dependencies of Olena, integrated
+into the source tree for convenience purpose.
+
+
+* trimesh/
+http://www.cs.princeton.edu/gfx/proj/trimesh2/src/trimesh2-2.8.tar.gz
+
+The trimesh2 library and tool from Szymon Rusinkiewicz (Princeton
+University), distributed under the GNU General Public License (GPL),
+version 2.
+
+http://www.cs.princeton.edu/gfx/proj/trimesh2/
+
+According to the author, ``The various libraries distributed with
+trimesh2 are open source, and are believed to be covered by
+GPL-compatible licenses. Please see the COPYING file.''
+
+This version of trimesh2 shipped with Olena no longer contains the
+following files and directories:
+
+ bin.Linux/
+ mesh_align
+ mesh_cat
+ mesh_cc
+ mesh_filter
+ mesh_make
+ mesh_shade
+ mesh_view
+ bin.Linux64/
+ mesh_align
+ mesh_cat
+ mesh_cc
+ mesh_filter
+ mesh_make
+ mesh_shade
+ mesh_view
+ bin.Win32/
+ mesh_align.exe
+ mesh_cat.exe
+ mesh_cc.exe
+ mesh_filter.exe
+ mesh_make.exe
+ mesh_shade.exe
+ mesh_view.exe
+ lib.Linux/
+ libgluit.a
+ libtrimesh.a
+ lib.Linux64/
+ libgluit.a
+ libtrimesh.a
+ lib.Win32/
+ libgluit.a
+ libtrimesh.a
+
+
+Local Variables:
+ispell-local-dictionary: "american"
+End: