2041: Add the trimesh2 library (version 2.8) as an external dependency.

https://svn.lrde.epita.fr/svn/oln/trunk Index: ChangeLog from Roland Levillain <roland@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@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@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@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@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@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@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@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@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@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@sourceforge.net>, 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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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:
participants (1)
-
Roland Levillain