From 29f6d05875e5dd48fe0e7d6f9849d97f3dedfb1d Mon Sep 17 00:00:00 2001 From: curt Date: Mon, 5 Apr 1999 21:32:32 +0000 Subject: [PATCH] Initial revision --- Docs/Autopilot/AltitudeHold.tex | 3 + Docs/Autopilot/HeadingHold.tex | 3 + Docs/CVSROOT/checkoutlist | 13 - Docs/CVSROOT/commitinfo | 15 - Docs/CVSROOT/config | 6 - Docs/CVSROOT/cvswrappers | 23 - Docs/CVSROOT/editinfo | 21 - Docs/CVSROOT/loginfo | 26 - Docs/CVSROOT/modules | 26 - Docs/CVSROOT/notify | 12 - Docs/CVSROOT/rcsinfo | 13 - Docs/CVSROOT/taginfo | 20 - Docs/CVSROOT/verifymsg | 21 - Docs/CoordinateSystem/old-coord.fig | 27 - Docs/{ => FDM}/LaRCsim/LaRCsim-notes.tex | 0 Docs/{ => FDM}/LaRCsim/LaRCsim-vars.tex | 0 .../LaRCsim/LaRCsim_generics_v_1.4.xls | Bin Docs/{ => FDM}/LaRCsim/manual.ps.gz | Bin Docs/{ => FDM}/LaRCsim/manual.tex.gz | Bin Docs/{ => InstallGuide}/HTML/arizona.gif | Bin Docs/{ => InstallGuide}/HTML/getstart.html | 0 Docs/{ => InstallGuide}/HTML/hud.gif | Bin Docs/{ => InstallGuide}/HTML/navion.gif | Bin Docs/{ => InstallGuide}/HTML/start.gif | Bin Docs/{ => InstallGuide}/PDF/getstart.pdf | Bin Docs/{ => InstallGuide}/SOURCE/arizona.eps | 0 Docs/{ => InstallGuide}/SOURCE/building.tex | 0 Docs/{ => InstallGuide}/SOURCE/flight.tex | 0 Docs/{ => InstallGuide}/SOURCE/free.tex | 0 Docs/{ => InstallGuide}/SOURCE/getstart.tex | 0 Docs/{ => InstallGuide}/SOURCE/hud.eps | 0 Docs/{ => InstallGuide}/SOURCE/index.tex | 0 Docs/{ => InstallGuide}/SOURCE/landing.tex | 0 Docs/{ => InstallGuide}/SOURCE/missed.tex | 0 Docs/{ => InstallGuide}/SOURCE/navion.eps | 0 Docs/{ => InstallGuide}/SOURCE/opengl.tex | 0 Docs/{ => InstallGuide}/SOURCE/prefligh.tex | 0 Docs/{ => InstallGuide}/SOURCE/start.eps | 0 Docs/{ => InstallGuide}/SOURCE/takeoff.tex | 0 Docs/{ => InstallGuide}/SOURCE/title.tex | 0 Docs/Misc/Features | 14 + Docs/Portability/fgfs-portability-guide.tex | 142 + Docs/{ => Scenery}/Astro/Stars.info | 0 Docs/{ => Scenery}/Astro/Stars.tex | 3 + .../CoordinateSystem/CoordinateSystem.tex | 0 Docs/{ => Scenery}/CoordinateSystem/coord.fig | 0 .../CoordinateSystem/geodesy.fig | 0 Docs/Scenery/DEM.info | 3 + Docs/Scenery/DLG/dlg3sdts.wp.gz | Bin 0 -> 30962 bytes Docs/Scenery/DLG/dug-2.wp6.gz | Bin 0 -> 61975 bytes Docs/Scenery/OBJ.format.txt | 3013 +++++++++++++++++ .../SceneGeneration/SceneryGeneration.tex | 3 + Docs/{ => Scenery}/SceneGeneration/ref.fig | 0 Docs/Scenery/SceneGeneration/terrain.outline | 50 + Docs/{ => Scenery}/SceneGeneration/trap.fig | 0 Docs/{ => Scenery}/Sky/Sky.tex | 3 + Docs/{ => Scenery}/Sky/dome.fig | 0 Docs/{ => Scenery}/Sky/earth.fig | 0 Docs/{ => Scenery}/Sky/local.fig | 0 Docs/Time/Events/Events.tex | 152 + Hints/aaa | 306 ++ Hints/endian-ness | 71 + Hints/gamma | 186 + Hints/joystick | 73 + Hints/lights.c | 288 ++ Hints/mip-mapping | 118 + Hints/nmea | 101 + Hints/opengl-optimization | 60 + Hints/polygon-offset | 269 ++ Hints/portable-sound | 331 ++ Hints/scene-graph | 85 + Hints/stl-gcc-redhat | 153 + Hints/strips-vs-fans | 251 ++ Hints/texturing | 1073 ++++++ Hints/tile-gaps | 72 + Hints/timezone | 67 + Hints/view-frustum-culling | 986 ++++++ Hints/view-projection | 86 + Hints/win32-time-funcs | 112 + Include/auto_ptr.hxx | 3 + Include/cmdargs.h | 3 + Include/compiler.h | 3 + Include/fg_callback.hxx | 3 + Include/fg_constants.h | 3 + Include/fg_memory.h | 3 + Include/fg_typedefs.h | 3 + Include/fg_zlib.h | 7 +- Include/general.hxx | 3 + Lib/Audio/CHANGES | 139 - Lib/Audio/Makefile.am | 1 - Lib/Audio/NOTICE | 9 - Lib/Audio/README | 9 - Lib/Audio/README.freebsd | 13 - Lib/Audio/README.linux | 13 - Lib/Audio/README.openbsd | 13 - Lib/Audio/README.sgi | 27 - Lib/Audio/README.unix | 20 - Lib/Audio/README.win | 15 - Lib/Bucket/newbucket.cxx | 3 + Lib/Bucket/newbucket.hxx | 3 + Lib/CVSROOT/checkoutlist | 13 - Lib/CVSROOT/commitinfo | 15 - Lib/CVSROOT/cvswrappers | 22 - Lib/CVSROOT/editinfo | 21 - Lib/CVSROOT/loginfo | 19 - Lib/CVSROOT/modules | 26 - Lib/CVSROOT/notify | 12 - Lib/CVSROOT/rcsinfo | 13 - Lib/CVSROOT/taginfo | 20 - Lib/Debug/fg_debug.c | 7 +- Lib/Debug/logstream.cxx | 3 + Lib/Debug/logstream.hxx | 3 + Lib/{Lib => }/Makefile.am | 0 Lib/Math/fg_geodesy.cxx | 6 + Lib/Math/fg_geodesy.hxx | 6 + Lib/Math/fg_random.c | 3 + Lib/Math/fg_random.h | 3 + Lib/Math/geotest.c | 30 + Lib/Math/interpolater.cxx | 3 + Lib/Math/interpolater.hxx | 3 + Lib/Math/inttest.cxx | 23 + Lib/Math/leastsqs.cxx | 3 + Lib/Math/leastsqs.hxx | 3 + Lib/Math/point3d.hxx | 3 + Lib/Math/polar3d.cxx | 3 + Lib/Math/polar3d.hxx | 3 + Lib/Math/vector.cxx | 3 + Lib/Math/vector.hxx | 3 + Lib/Misc/fgstream.cxx | 3 + Lib/Misc/fgstream.hxx | 3 + Lib/Misc/stopwatch.hxx | 3 + Lib/Misc/strutils.cxx | 3 + Lib/Misc/strutils.hxx | 3 + Lib/Misc/zfstream.cxx | 3 + Lib/Misc/zfstream.hxx | 3 + Lib/PUI/Makefile.am | 24 - Lib/PUI/complex.cxx | 332 -- Lib/PUI/pu.cxx | 332 -- Lib/PUI/pu.h | 805 ----- Lib/PUI/puBox.cxx | 319 -- Lib/PUI/puButton.cxx | 61 - Lib/PUI/puButtonBox.cxx | 100 - Lib/PUI/puDialogBox.cxx | 4 - Lib/PUI/puFrame.cxx | 30 - Lib/PUI/puInput.cxx | 226 -- Lib/PUI/puInterface.cxx | 268 -- Lib/PUI/puLocal.h | 19 - Lib/PUI/puMenuBar.cxx | 83 - Lib/PUI/puObject.cxx | 222 -- Lib/PUI/puOneShot.cxx | 9 - Lib/PUI/puPopup.cxx | 3 - Lib/PUI/puPopupMenu.cxx | 175 - Lib/PUI/puSlider.cxx | 107 - Lib/PUI/puText.cxx | 8 - Lib/Serial/serial.cxx | 3 + Lib/Serial/serial.hxx | 3 + Lib/example/Makefile.am | 17 - Lib/example/example.cxx | 89 - Lib/src/Makefile.am | 10 - Lib/src/sl.h | 629 ---- Lib/src/slDSP.cxx | 669 ---- Lib/src/slEnvelope.cxx | 170 - Lib/src/slPortability.h | 71 - Lib/src/slSample.cxx | 505 --- Lib/src/slSamplePlayer.cxx | 188 - Lib/src/slScheduler.cxx | 253 -- Lib/src/sm.h | 89 - Lib/src/smMixer.cxx | 256 -- Lib/zlib/ChangeLog | 471 --- Lib/zlib/INDEX | 86 - Lib/zlib/Makefile.am | 31 - Lib/zlib/README | 148 - Lib/zlib/adler32.c | 48 - Lib/zlib/algorithm.txt | 213 -- Lib/zlib/compress.c | 68 - Lib/zlib/crc32.c | 162 - Lib/zlib/deflate.c | 1350 -------- Lib/zlib/deflate.h | 318 -- Lib/zlib/descrip.mms | 48 - Lib/zlib/example.c | 556 --- Lib/zlib/gzio.c | 875 ----- Lib/zlib/infblock.c | 398 --- Lib/zlib/infblock.h | 39 - Lib/zlib/infcodes.c | 257 -- Lib/zlib/infcodes.h | 27 - Lib/zlib/inffast.c | 170 - Lib/zlib/inffast.h | 17 - Lib/zlib/inffixed.h | 151 - Lib/zlib/inflate.c | 366 -- Lib/zlib/inftrees.c | 455 --- Lib/zlib/inftrees.h | 58 - Lib/zlib/infutil.c | 87 - Lib/zlib/infutil.h | 98 - Lib/zlib/maketree.c | 85 - Lib/zlib/minigzip.c | 320 -- Lib/zlib/trees.c | 1214 ------- Lib/zlib/trees.h | 128 - Lib/zlib/uncompr.c | 58 - Lib/zlib/zconf.h | 279 -- Lib/zlib/zlib.3 | 107 - Lib/zlib/zlib.h | 893 ----- Lib/zlib/zutil.c | 225 -- Lib/zlib/zutil.h | 220 -- Makefile.am | 4 +- README.src | 58 + Simulator/Aircraft/aircraft.cxx | 3 + Simulator/Aircraft/aircraft.hxx | 3 + Simulator/Airports/genapt.cxx | 3 + Simulator/Airports/genapt.hxx | 3 + Simulator/Airports/old_draw_runways.c | 83 + Simulator/Airports/simple.cxx | 3 + Simulator/Airports/simple.hxx | 3 + Simulator/Airports/testair.cxx | 21 + Simulator/Astro/sky.cxx | 3 + Simulator/Astro/sky.hxx | 3 + Simulator/Astro/stars.cxx | 3 + Simulator/Astro/stars.hxx | 3 + Simulator/Autopilot/autopilot.cxx | 3 + Simulator/Autopilot/autopilot.hxx | 3 + Simulator/CVSROOT/checkoutlist | 13 - Simulator/CVSROOT/commitinfo | 15 - Simulator/CVSROOT/cvswrappers | 22 - Simulator/CVSROOT/editinfo | 21 - Simulator/CVSROOT/loginfo | 19 - Simulator/CVSROOT/modules | 26 - Simulator/CVSROOT/notify | 12 - Simulator/CVSROOT/rcsinfo | 13 - Simulator/CVSROOT/taginfo | 20 - Simulator/Cockpit/cockpit.cxx | 3 + Simulator/Cockpit/cockpit.hxx | 9 +- Simulator/Cockpit/hud.cxx | 3 + Simulator/Cockpit/hud.hxx | 3 + Simulator/Cockpit/panel.cxx | 3 + Simulator/Cockpit/panel.hxx | 3 + Simulator/Cockpit/proposed-navaids.hpp | 107 + Simulator/Controls/controls.cxx | 3 + Simulator/Controls/controls.hxx | 3 + Simulator/{Simulator => }/Done | 0 Simulator/{ => FDM}/External/Makefile.am | 0 Simulator/{ => FDM}/External/external.cxx | 3 + Simulator/{ => FDM}/External/external.hxx | 3 + Simulator/FDM/JSBsim.cxx | 3 + Simulator/FDM/JSBsim.hxx | 3 + Simulator/{ => FDM}/JSBsim/FGAircraft.cpp | 0 Simulator/{ => FDM}/JSBsim/FGAircraft.h | 0 Simulator/{ => FDM}/JSBsim/FGAtmosphere.cpp | 0 Simulator/{ => FDM}/JSBsim/FGAtmosphere.h | 0 Simulator/{ => FDM}/JSBsim/FGAuxiliary.cpp | 0 Simulator/{ => FDM}/JSBsim/FGAuxiliary.h | 0 Simulator/{ => FDM}/JSBsim/FGCoefficient.cpp | 0 Simulator/{ => FDM}/JSBsim/FGCoefficient.h | 0 Simulator/{ => FDM}/JSBsim/FGControls.cpp | 3 + Simulator/{ => FDM}/JSBsim/FGControls.h | 3 + Simulator/{ => FDM}/JSBsim/FGDefs.h | 0 Simulator/{ => FDM}/JSBsim/FGEngine.cpp | 0 Simulator/{ => FDM}/JSBsim/FGEngine.h | 0 Simulator/{ => FDM}/JSBsim/FGFCS.cpp | 0 Simulator/{ => FDM}/JSBsim/FGFCS.h | 0 Simulator/{ => FDM}/JSBsim/FGFDMExec.cpp | 0 Simulator/{ => FDM}/JSBsim/FGFDMExec.h | 0 Simulator/{ => FDM}/JSBsim/FGMain.cpp | 0 Simulator/{ => FDM}/JSBsim/FGMatrix.cpp | 0 Simulator/{ => FDM}/JSBsim/FGMatrix.h | 0 Simulator/{ => FDM}/JSBsim/FGModel.cpp | 0 Simulator/{ => FDM}/JSBsim/FGModel.h | 0 Simulator/{ => FDM}/JSBsim/FGOutput.cpp | 0 Simulator/{ => FDM}/JSBsim/FGOutput.h | 0 Simulator/{ => FDM}/JSBsim/FGPosition.cpp | 0 Simulator/{ => FDM}/JSBsim/FGPosition.h | 0 Simulator/{ => FDM}/JSBsim/FGRotation.cpp | 0 Simulator/{ => FDM}/JSBsim/FGRotation.h | 0 Simulator/{ => FDM}/JSBsim/FGState.cpp | 0 Simulator/{ => FDM}/JSBsim/FGState.h | 0 Simulator/{ => FDM}/JSBsim/FGTank.cpp | 0 Simulator/{ => FDM}/JSBsim/FGTank.h | 0 Simulator/{ => FDM}/JSBsim/FGTranslation.cpp | 0 Simulator/{ => FDM}/JSBsim/FGTranslation.h | 0 Simulator/{ => FDM}/JSBsim/FGUtility.cpp | 0 Simulator/{ => FDM}/JSBsim/FGUtility.h | 0 Simulator/{ => FDM}/JSBsim/Makefile.am | 0 Simulator/FDM/LaRCsim.cxx | 3 + Simulator/FDM/LaRCsim.hxx | 3 + Simulator/FDM/LaRCsim/Cherokee.txt | 60 + Simulator/{ => FDM}/LaRCsim/Makefile.am | 0 Simulator/{ => FDM}/LaRCsim/atmos_62.c | 0 Simulator/{ => FDM}/LaRCsim/atmos_62.h | 0 Simulator/FDM/LaRCsim/cherokee_aero.c | 170 + Simulator/FDM/LaRCsim/cherokee_engine.c | 104 + Simulator/FDM/LaRCsim/cherokee_gear.c | 314 ++ Simulator/FDM/LaRCsim/cherokee_init.c | 63 + .../LaRCsim/default_model_routines.c | 3 + .../LaRCsim/default_model_routines.h | 0 Simulator/{ => FDM}/LaRCsim/ls_accel.c | 3 + Simulator/{ => FDM}/LaRCsim/ls_accel.h | 0 Simulator/{ => FDM}/LaRCsim/ls_aux.c | 3 + Simulator/{ => FDM}/LaRCsim/ls_aux.h | 0 Simulator/{ => FDM}/LaRCsim/ls_cockpit.h | 3 + Simulator/{ => FDM}/LaRCsim/ls_constants.h | 0 Simulator/{ => FDM}/LaRCsim/ls_generic.h | 0 Simulator/{ => FDM}/LaRCsim/ls_geodesy.c | 3 + Simulator/{ => FDM}/LaRCsim/ls_geodesy.h | 0 Simulator/{ => FDM}/LaRCsim/ls_gravity.c | 3 + Simulator/{ => FDM}/LaRCsim/ls_gravity.h | 0 Simulator/{ => FDM}/LaRCsim/ls_init.c | 3 + Simulator/{ => FDM}/LaRCsim/ls_init.h | 0 Simulator/{ => FDM}/LaRCsim/ls_interface.c | 3 + Simulator/{ => FDM}/LaRCsim/ls_interface.h | 3 + Simulator/{ => FDM}/LaRCsim/ls_matrix.c | 3 + Simulator/{ => FDM}/LaRCsim/ls_matrix.h | 3 + Simulator/{ => FDM}/LaRCsim/ls_model.c | 3 + Simulator/{ => FDM}/LaRCsim/ls_model.h | 0 Simulator/{ => FDM}/LaRCsim/ls_sim_control.h | 3 + Simulator/{ => FDM}/LaRCsim/ls_step.c | 3 + Simulator/{ => FDM}/LaRCsim/ls_step.h | 0 Simulator/{ => FDM}/LaRCsim/ls_sym.h | 3 + Simulator/FDM/LaRCsim/ls_trim.c | 685 ++++ Simulator/{ => FDM}/LaRCsim/ls_types.h | 0 Simulator/{ => FDM}/LaRCsim/mymain.c | 0 Simulator/{ => FDM}/LaRCsim/navion_aero.c | 0 Simulator/{ => FDM}/LaRCsim/navion_engine.c | 0 Simulator/{ => FDM}/LaRCsim/navion_gear.c | 3 + Simulator/{ => FDM}/LaRCsim/navion_init.c | 0 Simulator/{ => FDM}/LaRCsim/navion_init.h | 0 Simulator/FDM/LaRCsim/on_ground.ic | 29 + Simulator/{ => FDM}/Slew/Makefile.am | 0 Simulator/{ => FDM}/Slew/slew.cxx | 3 + Simulator/{ => FDM}/Slew/slew.hxx | 3 + Simulator/FDM/flight.cxx | 3 + Simulator/FDM/flight.hxx | 3 + Simulator/Joystick/Makefile.am | 4 +- Simulator/Joystick/joystick.cxx | 3 + Simulator/Joystick/joystick.hxx | 3 + Simulator/Main/3dfx.sh | 34 + Simulator/Main/GLUTkey.cxx | 3 + Simulator/Main/GLUTkey.hxx | 3 + Simulator/Main/GLUTmain.cxx | 3 + Simulator/Main/fg_init.cxx | 3 + Simulator/Main/fg_init.hxx | 3 + Simulator/Main/fg_serial.cxx | 3 + Simulator/Main/fg_serial.hxx | 3 + Simulator/Main/mtest.c | 24 + Simulator/Main/options.cxx | 3 + Simulator/Main/options.hxx | 3 + Simulator/Main/runfgfs.in | 3 + Simulator/Main/splash.cxx | 3 + Simulator/Main/splash.hxx | 3 + Simulator/Main/ttest.cxx | 93 + Simulator/Main/views.cxx | 3 + Simulator/Main/views.hxx | 3 + Simulator/{Simulator => }/Makefile.am | 0 Simulator/Objects/fragment.cxx | 3 + Simulator/Objects/fragment.hxx | 3 + Simulator/Objects/material.cxx | 559 --- Simulator/Objects/material.hxx | 320 -- Simulator/Objects/obj.cxx | 3 + Simulator/Objects/obj.hxx | 3 + Simulator/Objects/texload.c | 273 -- Simulator/Objects/texload.h | 30 - Simulator/Scenery/design | 46 + Simulator/Scenery/maptest.cxx | 21 + Simulator/Scenery/scenery.cxx | 3 + Simulator/Scenery/scenery.hxx | 3 + Simulator/Scenery/test.cxx | 68 + Simulator/Scenery/tile.cxx | 3 + Simulator/Scenery/tile.hxx | 3 + Simulator/Scenery/tilecache.cxx | 3 + Simulator/Scenery/tilecache.hxx | 3 + Simulator/Scenery/tilemgr.cxx | 3 + Simulator/Scenery/tilemgr.hxx | 3 + Simulator/Time/event.cxx | 3 + Simulator/Time/event.hxx | 3 + Simulator/Time/fg_time.cxx | 3 + Simulator/Time/fg_time.hxx | 3 + Simulator/Time/fg_timer.cxx | 3 + Simulator/Time/fg_timer.hxx | 11 +- Simulator/Time/light.cxx | 3 + Simulator/Time/light.hxx | 3 + Simulator/Time/moonpos.cxx | 3 + Simulator/Time/sunpos.cxx | 3 + Simulator/Time/test_event.c | 38 + Simulator/Time/timestamp.hxx | 3 + Simulator/Time/ttest.c | 86 + Simulator/Time/win32test.c | 65 + Simulator/{Simulator => }/Todo | 0 Simulator/Weather/weather.cxx | 3 + Simulator/Weather/weather.hxx | 3 + Tools/Areas/Makefile.am | 3 + Tools/Areas/area.cxx | 3 + Tools/Areas/area.hxx | 3 + Tools/AssemTris/Makefile.am | 62 - Tools/AssemTris/assemtris.cxx | 600 ---- Tools/AssemTris/assemtris.hxx | 51 - Tools/CVSROOT/checkoutlist | 13 - Tools/CVSROOT/commitinfo | 15 - Tools/CVSROOT/cvswrappers | 22 - Tools/CVSROOT/editinfo | 21 - Tools/CVSROOT/loginfo | 19 - Tools/CVSROOT/modules | 26 - Tools/CVSROOT/notify | 12 - Tools/CVSROOT/rcsinfo | 13 - Tools/CVSROOT/taginfo | 20 - Tools/{ => Construct}/Array/Makefile.am | 0 Tools/{ => Construct}/Array/array.cxx | 3 + Tools/{ => Construct}/Array/array.hxx | 3 + Tools/{ => Construct}/Array/testarray.cxx | 0 Tools/{ => Construct}/Clipper/Makefile.am | 0 Tools/{ => Construct}/Clipper/clipper.cxx | 3 + Tools/{ => Construct}/Clipper/clipper.hxx | 3 + Tools/{ => Construct}/Clipper/testclipper.cxx | 3 + Tools/{ => Construct}/Combine/Makefile.am | 0 Tools/{ => Construct}/Combine/genfans.cxx | 3 + Tools/{ => Construct}/Combine/genfans.hxx | 3 + Tools/{ => Construct}/GenOutput/Makefile.am | 0 Tools/{ => Construct}/GenOutput/genobj.cxx | 3 + Tools/{ => Construct}/GenOutput/genobj.hxx | 3 + Tools/{ => Construct}/Main/Makefile.am | 0 .../{ => Construct}/Main/construct_types.hxx | 3 + Tools/{ => Construct}/Triangulate/Makefile.am | 0 .../{ => Construct}/Triangulate/triangle.cxx | 3 + .../{ => Construct}/Triangulate/triangle.hxx | 3 + Tools/{ => Construct}/Triangulate/trieles.cxx | 3 + Tools/{ => Construct}/Triangulate/trieles.hxx | 3 + .../{ => Construct}/Triangulate/trinodes.cxx | 3 + .../{ => Construct}/Triangulate/trinodes.hxx | 3 + Tools/{ => Construct}/Triangulate/tripoly.cxx | 3 + Tools/{ => Construct}/Triangulate/tripoly.hxx | 3 + Tools/{ => Construct}/Triangulate/trisegs.cxx | 3 + Tools/{ => Construct}/Triangulate/trisegs.hxx | 3 + Tools/FixNode/Makefile.am | 95 - Tools/FixNode/fixnode.cxx | 161 - Tools/FixNode/fixnode.hxx | 95 - Tools/FixNode/main.cxx | 146 - Tools/FixObj/Makefile.am | 69 - Tools/FixObj/main.cxx | 57 - Tools/FixObj/obj.cxx | 647 ---- Tools/FixObj/obj.hxx | 60 - Tools/{ => Lib}/DEM/Makefile.am | 0 Tools/{ => Lib}/DEM/dem.cxx | 3 + Tools/{ => Lib}/DEM/dem.hxx | 3 + Tools/{ => Lib}/Polygon/Makefile.am | 0 Tools/{ => Lib}/Polygon/index.cxx | 3 + Tools/{ => Lib}/Polygon/index.hxx | 3 + Tools/{ => Lib}/Polygon/names.cxx | 3 + Tools/{ => Lib}/Polygon/names.hxx | 3 + Tools/{ => Lib}/Triangle/A.poly | 0 Tools/{ => Lib}/Triangle/Makefile.am | 0 Tools/{ => Lib}/Triangle/README | 0 Tools/{ => Lib}/Triangle/showme.c | 0 Tools/{ => Lib}/Triangle/triangle.c | 0 Tools/{ => Lib}/Triangle/triangle.doc | 0 Tools/{ => Lib}/Triangle/triangle.h | 0 Tools/{ => Lib}/Triangle/tricall.c | 0 Tools/Main/construct.cxx | 373 -- Tools/{Tools => }/Makefile.am | 0 Tools/{ => Prep}/DemChop/Makefile.am | 3 + Tools/{ => Prep}/DemChop/demchop.cxx | 3 + Tools/{ => Prep}/DemChop/point2d.cxx | 3 + Tools/{ => Prep}/DemChop/point2d.hxx | 3 + Tools/{ => Prep}/DemInfo/Makefile.am | 3 + Tools/{ => Prep}/DemInfo/deminfo.cxx | 3 + Tools/{ => Prep}/DemInfo/gather-dem-info.pl | 3 + Tools/{ => Prep}/DemRaw2ascii/Makefile.am | 3 + Tools/{ => Prep}/DemRaw2ascii/main.c | 3 + Tools/{ => Prep}/DemRaw2ascii/rawdem.c | 3 + Tools/{ => Prep}/DemRaw2ascii/rawdem.h | 3 + Tools/{ => Prep}/GenAirports/Makefile.am | 3 + Tools/{ => Prep}/GenAirports/area.cxx | 3 + Tools/{ => Prep}/GenAirports/area.hxx | 3 + Tools/{ => Prep}/GenAirports/convex_hull.cxx | 3 + Tools/{ => Prep}/GenAirports/convex_hull.hxx | 3 + Tools/{ => Prep}/GenAirports/main.cxx | 3 + Tools/{ => Prep}/GenAirports/point2d.cxx | 3 + Tools/{ => Prep}/GenAirports/point2d.hxx | 3 + Tools/{ => Prep}/ShapeFile/Makefile.am | 0 Tools/{ => Prep}/ShapeFile/main.cxx | 3 + Tools/{ => Prep}/ShapeFile/shape.cxx | 3 + Tools/{ => Prep}/ShapeFile/shape.hxx | 3 + Tools/{Tools => }/README | 0 Tools/SplitTris/Makefile.am | 77 - Tools/SplitTris/splittris.cxx | 673 ---- Tools/SplitTris/splittris.hxx | 89 - Tools/Stripe_u/Makefile.am | 30 - Tools/Stripe_u/add.c | 386 --- Tools/Stripe_u/add.h | 25 - Tools/Stripe_u/bands.c | 549 --- Tools/Stripe_u/common.c | 811 ----- Tools/Stripe_u/common.h | 41 - Tools/Stripe_u/define.h | 13 - Tools/Stripe_u/extend.h | 17 - Tools/Stripe_u/free.c | 110 - Tools/Stripe_u/free.h | 22 - Tools/Stripe_u/global.h | 37 - Tools/Stripe_u/glove.h | 151 - Tools/Stripe_u/init.c | 217 -- Tools/Stripe_u/init.h | 30 - Tools/Stripe_u/local.c | 123 - Tools/Stripe_u/local.h | 19 - Tools/Stripe_u/my_global.h | 3 - Tools/Stripe_u/newpolve.c | 1667 --------- Tools/Stripe_u/options.c | 181 - Tools/Stripe_u/options.h | 17 - Tools/Stripe_u/output.c | 582 ---- Tools/Stripe_u/output.h | 26 - Tools/Stripe_u/outputex.c | 518 --- Tools/Stripe_u/outputex.h | 23 - Tools/Stripe_u/partial.c | 665 ---- Tools/Stripe_u/partial.h | 15 - Tools/Stripe_u/polverts.h | 87 - Tools/Stripe_u/polvertsex.h | 34 - Tools/Stripe_u/queue.c | 226 -- Tools/Stripe_u/queue.h | 283 -- Tools/Stripe_u/sgi_triang.c | 631 ---- Tools/Stripe_u/sgi_triangex.c | 584 ---- Tools/Stripe_u/struct.c | 549 --- Tools/Stripe_u/struct.h | 6 - Tools/Stripe_u/structex.c | 553 --- Tools/Stripe_u/sturcts.h | 31 - Tools/Stripe_u/sturctsex.h | 28 - Tools/Stripe_u/ties.c | 304 -- Tools/Stripe_u/ties.h | 15 - Tools/Stripe_u/triangulate.h | 23 - Tools/Stripe_u/triangulatex.h | 23 - Tools/Stripe_u/util.c | 272 -- Tools/Stripe_u/util.h | 24 - Tools/Stripe_w/Makefile.am | 27 - Tools/Stripe_w/add.c | 384 --- Tools/Stripe_w/add.h | 31 - Tools/Stripe_w/bands.c | 569 ---- Tools/Stripe_w/common.c | 810 ----- Tools/Stripe_w/common.h | 42 - Tools/Stripe_w/extend.h | 17 - Tools/Stripe_w/free.c | 112 - Tools/Stripe_w/free.h | 22 - Tools/Stripe_w/global.h | 44 - Tools/Stripe_w/init.c | 217 -- Tools/Stripe_w/init.h | 30 - Tools/Stripe_w/local.c | 119 - Tools/Stripe_w/local.h | 20 - Tools/Stripe_w/newpolve.c | 1659 --------- Tools/Stripe_w/options.c | 181 - Tools/Stripe_w/options.h | 17 - Tools/Stripe_w/output.c | 579 ---- Tools/Stripe_w/output.h | 34 - Tools/Stripe_w/outputex.c | 514 --- Tools/Stripe_w/outputex.h | 31 - Tools/Stripe_w/partial.c | 668 ---- Tools/Stripe_w/partial.h | 20 - Tools/Stripe_w/polverts.h | 108 - Tools/Stripe_w/polyvertsex.h | 42 - Tools/Stripe_w/queue.c | 226 -- Tools/Stripe_w/queue.h | 283 -- Tools/Stripe_w/sgi_triang.c | 628 ---- Tools/Stripe_w/sgi_triangex.c | 582 ---- Tools/Stripe_w/struct.c | 549 --- Tools/Stripe_w/structex.c | 553 --- Tools/Stripe_w/sturcts.h | 36 - Tools/Stripe_w/sturctsex.h | 33 - Tools/Stripe_w/ties.c | 304 -- Tools/Stripe_w/ties.h | 15 - Tools/Stripe_w/triangulate.h | 27 - Tools/Stripe_w/triangulatex.h | 28 - Tools/Stripe_w/util.c | 272 -- Tools/Stripe_w/util.h | 24 - Tools/{Tools => }/Todo | 0 Tools/Tri2obj/Makefile.am | 71 - Tools/Tri2obj/tri2obj.cxx | 695 ---- Tools/Tri2obj/tri2obj.hxx | 68 - Tools/{ => Utils}/Makedir/Makefile.am | 0 Tools/{ => Utils}/Makedir/makedir.cxx | 0 Tools/Utils/Makefile.am | 2 + Tools/Utils/convert.pl | 20 + Tools/Utils/mirror-dem | 29 + Tools/{Tools => }/process-dem.pl | 3 + Tools/{Tools => }/scenery_version.hxx | 3 + configure.in | 9 +- 575 files changed, 10909 insertions(+), 42163 deletions(-) delete mode 100644 Docs/CVSROOT/checkoutlist delete mode 100644 Docs/CVSROOT/commitinfo delete mode 100644 Docs/CVSROOT/config delete mode 100644 Docs/CVSROOT/cvswrappers delete mode 100644 Docs/CVSROOT/editinfo delete mode 100644 Docs/CVSROOT/loginfo delete mode 100644 Docs/CVSROOT/modules delete mode 100644 Docs/CVSROOT/notify delete mode 100644 Docs/CVSROOT/rcsinfo delete mode 100644 Docs/CVSROOT/taginfo delete mode 100644 Docs/CVSROOT/verifymsg delete mode 100644 Docs/CoordinateSystem/old-coord.fig rename Docs/{ => FDM}/LaRCsim/LaRCsim-notes.tex (100%) rename Docs/{ => FDM}/LaRCsim/LaRCsim-vars.tex (100%) rename Docs/{ => FDM}/LaRCsim/LaRCsim_generics_v_1.4.xls (100%) rename Docs/{ => FDM}/LaRCsim/manual.ps.gz (100%) rename Docs/{ => FDM}/LaRCsim/manual.tex.gz (100%) rename Docs/{ => InstallGuide}/HTML/arizona.gif (100%) rename Docs/{ => InstallGuide}/HTML/getstart.html (100%) rename Docs/{ => InstallGuide}/HTML/hud.gif (100%) rename Docs/{ => InstallGuide}/HTML/navion.gif (100%) rename Docs/{ => InstallGuide}/HTML/start.gif (100%) rename Docs/{ => InstallGuide}/PDF/getstart.pdf (100%) rename Docs/{ => InstallGuide}/SOURCE/arizona.eps (100%) rename Docs/{ => InstallGuide}/SOURCE/building.tex (100%) rename Docs/{ => InstallGuide}/SOURCE/flight.tex (100%) rename Docs/{ => InstallGuide}/SOURCE/free.tex (100%) rename Docs/{ => InstallGuide}/SOURCE/getstart.tex (100%) rename Docs/{ => InstallGuide}/SOURCE/hud.eps (100%) rename Docs/{ => InstallGuide}/SOURCE/index.tex (100%) rename Docs/{ => InstallGuide}/SOURCE/landing.tex (100%) rename Docs/{ => InstallGuide}/SOURCE/missed.tex (100%) rename Docs/{ => InstallGuide}/SOURCE/navion.eps (100%) rename Docs/{ => InstallGuide}/SOURCE/opengl.tex (100%) rename Docs/{ => InstallGuide}/SOURCE/prefligh.tex (100%) rename Docs/{ => InstallGuide}/SOURCE/start.eps (100%) rename Docs/{ => InstallGuide}/SOURCE/takeoff.tex (100%) rename Docs/{ => InstallGuide}/SOURCE/title.tex (100%) create mode 100644 Docs/Misc/Features create mode 100644 Docs/Portability/fgfs-portability-guide.tex rename Docs/{ => Scenery}/Astro/Stars.info (100%) rename Docs/{ => Scenery}/Astro/Stars.tex (99%) rename Docs/{ => Scenery}/CoordinateSystem/CoordinateSystem.tex (100%) rename Docs/{ => Scenery}/CoordinateSystem/coord.fig (100%) rename Docs/{ => Scenery}/CoordinateSystem/geodesy.fig (100%) create mode 100644 Docs/Scenery/DEM.info create mode 100644 Docs/Scenery/DLG/dlg3sdts.wp.gz create mode 100755 Docs/Scenery/DLG/dug-2.wp6.gz create mode 100644 Docs/Scenery/OBJ.format.txt rename Docs/{ => Scenery}/SceneGeneration/SceneryGeneration.tex (99%) rename Docs/{ => Scenery}/SceneGeneration/ref.fig (100%) create mode 100644 Docs/Scenery/SceneGeneration/terrain.outline rename Docs/{ => Scenery}/SceneGeneration/trap.fig (100%) rename Docs/{ => Scenery}/Sky/Sky.tex (99%) rename Docs/{ => Scenery}/Sky/dome.fig (100%) rename Docs/{ => Scenery}/Sky/earth.fig (100%) rename Docs/{ => Scenery}/Sky/local.fig (100%) create mode 100644 Docs/Time/Events/Events.tex create mode 100644 Hints/aaa create mode 100644 Hints/endian-ness create mode 100644 Hints/gamma create mode 100644 Hints/joystick create mode 100644 Hints/lights.c create mode 100644 Hints/mip-mapping create mode 100644 Hints/nmea create mode 100644 Hints/opengl-optimization create mode 100644 Hints/polygon-offset create mode 100644 Hints/portable-sound create mode 100644 Hints/scene-graph create mode 100644 Hints/stl-gcc-redhat create mode 100644 Hints/strips-vs-fans create mode 100644 Hints/texturing create mode 100644 Hints/tile-gaps create mode 100644 Hints/timezone create mode 100644 Hints/view-frustum-culling create mode 100644 Hints/view-projection create mode 100644 Hints/win32-time-funcs delete mode 100644 Lib/Audio/CHANGES delete mode 100644 Lib/Audio/Makefile.am delete mode 100644 Lib/Audio/NOTICE delete mode 100644 Lib/Audio/README delete mode 100644 Lib/Audio/README.freebsd delete mode 100644 Lib/Audio/README.linux delete mode 100644 Lib/Audio/README.openbsd delete mode 100644 Lib/Audio/README.sgi delete mode 100644 Lib/Audio/README.unix delete mode 100644 Lib/Audio/README.win delete mode 100644 Lib/CVSROOT/checkoutlist delete mode 100644 Lib/CVSROOT/commitinfo delete mode 100644 Lib/CVSROOT/cvswrappers delete mode 100644 Lib/CVSROOT/editinfo delete mode 100644 Lib/CVSROOT/loginfo delete mode 100644 Lib/CVSROOT/modules delete mode 100644 Lib/CVSROOT/notify delete mode 100644 Lib/CVSROOT/rcsinfo delete mode 100644 Lib/CVSROOT/taginfo rename Lib/{Lib => }/Makefile.am (100%) create mode 100644 Lib/Math/geotest.c create mode 100644 Lib/Math/inttest.cxx delete mode 100644 Lib/PUI/Makefile.am delete mode 100644 Lib/PUI/complex.cxx delete mode 100644 Lib/PUI/pu.cxx delete mode 100644 Lib/PUI/pu.h delete mode 100644 Lib/PUI/puBox.cxx delete mode 100644 Lib/PUI/puButton.cxx delete mode 100644 Lib/PUI/puButtonBox.cxx delete mode 100644 Lib/PUI/puDialogBox.cxx delete mode 100644 Lib/PUI/puFrame.cxx delete mode 100644 Lib/PUI/puInput.cxx delete mode 100644 Lib/PUI/puInterface.cxx delete mode 100644 Lib/PUI/puLocal.h delete mode 100644 Lib/PUI/puMenuBar.cxx delete mode 100644 Lib/PUI/puObject.cxx delete mode 100644 Lib/PUI/puOneShot.cxx delete mode 100644 Lib/PUI/puPopup.cxx delete mode 100644 Lib/PUI/puPopupMenu.cxx delete mode 100644 Lib/PUI/puSlider.cxx delete mode 100644 Lib/PUI/puText.cxx delete mode 100644 Lib/example/Makefile.am delete mode 100644 Lib/example/example.cxx delete mode 100644 Lib/src/Makefile.am delete mode 100644 Lib/src/sl.h delete mode 100644 Lib/src/slDSP.cxx delete mode 100644 Lib/src/slEnvelope.cxx delete mode 100644 Lib/src/slPortability.h delete mode 100644 Lib/src/slSample.cxx delete mode 100644 Lib/src/slSamplePlayer.cxx delete mode 100644 Lib/src/slScheduler.cxx delete mode 100644 Lib/src/sm.h delete mode 100644 Lib/src/smMixer.cxx delete mode 100644 Lib/zlib/ChangeLog delete mode 100644 Lib/zlib/INDEX delete mode 100644 Lib/zlib/Makefile.am delete mode 100644 Lib/zlib/README delete mode 100644 Lib/zlib/adler32.c delete mode 100644 Lib/zlib/algorithm.txt delete mode 100644 Lib/zlib/compress.c delete mode 100644 Lib/zlib/crc32.c delete mode 100644 Lib/zlib/deflate.c delete mode 100644 Lib/zlib/deflate.h delete mode 100644 Lib/zlib/descrip.mms delete mode 100644 Lib/zlib/example.c delete mode 100644 Lib/zlib/gzio.c delete mode 100644 Lib/zlib/infblock.c delete mode 100644 Lib/zlib/infblock.h delete mode 100644 Lib/zlib/infcodes.c delete mode 100644 Lib/zlib/infcodes.h delete mode 100644 Lib/zlib/inffast.c delete mode 100644 Lib/zlib/inffast.h delete mode 100644 Lib/zlib/inffixed.h delete mode 100644 Lib/zlib/inflate.c delete mode 100644 Lib/zlib/inftrees.c delete mode 100644 Lib/zlib/inftrees.h delete mode 100644 Lib/zlib/infutil.c delete mode 100644 Lib/zlib/infutil.h delete mode 100644 Lib/zlib/maketree.c delete mode 100644 Lib/zlib/minigzip.c delete mode 100644 Lib/zlib/trees.c delete mode 100644 Lib/zlib/trees.h delete mode 100644 Lib/zlib/uncompr.c delete mode 100644 Lib/zlib/zconf.h delete mode 100644 Lib/zlib/zlib.3 delete mode 100644 Lib/zlib/zlib.h delete mode 100644 Lib/zlib/zutil.c delete mode 100644 Lib/zlib/zutil.h create mode 100644 README.src create mode 100644 Simulator/Airports/old_draw_runways.c create mode 100644 Simulator/Airports/testair.cxx delete mode 100644 Simulator/CVSROOT/checkoutlist delete mode 100644 Simulator/CVSROOT/commitinfo delete mode 100644 Simulator/CVSROOT/cvswrappers delete mode 100644 Simulator/CVSROOT/editinfo delete mode 100644 Simulator/CVSROOT/loginfo delete mode 100644 Simulator/CVSROOT/modules delete mode 100644 Simulator/CVSROOT/notify delete mode 100644 Simulator/CVSROOT/rcsinfo delete mode 100644 Simulator/CVSROOT/taginfo create mode 100644 Simulator/Cockpit/proposed-navaids.hpp rename Simulator/{Simulator => }/Done (100%) rename Simulator/{ => FDM}/External/Makefile.am (100%) rename Simulator/{ => FDM}/External/external.cxx (96%) rename Simulator/{ => FDM}/External/external.hxx (97%) rename Simulator/{ => FDM}/JSBsim/FGAircraft.cpp (100%) rename Simulator/{ => FDM}/JSBsim/FGAircraft.h (100%) rename Simulator/{ => FDM}/JSBsim/FGAtmosphere.cpp (100%) rename Simulator/{ => FDM}/JSBsim/FGAtmosphere.h (100%) rename Simulator/{ => FDM}/JSBsim/FGAuxiliary.cpp (100%) rename Simulator/{ => FDM}/JSBsim/FGAuxiliary.h (100%) rename Simulator/{ => FDM}/JSBsim/FGCoefficient.cpp (100%) rename Simulator/{ => FDM}/JSBsim/FGCoefficient.h (100%) rename Simulator/{ => FDM}/JSBsim/FGControls.cpp (97%) rename Simulator/{ => FDM}/JSBsim/FGControls.h (99%) rename Simulator/{ => FDM}/JSBsim/FGDefs.h (100%) rename Simulator/{ => FDM}/JSBsim/FGEngine.cpp (100%) rename Simulator/{ => FDM}/JSBsim/FGEngine.h (100%) rename Simulator/{ => FDM}/JSBsim/FGFCS.cpp (100%) rename Simulator/{ => FDM}/JSBsim/FGFCS.h (100%) rename Simulator/{ => FDM}/JSBsim/FGFDMExec.cpp (100%) rename Simulator/{ => FDM}/JSBsim/FGFDMExec.h (100%) rename Simulator/{ => FDM}/JSBsim/FGMain.cpp (100%) rename Simulator/{ => FDM}/JSBsim/FGMatrix.cpp (100%) rename Simulator/{ => FDM}/JSBsim/FGMatrix.h (100%) rename Simulator/{ => FDM}/JSBsim/FGModel.cpp (100%) rename Simulator/{ => FDM}/JSBsim/FGModel.h (100%) rename Simulator/{ => FDM}/JSBsim/FGOutput.cpp (100%) rename Simulator/{ => FDM}/JSBsim/FGOutput.h (100%) rename Simulator/{ => FDM}/JSBsim/FGPosition.cpp (100%) rename Simulator/{ => FDM}/JSBsim/FGPosition.h (100%) rename Simulator/{ => FDM}/JSBsim/FGRotation.cpp (100%) rename Simulator/{ => FDM}/JSBsim/FGRotation.h (100%) rename Simulator/{ => FDM}/JSBsim/FGState.cpp (100%) rename Simulator/{ => FDM}/JSBsim/FGState.h (100%) rename Simulator/{ => FDM}/JSBsim/FGTank.cpp (100%) rename Simulator/{ => FDM}/JSBsim/FGTank.h (100%) rename Simulator/{ => FDM}/JSBsim/FGTranslation.cpp (100%) rename Simulator/{ => FDM}/JSBsim/FGTranslation.h (100%) rename Simulator/{ => FDM}/JSBsim/FGUtility.cpp (100%) rename Simulator/{ => FDM}/JSBsim/FGUtility.h (100%) rename Simulator/{ => FDM}/JSBsim/Makefile.am (100%) create mode 100644 Simulator/FDM/LaRCsim/Cherokee.txt rename Simulator/{ => FDM}/LaRCsim/Makefile.am (100%) rename Simulator/{ => FDM}/LaRCsim/atmos_62.c (100%) rename Simulator/{ => FDM}/LaRCsim/atmos_62.h (100%) create mode 100644 Simulator/FDM/LaRCsim/cherokee_aero.c create mode 100644 Simulator/FDM/LaRCsim/cherokee_engine.c create mode 100644 Simulator/FDM/LaRCsim/cherokee_gear.c create mode 100644 Simulator/FDM/LaRCsim/cherokee_init.c rename Simulator/{ => FDM}/LaRCsim/default_model_routines.c (97%) rename Simulator/{ => FDM}/LaRCsim/default_model_routines.h (100%) rename Simulator/{ => FDM}/LaRCsim/ls_accel.c (99%) rename Simulator/{ => FDM}/LaRCsim/ls_accel.h (100%) rename Simulator/{ => FDM}/LaRCsim/ls_aux.c (99%) rename Simulator/{ => FDM}/LaRCsim/ls_aux.h (100%) rename Simulator/{ => FDM}/LaRCsim/ls_cockpit.h (97%) rename Simulator/{ => FDM}/LaRCsim/ls_constants.h (100%) rename Simulator/{ => FDM}/LaRCsim/ls_generic.h (100%) rename Simulator/{ => FDM}/LaRCsim/ls_geodesy.c (98%) rename Simulator/{ => FDM}/LaRCsim/ls_geodesy.h (100%) rename Simulator/{ => FDM}/LaRCsim/ls_gravity.c (97%) rename Simulator/{ => FDM}/LaRCsim/ls_gravity.h (100%) rename Simulator/{ => FDM}/LaRCsim/ls_init.c (99%) rename Simulator/{ => FDM}/LaRCsim/ls_init.h (100%) rename Simulator/{ => FDM}/LaRCsim/ls_interface.c (99%) rename Simulator/{ => FDM}/LaRCsim/ls_interface.h (98%) rename Simulator/{ => FDM}/LaRCsim/ls_matrix.c (99%) rename Simulator/{ => FDM}/LaRCsim/ls_matrix.h (98%) rename Simulator/{ => FDM}/LaRCsim/ls_model.c (97%) rename Simulator/{ => FDM}/LaRCsim/ls_model.h (100%) rename Simulator/{ => FDM}/LaRCsim/ls_sim_control.h (98%) rename Simulator/{ => FDM}/LaRCsim/ls_step.c (99%) rename Simulator/{ => FDM}/LaRCsim/ls_step.h (100%) rename Simulator/{ => FDM}/LaRCsim/ls_sym.h (98%) create mode 100644 Simulator/FDM/LaRCsim/ls_trim.c rename Simulator/{ => FDM}/LaRCsim/ls_types.h (100%) rename Simulator/{ => FDM}/LaRCsim/mymain.c (100%) rename Simulator/{ => FDM}/LaRCsim/navion_aero.c (100%) rename Simulator/{ => FDM}/LaRCsim/navion_engine.c (100%) rename Simulator/{ => FDM}/LaRCsim/navion_gear.c (99%) rename Simulator/{ => FDM}/LaRCsim/navion_init.c (100%) rename Simulator/{ => FDM}/LaRCsim/navion_init.h (100%) create mode 100644 Simulator/FDM/LaRCsim/on_ground.ic rename Simulator/{ => FDM}/Slew/Makefile.am (100%) rename Simulator/{ => FDM}/Slew/slew.cxx (98%) rename Simulator/{ => FDM}/Slew/slew.hxx (96%) create mode 100755 Simulator/Main/3dfx.sh create mode 100644 Simulator/Main/mtest.c create mode 100644 Simulator/Main/ttest.cxx rename Simulator/{Simulator => }/Makefile.am (100%) delete mode 100644 Simulator/Objects/material.cxx delete mode 100644 Simulator/Objects/material.hxx delete mode 100644 Simulator/Objects/texload.c delete mode 100644 Simulator/Objects/texload.h create mode 100644 Simulator/Scenery/design create mode 100644 Simulator/Scenery/maptest.cxx create mode 100644 Simulator/Scenery/test.cxx create mode 100644 Simulator/Time/test_event.c create mode 100644 Simulator/Time/ttest.c create mode 100644 Simulator/Time/win32test.c rename Simulator/{Simulator => }/Todo (100%) delete mode 100644 Tools/AssemTris/Makefile.am delete mode 100644 Tools/AssemTris/assemtris.cxx delete mode 100644 Tools/AssemTris/assemtris.hxx delete mode 100644 Tools/CVSROOT/checkoutlist delete mode 100644 Tools/CVSROOT/commitinfo delete mode 100644 Tools/CVSROOT/cvswrappers delete mode 100644 Tools/CVSROOT/editinfo delete mode 100644 Tools/CVSROOT/loginfo delete mode 100644 Tools/CVSROOT/modules delete mode 100644 Tools/CVSROOT/notify delete mode 100644 Tools/CVSROOT/rcsinfo delete mode 100644 Tools/CVSROOT/taginfo rename Tools/{ => Construct}/Array/Makefile.am (100%) rename Tools/{ => Construct}/Array/array.cxx (99%) rename Tools/{ => Construct}/Array/array.hxx (98%) rename Tools/{ => Construct}/Array/testarray.cxx (100%) rename Tools/{ => Construct}/Clipper/Makefile.am (100%) rename Tools/{ => Construct}/Clipper/clipper.cxx (99%) rename Tools/{ => Construct}/Clipper/clipper.hxx (97%) rename Tools/{ => Construct}/Clipper/testclipper.cxx (97%) rename Tools/{ => Construct}/Combine/Makefile.am (100%) rename Tools/{ => Construct}/Combine/genfans.cxx (99%) rename Tools/{ => Construct}/Combine/genfans.hxx (97%) rename Tools/{ => Construct}/GenOutput/Makefile.am (100%) rename Tools/{ => Construct}/GenOutput/genobj.cxx (99%) rename Tools/{ => Construct}/GenOutput/genobj.hxx (98%) rename Tools/{ => Construct}/Main/Makefile.am (100%) rename Tools/{ => Construct}/Main/construct_types.hxx (96%) rename Tools/{ => Construct}/Triangulate/Makefile.am (100%) rename Tools/{ => Construct}/Triangulate/triangle.cxx (99%) rename Tools/{ => Construct}/Triangulate/triangle.hxx (98%) rename Tools/{ => Construct}/Triangulate/trieles.cxx (93%) rename Tools/{ => Construct}/Triangulate/trieles.hxx (97%) rename Tools/{ => Construct}/Triangulate/trinodes.cxx (98%) rename Tools/{ => Construct}/Triangulate/trinodes.hxx (98%) rename Tools/{ => Construct}/Triangulate/tripoly.cxx (98%) rename Tools/{ => Construct}/Triangulate/tripoly.hxx (97%) rename Tools/{ => Construct}/Triangulate/trisegs.cxx (98%) rename Tools/{ => Construct}/Triangulate/trisegs.hxx (98%) delete mode 100644 Tools/FixNode/Makefile.am delete mode 100644 Tools/FixNode/fixnode.cxx delete mode 100644 Tools/FixNode/fixnode.hxx delete mode 100644 Tools/FixNode/main.cxx delete mode 100644 Tools/FixObj/Makefile.am delete mode 100644 Tools/FixObj/main.cxx delete mode 100644 Tools/FixObj/obj.cxx delete mode 100644 Tools/FixObj/obj.hxx rename Tools/{ => Lib}/DEM/Makefile.am (100%) rename Tools/{ => Lib}/DEM/dem.cxx (99%) rename Tools/{ => Lib}/DEM/dem.hxx (98%) rename Tools/{ => Lib}/Polygon/Makefile.am (100%) rename Tools/{ => Lib}/Polygon/index.cxx (96%) rename Tools/{ => Lib}/Polygon/index.hxx (95%) rename Tools/{ => Lib}/Polygon/names.cxx (98%) rename Tools/{ => Lib}/Polygon/names.hxx (97%) rename Tools/{ => Lib}/Triangle/A.poly (100%) rename Tools/{ => Lib}/Triangle/Makefile.am (100%) rename Tools/{ => Lib}/Triangle/README (100%) rename Tools/{ => Lib}/Triangle/showme.c (100%) rename Tools/{ => Lib}/Triangle/triangle.c (100%) rename Tools/{ => Lib}/Triangle/triangle.doc (100%) rename Tools/{ => Lib}/Triangle/triangle.h (100%) rename Tools/{ => Lib}/Triangle/tricall.c (100%) delete mode 100644 Tools/Main/construct.cxx rename Tools/{Tools => }/Makefile.am (100%) rename Tools/{ => Prep}/DemChop/Makefile.am (96%) rename Tools/{ => Prep}/DemChop/demchop.cxx (97%) rename Tools/{ => Prep}/DemChop/point2d.cxx (95%) rename Tools/{ => Prep}/DemChop/point2d.hxx (95%) rename Tools/{ => Prep}/DemInfo/Makefile.am (97%) rename Tools/{ => Prep}/DemInfo/deminfo.cxx (96%) rename Tools/{ => Prep}/DemInfo/gather-dem-info.pl (96%) rename Tools/{ => Prep}/DemRaw2ascii/Makefile.am (96%) rename Tools/{ => Prep}/DemRaw2ascii/main.c (97%) rename Tools/{ => Prep}/DemRaw2ascii/rawdem.c (99%) rename Tools/{ => Prep}/DemRaw2ascii/rawdem.h (97%) rename Tools/{ => Prep}/GenAirports/Makefile.am (97%) rename Tools/{ => Prep}/GenAirports/area.cxx (99%) rename Tools/{ => Prep}/GenAirports/area.hxx (95%) rename Tools/{ => Prep}/GenAirports/convex_hull.cxx (99%) rename Tools/{ => Prep}/GenAirports/convex_hull.hxx (96%) rename Tools/{ => Prep}/GenAirports/main.cxx (99%) rename Tools/{ => Prep}/GenAirports/point2d.cxx (95%) rename Tools/{ => Prep}/GenAirports/point2d.hxx (95%) rename Tools/{ => Prep}/ShapeFile/Makefile.am (100%) rename Tools/{ => Prep}/ShapeFile/main.cxx (99%) rename Tools/{ => Prep}/ShapeFile/shape.cxx (98%) rename Tools/{ => Prep}/ShapeFile/shape.hxx (96%) rename Tools/{Tools => }/README (100%) delete mode 100644 Tools/SplitTris/Makefile.am delete mode 100644 Tools/SplitTris/splittris.cxx delete mode 100644 Tools/SplitTris/splittris.hxx delete mode 100644 Tools/Stripe_u/Makefile.am delete mode 100644 Tools/Stripe_u/add.c delete mode 100644 Tools/Stripe_u/add.h delete mode 100644 Tools/Stripe_u/bands.c delete mode 100644 Tools/Stripe_u/common.c delete mode 100644 Tools/Stripe_u/common.h delete mode 100644 Tools/Stripe_u/define.h delete mode 100644 Tools/Stripe_u/extend.h delete mode 100644 Tools/Stripe_u/free.c delete mode 100644 Tools/Stripe_u/free.h delete mode 100644 Tools/Stripe_u/global.h delete mode 100644 Tools/Stripe_u/glove.h delete mode 100644 Tools/Stripe_u/init.c delete mode 100644 Tools/Stripe_u/init.h delete mode 100644 Tools/Stripe_u/local.c delete mode 100644 Tools/Stripe_u/local.h delete mode 100644 Tools/Stripe_u/my_global.h delete mode 100644 Tools/Stripe_u/newpolve.c delete mode 100644 Tools/Stripe_u/options.c delete mode 100644 Tools/Stripe_u/options.h delete mode 100644 Tools/Stripe_u/output.c delete mode 100644 Tools/Stripe_u/output.h delete mode 100644 Tools/Stripe_u/outputex.c delete mode 100644 Tools/Stripe_u/outputex.h delete mode 100644 Tools/Stripe_u/partial.c delete mode 100644 Tools/Stripe_u/partial.h delete mode 100644 Tools/Stripe_u/polverts.h delete mode 100644 Tools/Stripe_u/polvertsex.h delete mode 100644 Tools/Stripe_u/queue.c delete mode 100644 Tools/Stripe_u/queue.h delete mode 100644 Tools/Stripe_u/sgi_triang.c delete mode 100644 Tools/Stripe_u/sgi_triangex.c delete mode 100644 Tools/Stripe_u/struct.c delete mode 100644 Tools/Stripe_u/struct.h delete mode 100644 Tools/Stripe_u/structex.c delete mode 100644 Tools/Stripe_u/sturcts.h delete mode 100644 Tools/Stripe_u/sturctsex.h delete mode 100644 Tools/Stripe_u/ties.c delete mode 100644 Tools/Stripe_u/ties.h delete mode 100644 Tools/Stripe_u/triangulate.h delete mode 100644 Tools/Stripe_u/triangulatex.h delete mode 100644 Tools/Stripe_u/util.c delete mode 100644 Tools/Stripe_u/util.h delete mode 100644 Tools/Stripe_w/Makefile.am delete mode 100644 Tools/Stripe_w/add.c delete mode 100644 Tools/Stripe_w/add.h delete mode 100644 Tools/Stripe_w/bands.c delete mode 100644 Tools/Stripe_w/common.c delete mode 100644 Tools/Stripe_w/common.h delete mode 100644 Tools/Stripe_w/extend.h delete mode 100644 Tools/Stripe_w/free.c delete mode 100644 Tools/Stripe_w/free.h delete mode 100644 Tools/Stripe_w/global.h delete mode 100644 Tools/Stripe_w/init.c delete mode 100644 Tools/Stripe_w/init.h delete mode 100644 Tools/Stripe_w/local.c delete mode 100644 Tools/Stripe_w/local.h delete mode 100644 Tools/Stripe_w/newpolve.c delete mode 100644 Tools/Stripe_w/options.c delete mode 100644 Tools/Stripe_w/options.h delete mode 100644 Tools/Stripe_w/output.c delete mode 100644 Tools/Stripe_w/output.h delete mode 100644 Tools/Stripe_w/outputex.c delete mode 100644 Tools/Stripe_w/outputex.h delete mode 100644 Tools/Stripe_w/partial.c delete mode 100644 Tools/Stripe_w/partial.h delete mode 100644 Tools/Stripe_w/polverts.h delete mode 100644 Tools/Stripe_w/polyvertsex.h delete mode 100644 Tools/Stripe_w/queue.c delete mode 100644 Tools/Stripe_w/queue.h delete mode 100644 Tools/Stripe_w/sgi_triang.c delete mode 100644 Tools/Stripe_w/sgi_triangex.c delete mode 100644 Tools/Stripe_w/struct.c delete mode 100644 Tools/Stripe_w/structex.c delete mode 100644 Tools/Stripe_w/sturcts.h delete mode 100644 Tools/Stripe_w/sturctsex.h delete mode 100644 Tools/Stripe_w/ties.c delete mode 100644 Tools/Stripe_w/ties.h delete mode 100644 Tools/Stripe_w/triangulate.h delete mode 100644 Tools/Stripe_w/triangulatex.h delete mode 100644 Tools/Stripe_w/util.c delete mode 100644 Tools/Stripe_w/util.h rename Tools/{Tools => }/Todo (100%) delete mode 100644 Tools/Tri2obj/Makefile.am delete mode 100644 Tools/Tri2obj/tri2obj.cxx delete mode 100644 Tools/Tri2obj/tri2obj.hxx rename Tools/{ => Utils}/Makedir/Makefile.am (100%) rename Tools/{ => Utils}/Makedir/makedir.cxx (100%) create mode 100755 Tools/Utils/convert.pl create mode 100644 Tools/Utils/mirror-dem rename Tools/{Tools => }/process-dem.pl (99%) rename Tools/{Tools => }/scenery_version.hxx (94%) diff --git a/Docs/Autopilot/AltitudeHold.tex b/Docs/Autopilot/AltitudeHold.tex index c4dcd5f31..8727e520d 100644 --- a/Docs/Autopilot/AltitudeHold.tex +++ b/Docs/Autopilot/AltitudeHold.tex @@ -205,6 +205,9 @@ effectiveness of your controller. %------------------------------------------------------------------------ % $Log$ +% Revision 1.1 1999/04/05 21:32:34 curt +% Initial revision +% % Revision 1.1 1999/03/09 19:09:41 curt % Initial revision. % diff --git a/Docs/Autopilot/HeadingHold.tex b/Docs/Autopilot/HeadingHold.tex index ae08b0775..de2b106b5 100644 --- a/Docs/Autopilot/HeadingHold.tex +++ b/Docs/Autopilot/HeadingHold.tex @@ -102,6 +102,9 @@ built this system, feel free to e-mail me at %------------------------------------------------------------------------ % $Log$ +% Revision 1.1 1999/04/05 21:32:34 curt +% Initial revision +% % Revision 1.1 1999/03/09 19:09:41 curt % Initial revision. % diff --git a/Docs/CVSROOT/checkoutlist b/Docs/CVSROOT/checkoutlist deleted file mode 100644 index b04b3501f..000000000 --- a/Docs/CVSROOT/checkoutlist +++ /dev/null @@ -1,13 +0,0 @@ -# The "checkoutlist" file is used to support additional version controlled -# administrative files in $CVSROOT/CVSROOT, such as template files. -# -# The first entry on a line is a filename which will be checked out from -# the corresponding RCS file in the $CVSROOT/CVSROOT directory. -# The remainder of the line is an error message to use if the file cannot -# be checked out. -# -# File format: -# -# [] -# -# comment lines begin with '#' diff --git a/Docs/CVSROOT/commitinfo b/Docs/CVSROOT/commitinfo deleted file mode 100644 index b19e7b7a6..000000000 --- a/Docs/CVSROOT/commitinfo +++ /dev/null @@ -1,15 +0,0 @@ -# The "commitinfo" file is used to control pre-commit checks. -# The filter on the right is invoked with the repository and a list -# of files to check. A non-zero exit of the filter program will -# cause the commit to be aborted. -# -# The first entry on a line is a regular expression which is tested -# against the directory that the change is being committed to, relative -# to the $CVSROOT. For the first match that is found, then the remainder -# of the line is the name of the filter to run. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. -# -# If the name "ALL" appears as a regular expression it is always used -# in addition to the first matching regex or "DEFAULT". diff --git a/Docs/CVSROOT/config b/Docs/CVSROOT/config deleted file mode 100644 index 51b03f663..000000000 --- a/Docs/CVSROOT/config +++ /dev/null @@ -1,6 +0,0 @@ -# Set this to "no" if pserver shouldn't check system users/passwords -#SystemAuth=no - -# Set `PreservePermissions' to `yes' to save file status information -# in the repository. -#PreservePermissions=no diff --git a/Docs/CVSROOT/cvswrappers b/Docs/CVSROOT/cvswrappers deleted file mode 100644 index 0accaf1b1..000000000 --- a/Docs/CVSROOT/cvswrappers +++ /dev/null @@ -1,23 +0,0 @@ -# This file affects handling of files based on their names. -# -# The -t/-f options allow one to treat directories of files -# as a single file, or to transform a file in other ways on -# its way in and out of CVS. -# -# The -m option specifies whether CVS attempts to merge files. -# -# The -k option specifies keyword expansion (e.g. -kb for binary). -# -# Format of wrapper file ($CVSROOT/CVSROOT/cvswrappers or .cvswrappers) -# -# wildcard [option value][option value]... -# -# where option is one of -# -f from cvs filter value: path to filter -# -t to cvs filter value: path to filter -# -m update methodology value: MERGE or COPY -# -k expansion mode value: b, o, kkv, &c -# -# and value is a single-quote delimited value. -# For example: -#*.gif -k 'b' diff --git a/Docs/CVSROOT/editinfo b/Docs/CVSROOT/editinfo deleted file mode 100644 index d78886c15..000000000 --- a/Docs/CVSROOT/editinfo +++ /dev/null @@ -1,21 +0,0 @@ -# The "editinfo" file is used to allow verification of logging -# information. It works best when a template (as specified in the -# rcsinfo file) is provided for the logging procedure. Given a -# template with locations for, a bug-id number, a list of people who -# reviewed the code before it can be checked in, and an external -# process to catalog the differences that were code reviewed, the -# following test can be applied to the code: -# -# Making sure that the entered bug-id number is correct. -# Validating that the code that was reviewed is indeed the code being -# checked in (using the bug-id number or a seperate review -# number to identify this particular code set.). -# -# If any of the above test failed, then the commit would be aborted. -# -# Actions such as mailing a copy of the report to each reviewer are -# better handled by an entry in the loginfo file. -# -# One thing that should be noted is the the ALL keyword is not -# supported. There can be only one entry that matches a given -# repository. diff --git a/Docs/CVSROOT/loginfo b/Docs/CVSROOT/loginfo deleted file mode 100644 index 5a59f0a54..000000000 --- a/Docs/CVSROOT/loginfo +++ /dev/null @@ -1,26 +0,0 @@ -# The "loginfo" file controls where "cvs commit" log information -# is sent. The first entry on a line is a regular expression which must match -# the directory that the change is being made to, relative to the -# $CVSROOT. If a match is found, then the remainder of the line is a filter -# program that should expect log information on its standard input. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. -# -# If the name ALL appears as a regular expression it is always used -# in addition to the first matching regex or DEFAULT. -# -# You may specify a format string as part of the -# filter. The string is composed of a `%' followed -# by a single format character, or followed by a set of format -# characters surrounded by `{' and `}' as separators. The format -# characters are: -# -# s = file name -# V = old version number (pre-checkin) -# v = new version number (post-checkin) -# -# For example: -#DEFAULT (echo ""; id; echo %s; date; cat) >> $CVSROOT/CVSROOT/commitlog -# or -#DEFAULT (echo ""; id; echo %{sVv}; date; cat) >> $CVSROOT/CVSROOT/commitlog diff --git a/Docs/CVSROOT/modules b/Docs/CVSROOT/modules deleted file mode 100644 index cb9e9efc9..000000000 --- a/Docs/CVSROOT/modules +++ /dev/null @@ -1,26 +0,0 @@ -# Three different line formats are valid: -# key -a aliases... -# key [options] directory -# key [options] directory files... -# -# Where "options" are composed of: -# -i prog Run "prog" on "cvs commit" from top-level of module. -# -o prog Run "prog" on "cvs checkout" of module. -# -e prog Run "prog" on "cvs export" of module. -# -t prog Run "prog" on "cvs rtag" of module. -# -u prog Run "prog" on "cvs update" of module. -# -d dir Place module in directory "dir" instead of module name. -# -l Top-level directory only -- do not recurse. -# -# NOTE: If you change any of the "Run" options above, you'll have to -# release and re-checkout any working directories of these modules. -# -# And "directory" is a path to a directory relative to $CVSROOT. -# -# The "-a" option specifies an alias. An alias is interpreted as if -# everything on the right of the "-a" had been typed on the command line. -# -# You can encode a module within a module by using the special '&' -# character to interpose another module into the current module. This -# can be useful for creating a module that consists of many directories -# spread out over the entire source repository. diff --git a/Docs/CVSROOT/notify b/Docs/CVSROOT/notify deleted file mode 100644 index 34f0bc288..000000000 --- a/Docs/CVSROOT/notify +++ /dev/null @@ -1,12 +0,0 @@ -# The "notify" file controls where notifications from watches set by -# "cvs watch add" or "cvs edit" are sent. The first entry on a line is -# a regular expression which is tested against the directory that the -# change is being made to, relative to the $CVSROOT. If it matches, -# then the remainder of the line is a filter program that should contain -# one occurrence of %s for the user to notify, and information on its -# standard input. -# -# "ALL" or "DEFAULT" can be used in place of the regular expression. -# -# For example: -#ALL mail %s -s "CVS notification" diff --git a/Docs/CVSROOT/rcsinfo b/Docs/CVSROOT/rcsinfo deleted file mode 100644 index 49e59f4d0..000000000 --- a/Docs/CVSROOT/rcsinfo +++ /dev/null @@ -1,13 +0,0 @@ -# The "rcsinfo" file is used to control templates with which the editor -# is invoked on commit and import. -# -# The first entry on a line is a regular expression which is tested -# against the directory that the change is being made to, relative to the -# $CVSROOT. For the first match that is found, then the remainder of the -# line is the name of the file that contains the template. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. -# -# If the name "ALL" appears as a regular expression it is always used -# in addition to the first matching regex or "DEFAULT". diff --git a/Docs/CVSROOT/taginfo b/Docs/CVSROOT/taginfo deleted file mode 100644 index 274a46dd5..000000000 --- a/Docs/CVSROOT/taginfo +++ /dev/null @@ -1,20 +0,0 @@ -# The "taginfo" file is used to control pre-tag checks. -# The filter on the right is invoked with the following arguments: -# -# $1 -- tagname -# $2 -- operation "add" for tag, "mov" for tag -F, and "del" for tag -d -# $3 -- repository -# $4-> file revision [file revision ...] -# -# A non-zero exit of the filter program will cause the tag to be aborted. -# -# The first entry on a line is a regular expression which is tested -# against the directory that the change is being committed to, relative -# to the $CVSROOT. For the first match that is found, then the remainder -# of the line is the name of the filter to run. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. -# -# If the name "ALL" appears as a regular expression it is always used -# in addition to the first matching regex or "DEFAULT". diff --git a/Docs/CVSROOT/verifymsg b/Docs/CVSROOT/verifymsg deleted file mode 100644 index 86f747ce2..000000000 --- a/Docs/CVSROOT/verifymsg +++ /dev/null @@ -1,21 +0,0 @@ -# The "verifymsg" file is used to allow verification of logging -# information. It works best when a template (as specified in the -# rcsinfo file) is provided for the logging procedure. Given a -# template with locations for, a bug-id number, a list of people who -# reviewed the code before it can be checked in, and an external -# process to catalog the differences that were code reviewed, the -# following test can be applied to the code: -# -# Making sure that the entered bug-id number is correct. -# Validating that the code that was reviewed is indeed the code being -# checked in (using the bug-id number or a seperate review -# number to identify this particular code set.). -# -# If any of the above test failed, then the commit would be aborted. -# -# Actions such as mailing a copy of the report to each reviewer are -# better handled by an entry in the loginfo file. -# -# One thing that should be noted is the the ALL keyword is not -# supported. There can be only one entry that matches a given -# repository. diff --git a/Docs/CoordinateSystem/old-coord.fig b/Docs/CoordinateSystem/old-coord.fig deleted file mode 100644 index 8de4472ce..000000000 --- a/Docs/CoordinateSystem/old-coord.fig +++ /dev/null @@ -1,27 +0,0 @@ -#FIG 3.2 -Landscape -Center -Inches -Letter -100.00 -Single -0 -1200 2 -5 1 0 1 0 7 0 0 -1 0.000 0 1 0 0 8962.500 6000.000 3600 5100 3525 6000 3600 6900 -5 1 0 1 0 7 0 0 -1 0.000 0 1 0 0 10762.500 6000.000 5400 5100 5325 6000 5400 6900 -5 1 0 1 0 7 0 0 -1 0.000 0 1 0 0 4500.000 -262.500 3600 5100 4500 5175 5400 5100 -5 1 0 1 0 7 0 0 -1 0.000 0 0 0 0 4500.000 1537.500 5400 6900 4500 6975 3600 6900 -5 1 2 1 0 7 0 0 -1 3.000 0 1 0 0 9825.000 6075.000 4500 5175 4425 6000 4500 6975 -5 1 2 1 0 7 0 0 -1 3.000 0 0 0 0 4425.000 637.500 5325 6000 4425 6075 3525 6000 -2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2 - 2 1 1.00 60.00 120.00 - 6000 5175 4425 6075 -2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2 - 2 1 1.00 60.00 120.00 - 6000 5175 8550 5175 -2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2 - 2 1 1.00 60.00 120.00 - 6000 5175 6000 2625 -4 0 0 0 0 0 18 0.0000 4 195 180 8475 5475 X\001 -4 0 0 0 0 0 18 0.0000 4 195 180 5700 2700 Y\001 -4 0 0 0 0 0 18 0.0000 4 195 180 4500 5850 Z\001 diff --git a/Docs/LaRCsim/LaRCsim-notes.tex b/Docs/FDM/LaRCsim/LaRCsim-notes.tex similarity index 100% rename from Docs/LaRCsim/LaRCsim-notes.tex rename to Docs/FDM/LaRCsim/LaRCsim-notes.tex diff --git a/Docs/LaRCsim/LaRCsim-vars.tex b/Docs/FDM/LaRCsim/LaRCsim-vars.tex similarity index 100% rename from Docs/LaRCsim/LaRCsim-vars.tex rename to Docs/FDM/LaRCsim/LaRCsim-vars.tex diff --git a/Docs/LaRCsim/LaRCsim_generics_v_1.4.xls b/Docs/FDM/LaRCsim/LaRCsim_generics_v_1.4.xls similarity index 100% rename from Docs/LaRCsim/LaRCsim_generics_v_1.4.xls rename to Docs/FDM/LaRCsim/LaRCsim_generics_v_1.4.xls diff --git a/Docs/LaRCsim/manual.ps.gz b/Docs/FDM/LaRCsim/manual.ps.gz similarity index 100% rename from Docs/LaRCsim/manual.ps.gz rename to Docs/FDM/LaRCsim/manual.ps.gz diff --git a/Docs/LaRCsim/manual.tex.gz b/Docs/FDM/LaRCsim/manual.tex.gz similarity index 100% rename from Docs/LaRCsim/manual.tex.gz rename to Docs/FDM/LaRCsim/manual.tex.gz diff --git a/Docs/HTML/arizona.gif b/Docs/InstallGuide/HTML/arizona.gif similarity index 100% rename from Docs/HTML/arizona.gif rename to Docs/InstallGuide/HTML/arizona.gif diff --git a/Docs/HTML/getstart.html b/Docs/InstallGuide/HTML/getstart.html similarity index 100% rename from Docs/HTML/getstart.html rename to Docs/InstallGuide/HTML/getstart.html diff --git a/Docs/HTML/hud.gif b/Docs/InstallGuide/HTML/hud.gif similarity index 100% rename from Docs/HTML/hud.gif rename to Docs/InstallGuide/HTML/hud.gif diff --git a/Docs/HTML/navion.gif b/Docs/InstallGuide/HTML/navion.gif similarity index 100% rename from Docs/HTML/navion.gif rename to Docs/InstallGuide/HTML/navion.gif diff --git a/Docs/HTML/start.gif b/Docs/InstallGuide/HTML/start.gif similarity index 100% rename from Docs/HTML/start.gif rename to Docs/InstallGuide/HTML/start.gif diff --git a/Docs/PDF/getstart.pdf b/Docs/InstallGuide/PDF/getstart.pdf similarity index 100% rename from Docs/PDF/getstart.pdf rename to Docs/InstallGuide/PDF/getstart.pdf diff --git a/Docs/SOURCE/arizona.eps b/Docs/InstallGuide/SOURCE/arizona.eps similarity index 100% rename from Docs/SOURCE/arizona.eps rename to Docs/InstallGuide/SOURCE/arizona.eps diff --git a/Docs/SOURCE/building.tex b/Docs/InstallGuide/SOURCE/building.tex similarity index 100% rename from Docs/SOURCE/building.tex rename to Docs/InstallGuide/SOURCE/building.tex diff --git a/Docs/SOURCE/flight.tex b/Docs/InstallGuide/SOURCE/flight.tex similarity index 100% rename from Docs/SOURCE/flight.tex rename to Docs/InstallGuide/SOURCE/flight.tex diff --git a/Docs/SOURCE/free.tex b/Docs/InstallGuide/SOURCE/free.tex similarity index 100% rename from Docs/SOURCE/free.tex rename to Docs/InstallGuide/SOURCE/free.tex diff --git a/Docs/SOURCE/getstart.tex b/Docs/InstallGuide/SOURCE/getstart.tex similarity index 100% rename from Docs/SOURCE/getstart.tex rename to Docs/InstallGuide/SOURCE/getstart.tex diff --git a/Docs/SOURCE/hud.eps b/Docs/InstallGuide/SOURCE/hud.eps similarity index 100% rename from Docs/SOURCE/hud.eps rename to Docs/InstallGuide/SOURCE/hud.eps diff --git a/Docs/SOURCE/index.tex b/Docs/InstallGuide/SOURCE/index.tex similarity index 100% rename from Docs/SOURCE/index.tex rename to Docs/InstallGuide/SOURCE/index.tex diff --git a/Docs/SOURCE/landing.tex b/Docs/InstallGuide/SOURCE/landing.tex similarity index 100% rename from Docs/SOURCE/landing.tex rename to Docs/InstallGuide/SOURCE/landing.tex diff --git a/Docs/SOURCE/missed.tex b/Docs/InstallGuide/SOURCE/missed.tex similarity index 100% rename from Docs/SOURCE/missed.tex rename to Docs/InstallGuide/SOURCE/missed.tex diff --git a/Docs/SOURCE/navion.eps b/Docs/InstallGuide/SOURCE/navion.eps similarity index 100% rename from Docs/SOURCE/navion.eps rename to Docs/InstallGuide/SOURCE/navion.eps diff --git a/Docs/SOURCE/opengl.tex b/Docs/InstallGuide/SOURCE/opengl.tex similarity index 100% rename from Docs/SOURCE/opengl.tex rename to Docs/InstallGuide/SOURCE/opengl.tex diff --git a/Docs/SOURCE/prefligh.tex b/Docs/InstallGuide/SOURCE/prefligh.tex similarity index 100% rename from Docs/SOURCE/prefligh.tex rename to Docs/InstallGuide/SOURCE/prefligh.tex diff --git a/Docs/SOURCE/start.eps b/Docs/InstallGuide/SOURCE/start.eps similarity index 100% rename from Docs/SOURCE/start.eps rename to Docs/InstallGuide/SOURCE/start.eps diff --git a/Docs/SOURCE/takeoff.tex b/Docs/InstallGuide/SOURCE/takeoff.tex similarity index 100% rename from Docs/SOURCE/takeoff.tex rename to Docs/InstallGuide/SOURCE/takeoff.tex diff --git a/Docs/SOURCE/title.tex b/Docs/InstallGuide/SOURCE/title.tex similarity index 100% rename from Docs/SOURCE/title.tex rename to Docs/InstallGuide/SOURCE/title.tex diff --git a/Docs/Misc/Features b/Docs/Misc/Features new file mode 100644 index 000000000..8bd493fa6 --- /dev/null +++ b/Docs/Misc/Features @@ -0,0 +1,14 @@ +Sky + stars + correct placement for time, date, and viewer position + correct magnitude + sun + correct position + lights the scene correctly + sky + blends into haze at horizon + sunset/sunrise effects + planets + correct position + correct magnitude + diff --git a/Docs/Portability/fgfs-portability-guide.tex b/Docs/Portability/fgfs-portability-guide.tex new file mode 100644 index 000000000..99d826aed --- /dev/null +++ b/Docs/Portability/fgfs-portability-guide.tex @@ -0,0 +1,142 @@ +%% This LaTeX-file was created by Sat Dec 5 17:56:02 1998 +%% LyX 0.12 (C) 1995-1998 by Matthias Ettrich and the LyX Team + +%% Do not edit this file unless you know what you are doing. +\documentclass{article} +\usepackage[T1]{fontenc} + +\makeatletter + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% LyX specific LaTeX commands. +\newcommand{\LyX}{L\kern-.1667em\lower.25em\hbox{Y}\kern-.125emX\spacefactor1000} + +\makeatother + +\begin{document} + + +\vfill{} +\title{\emph{FlightGear} Flight Simulator\\ +Portability Guide} +\vfill{} + + +\author{Bernie Bright (bbright@c031.aone.net.au)} + + +\date{28 November 1998} + +\maketitle +FlightGear is a multi-platform general aviation flight simulator\@. It is an +open development project in which anyone with network access and a C++ compiler +can contribute patches or new features.\\ + + + +\section{Introduction} + +The file \emph{Include/compiler.h} attempts to capture the differences between +C++ compiler and STL implementations through the use of ``feature test macros''\@. +The file is divided into two parts. The first part contains a section for each +compiler, consisting of manifest constants specifying the features supported +or absent from the particular compiler/STL combination\@. The second part uses +the feature test macros to supply any missing features\@. + + +\subsection{Supported compilers (more to come)} + +gcc 2.7.x\\ +gcc 2.8.x\\ +egcs 1.x\\ +Inprise (Borland) C++ 5.02\\ +Inprise (Borland) C++Builder 1 (5.20) + + +\subsection{Features Tests} + + +\subsubsection{STL} + +\begin{description} +\item [FG\_NEED\_AUTO\_PTR]Some STL implementations don't supply an \texttt{auto\_ptr<>} +class template. Define this to provide one. +\item [FG\_NO\_DEFAULT\_TEMPLATE\_ARGS]Define this if the compiler doesn't support +default arguments in template declarations. \emph{(example)} +\item [FG\_INCOMPLETE\_FUNCTIONAL]Some STL implementations don't have \texttt{mem\_fun\_ref()}. +Define this to provide one. +\item [FG\_NO\_ARROW\_OPERATOR]Define this if iterators don't support \texttt{operator->()}. +\emph{(example)} +\item [FG\_EXPLICIT\_FUNCTION\_TMPL\_ARGS]~ +\item [FG\_MEMBER\_TEMPLATES]~ +\end{description} + +\subsubsection{Compiler} + +\begin{description} +\item [FG\_NAMESPACES]Define if compiler supports namespaces. +\item [FG\_HAVE\_STD]Define if std:: namespace supported. +\item [FG\_HAVE\_STD\_INCLUDES]Define if headers should be included as \texttt{} +instead of \texttt{. Also implies that all ISO C++ standard include +files are present. +\item [FG\_HAVE\_STREAMBUF]Define if \texttt{} or \texttt{ +are present. +\item [FG\_CLASS\_PARTIAL\_SPECIALIZATION]~ +\item [FG\_NEED\_EXPLICIT]Define if the compiler doesn't support the \texttt{\textbf{explicit}} +keyword. +\item [FG\_NEED\_TYPENAME]Define if the compiler doesn't support the \texttt{\textbf{typename}} +keyword. +\item [FG\_NEED\_MUTABLE]Define if the compiler doesn't support the \texttt{\textbf{mutable}} +keyword. +\item [FG\_NEED\_BOOL]Define if the compiler doesn't have the \texttt{\textbf{bool}} +type. +\end{description} + +\subsubsection{Include Files} + +This section deals with header file naming conventions. Some systems truncate +filenames, 8.3 being common, other systems use old or non-standard names for +some header files. We deal with the simple cases by defining macros that expand +to the appropriate filename. + +\begin{description} +\item [STD\_ALGORITHM]=> , ``algorithm'' +\item [STD\_FUNCTIONAL]=> , ``functional'' +\item [STD\_IOMANIP]=> , +\item [STD\_IOSTREAM]=> , , +\item [STD\_STDEXCEPT]=> (ignore this, FlightGear doesn't use exceptions) +\item [STD\_STRING]=> +\item [STD\_STRSTREAM]=> , +\end{description} +In use, instead of writing \#include you write \#include STD\_IOSTREAM.\\ + \\ +The situation becomes complicated with missing header files. is +a good example. In this case we must rely on FG\_HAVE\_STD\_INCLUDES and FG\_HAVE\_STREAMBUF.\\ + \emph{}\\ +\emph{TODO} + + +\subsection{and the rest} + + +\subsubsection{Namespace Issues} + +\begin{description} +\item [FG\_USING\_STD(X)]~ +\item [FG\_NAMESPACE(X)]~ +\item [FG\_NAMESPACE\_END]~ +\item [FG\_USING\_NAMESPACE(X)]~ +\end{description} + +\subsubsection{Templates} + +\begin{description} +\item [FG\_NULL\_TMPL\_ARGS]~ +\item [FG\_TEMPLATE\_NULL]~ +\end{description} +\begin{thebibliography}{} +\bibitem{1}Stroustrup, Bjarne, \emph{The C++ Programming Programming Language}, 3rd edition, +June 1997, ISBN 0-201-88954-4 +\bibitem{2}SGI Standard Template Library (STL) release 3.11 +\end{thebibliography} +\end{document} diff --git a/Docs/Astro/Stars.info b/Docs/Scenery/Astro/Stars.info similarity index 100% rename from Docs/Astro/Stars.info rename to Docs/Scenery/Astro/Stars.info diff --git a/Docs/Astro/Stars.tex b/Docs/Scenery/Astro/Stars.tex similarity index 99% rename from Docs/Astro/Stars.tex rename to Docs/Scenery/Astro/Stars.tex index 5d642157f..0471afdcb 100644 --- a/Docs/Astro/Stars.tex +++ b/Docs/Scenery/Astro/Stars.tex @@ -202,6 +202,9 @@ so that you can never fly any closer to them. %------------------------------------------------------------------------ % $Log$ +% Revision 1.1 1999/04/05 21:32:34 curt +% Initial revision +% % Revision 1.1 1999/02/14 19:10:47 curt % Initial revisions. % diff --git a/Docs/CoordinateSystem/CoordinateSystem.tex b/Docs/Scenery/CoordinateSystem/CoordinateSystem.tex similarity index 100% rename from Docs/CoordinateSystem/CoordinateSystem.tex rename to Docs/Scenery/CoordinateSystem/CoordinateSystem.tex diff --git a/Docs/CoordinateSystem/coord.fig b/Docs/Scenery/CoordinateSystem/coord.fig similarity index 100% rename from Docs/CoordinateSystem/coord.fig rename to Docs/Scenery/CoordinateSystem/coord.fig diff --git a/Docs/CoordinateSystem/geodesy.fig b/Docs/Scenery/CoordinateSystem/geodesy.fig similarity index 100% rename from Docs/CoordinateSystem/geodesy.fig rename to Docs/Scenery/CoordinateSystem/geodesy.fig diff --git a/Docs/Scenery/DEM.info b/Docs/Scenery/DEM.info new file mode 100644 index 000000000..001074413 --- /dev/null +++ b/Docs/Scenery/DEM.info @@ -0,0 +1,3 @@ +An online guide for interpreting the DEM data file format is available at: + + http://edcwww.cr.usgs.gov/glis/hyper/guide/1_dgr_dem diff --git a/Docs/Scenery/DLG/dlg3sdts.wp.gz b/Docs/Scenery/DLG/dlg3sdts.wp.gz new file mode 100644 index 0000000000000000000000000000000000000000..2624e74c887cfd7d40dc2009e7538aa4c213cb2f GIT binary patch literal 30962 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
?hiK(u|pGh
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

literal 0
HcmV?d00001

diff --git a/Docs/Scenery/OBJ.format.txt b/Docs/Scenery/OBJ.format.txt
new file mode 100644
index 000000000..09b6e7205
--- /dev/null
+++ b/Docs/Scenery/OBJ.format.txt
@@ -0,0 +1,3013 @@
+B1. Object Files (.obj)
+
+Object files define the geometry and other properties for objects in
+Wavefront's Advanced Visualizer. Object files can also be used to
+transfer geometric data back and forth between the Advanced Visualizer
+and other applications.
+
+Object files can be in ASCII format (.obj) or binary format (.mod).
+This appendix describes the ASCII format for object files. These files
+must have the extension .obj.
+
+In this release, the .obj file format supports both polygonal objects
+and free-form objects. Polygonal geometry uses points, lines, and faces
+to define objects while free-form geometry uses curves and surfaces.
+
+About this section
+
+The .obj appendix is for those who want to use the .obj format to
+translate geometric data from other software applications to Wavefront
+products. It also provides information for Advanced Visualizer users
+who want detailed information on the Wavefront .obj file format.
+
+If you are a 2.11 user and want to understand the significance of the
+3.0 release and how it affects your existing files, you may be
+especially interested in the section called "Superseded statements" at
+the end of the appendix. The section, "Patches and free-form surfaces,"
+gives examples of how 2.11 patches look in 3.0.
+
+How this section is organized
+
+Most of this appendix describes the different parts of an .obj file and
+how those parts are arranged in the file. The three sections at the end
+of the appendix provide background information on the 3.0 release of
+the .obj format.
+
+The .obj appendix includes the following sections:
+
+o       File structure
+
+o       General statement
+
+o       Vertex data
+
+o       Specifying free-form curves/surfaces
+
+o       Free-form curve/surface attributes
+
+o       Elements
+
+o       Free-form curve/surface body statements
+
+o       Connectivity between free-form surfaces
+
+o       Grouping
+
+o       Display/render attributes
+
+o       Comments
+
+o       Mathematics for free-form curves/surfaces
+
+o       Superseded statements
+
+o       Patches and free-form surfaces
+
+---------------
+
+    The curve and surface extensions to the .obj file format were
+    developed in conjunction with mental images GmbH&Co.KG, Berlin,
+    Germany, as part of a joint development project to incorporate
+    free-form surfaces into Wavefront's Advanced Visualizer.
+
+File structure
+
+The following types of data may be included in an .obj file. In this
+list, the keyword (in parentheses) follows the data type.
+
+Vertex data
+
+o       geometric vertices (v)
+
+o       texture vertices (vt)
+
+o       vertex normals (vn)
+
+o       parameter space vertices (vp)
+	Free-form curve/surface attributes
+
+o       rational or non-rational forms of curve or surface type:
+	basis matrix, Bezier, B-spline, Cardinal, Taylor (cstype)
+
+o       degree (deg)
+
+o       basis matrix (bmat)
+
+o       step size (step)
+
+Elements
+
+o       point (p)
+
+o       line (l)
+
+o       face (f)
+
+o       curve (curv)
+
+o       2D curve (curv2)
+
+o       surface (surf)
+
+Free-form curve/surface body statements
+
+o       parameter values (parm)
+
+o       outer trimming loop (trim)
+
+o       inner trimming loop (hole)
+
+o       special curve (scrv)
+
+o       special point (sp)
+
+o       end statement (end)
+
+Connectivity between free-form surfaces
+
+
+o       connect (con)
+
+Grouping
+
+o       group name (g)
+
+o       smoothing group (s)
+
+o       merging group (mg)
+
+o       object name (o)
+
+Display/render attributes
+
+o       bevel interpolation (bevel)
+
+o       color interpolation (c_interp)
+
+o       dissolve interpolation (d_interp)
+
+o       level of detail (lod)
+
+o       material name (usemtl)
+
+o       material library (mtllib)
+
+o       shadow casting (shadow_obj)
+
+o       ray tracing (trace_obj)
+
+o       curve approximation technique (ctech)
+
+o       surface approximation technique (stech)
+
+
+The following diagram shows how these parts fit together in a typical
+.obj file.
+
+Figure  B1-1.   Typical .obj file structure
+
+General statement
+
+call  filename.ext arg1 arg2 . . .
+
+    Reads the contents of the specified .obj or .mod file at this
+    location.  The call statement can be inserted into .obj files using
+    a text editor.
+
+    filename.ext is the name of the .obj or .mod file to be read. You
+    must include the extension with the filename.
+
+    arg1  arg2 . . .  specifies a series of optional integer arguments
+    that are passed to the called file. There is no limit to the number
+    of nested calls that can be made.
+
+    Arguments passed to the called file are substituted in the same way
+    as in UNIX scripts; for example, $1 in the called file is replaced
+    by arg1,  $2 in the called file is replaced by arg2, and so on.
+
+    If the frame number is needed in the called file for variable
+    substitution, "$1" must be used as the first argument in the call
+    statement. For example:
+
+	call filename.obj $1
+
+    Then the statement in the called file,
+
+	scmp filename.pv $1
+
+    will work as expected. For more information on the scmp statement,
+    see appendix C, Variable Substitution for more information.
+
+    Another method to do the same thing is:
+
+	scmp filename.pv $1
+
+	call filename.obj
+
+    Using this method, the scmp statement provides the .pv file for all
+    subsequently called .obj or .mod files.
+
+csh command
+
+csh -command
+
+    Executes the requested UNIX command. If the UNIX command returns an
+    error, the parser flags an error during parsing.
+
+    If a dash (-) precedes the UNIX command, the error is ignored.
+
+    command is the UNIX command.
+
+Vertex data
+
+Vertex data provides coordinates for:
+
+o        geometric vertices
+
+o        texture vertices
+
+o        vertex normals
+
+For free-form objects, the vertex data also provides:
+
+o        parameter space vertices
+
+The vertex data is represented by four vertex lists; one for each type
+of vertex coordinate. A right-hand coordinate system is used to specify
+the coordinate locations.
+
+The following sample is a portion of an .obj file that contains the
+four types of vertex information.
+
+    v      -5.000000       5.000000       0.000000
+    v      -5.000000      -5.000000       0.000000
+    v       5.000000      -5.000000       0.000000
+    v       5.000000       5.000000       0.000000
+    vt     -5.000000       5.000000       0.000000
+    vt     -5.000000      -5.000000       0.000000
+    vt      5.000000      -5.000000       0.000000
+    vt      5.000000       5.000000       0.000000
+    vn      0.000000       0.000000       1.000000
+    vn      0.000000       0.000000       1.000000
+    vn      0.000000       0.000000       1.000000
+    vn      0.000000       0.000000       1.000000
+    vp      0.210000       3.590000
+    vp      0.000000       0.000000
+    vp      1.000000       0.000000
+    vp      0.500000       0.500000
+
+
+
+When vertices are loaded into the Advanced Visualizer, they are
+sequentially numbered, starting with 1. These reference numbers are
+used in element statements.
+
+Syntax
+
+The following syntax statements are listed in order of complexity.
+
+v x y z w
+
+    Polygonal and free-form geometry statement.
+
+    Specifies a geometric vertex and its x y z coordinates. Rational
+    curves and surfaces require a fourth homogeneous coordinate, also
+    called the weight.
+
+    x y z are the x, y, and z coordinates for the vertex. These are
+    floating point numbers that define the position of the vertex in
+    three dimensions.
+
+    w is the weight required for rational curves and surfaces. It is
+    not required for non-rational curves and surfaces. If you do not
+    specify a value for w, the default is 1.0.
+
+    NOTE: A positive weight value is recommended. Using zero or
+    negative values may result in an undefined point in a curve or
+    surface.
+
+vp u v w
+
+    Free-form geometry statement.
+
+    Specifies a point in the parameter space of a curve or surface.
+
+    The usage determines how many coordinates are required. Special
+    points for curves require a 1D control point (u only) in the
+    parameter space of the curve. Special points for surfaces require a
+    2D point (u and v) in the parameter space of the surface. Control
+    points for non-rational trimming curves require u and v
+    coordinates. Control points for rational trimming curves require u,
+    v, and w (weight) coordinates.
+
+    u is the point in the parameter space of a curve or the first
+    coordinate in the parameter space of a surface.
+
+    v is the second coordinate in the parameter space of a surface.
+
+    w is the weight required for rational trimming curves. If you do
+    not specify a value for w, it defaults to 1.0.
+
+    NOTE: For additional information on parameter vertices, see the
+    curv2 and sp statements
+
+vn i j k
+
+    Polygonal and free-form geometry statement.
+
+    Specifies a normal vector with components i, j, and k.
+
+    Vertex normals affect the smooth-shading and rendering of geometry.
+    For polygons, vertex normals are used in place of the actual facet
+    normals.  For surfaces, vertex normals are interpolated over the
+    entire surface and replace the actual analytic surface normal.
+
+    When vertex normals are present, they supersede smoothing groups.
+
+    i j k are the i, j, and k coordinates for the vertex normal. They
+    are floating point numbers.
+
+vt u v w
+
+    Vertex statement for both polygonal and free-form geometry.
+
+    Specifies a texture vertex and its coordinates. A 1D texture
+    requires only u texture coordinates, a 2D texture requires both u
+    and v texture coordinates, and a 3D texture requires all three
+    coordinates.
+
+    u is the value for the horizontal direction of the texture.
+
+    v is an optional argument.
+
+    v is the value for the vertical direction of the texture. The
+    default is 0.
+
+    w is an optional argument.
+
+    w is a value for the depth of the texture. The default is 0.
+
+Specifying free-form curves/surfaces
+
+There are three steps involved in specifying a free-form curve or
+surface element.
+
+o       Specify the type of curve or surface (basis matrix, Bezier,
+	B-spline, Cardinal, or Taylor) using free-form curve/surface
+	attributes.
+
+o       Describe the curve or surface with element statements.
+
+o       Supply additional information, using free-form curve/surface
+	body statements
+
+The next three sections of this appendix provide detailed information
+on each of these steps.
+
+Data requirements for curves and surfaces
+
+All curves and surfaces require a certain set of data. This consists of
+the following:
+
+Free-form curve/surface attributes
+
+o       All curves and surfaces require type data, which is given with
+	the cstype statement.
+
+o       All curves and surfaces require degree data, which is given
+	with the deg statement.
+
+o       Basis matrix curves or surfaces require a bmat statement.
+
+o       Basis matrix curves or surfaces also require a step size, which
+	is given with the step statement.
+
+Elements
+
+o       All curves and surfaces require control points, which are
+	referenced in the curv, curv2, or surf statements.
+
+o       3D curves and surfaces require a parameter range, which is
+	given in the curv and surf statements, respectively.
+
+Free-form curve/surface body statements
+
+o       All curves and surfaces require a set of global parameters or a
+	knot vector, both of which are given with the parm statement.
+
+o       All curves and surfaces body statements require an explicit end
+	statement.
+
+Error checks
+
+The above set of data starts out empty with no default values when
+reading of an .obj file begins. While the file is being read,
+statements are encountered, information is accumulated, and some errors
+may be reported.
+
+When the end statement is encountered, the following error checks,
+which involve consistency between various statements, are performed:
+
+o       All required information is present.
+
+o       The number of control points, number of parameter values
+	(knots), and degree are consistent with the curve or surface
+	type. If the type is bmatrix, the step size is also consistent.
+	(For more information, refer to the parameter vector equations
+	in the section, "Mathematics of free-form curves/ surfaces" at
+	the end of appendix B1.)
+
+o       If the type is bmatrix and the degree is n, the size of the
+	basis matrix is (n + 1) x (n + 1).
+
+Note that any information given by the state-setting statements remains
+in effect from one curve or surface to the next. Information given
+within a curve or surface body is only effective for the curve or
+surface it is given with.
+
+
+
+Free-form curve/surface attributes
+
+Five types of free-form geometry are available in the .obj file
+format:
+
+o       Bezier
+
+o       basis matrix
+
+o       B-spline
+
+o       Cardinal
+
+o       Taylor
+
+You can apply these types only to curves and surfaces. Each of these
+five types can be rational or non-rational.
+
+In addition to specifying the type, you must define the degree for the
+curve or surface. For basis matrix curve and surface elements, you must
+also specify the basis matrix and step size.
+
+All free-form curve and surface attribute statements are state-setting.
+This means that once an attribute statement is set, it applies to all
+elements that follow until it is reset to a different value.
+
+Syntax
+
+The following syntax statements are listed in order of use.
+
+cstype rat type
+
+    Free-form geometry statement.
+
+    Specifies the type of curve or surface and indicates a rational or
+    non-rational form.
+
+    rat is an optional argument.
+
+    rat specifies a rational form for the curve or surface type. If rat
+    is not included, the curve or surface is non-rational
+
+    type specifies the curve or surface type. Allowed types are:
+
+	bmatrix		basis matrix
+
+	bezier		Bezier
+
+	bspline		B-spline
+
+	cardinal        Cardinal
+
+	taylor		Taylor
+
+    There is no default. A value must be supplied.
+
+deg degu degv
+
+    Free-form geometry statement.
+
+    Sets the polynomial degree for curves and surfaces.
+
+    degu is the degree in the u direction. It is required for both
+    curves and surfaces.
+
+    degv is the degree in the v direction. It is required only for
+    surfaces. For Bezier, B-spline, Taylor, and basis matrix, there is
+    no default; a value must be supplied. For Cardinal, the degree is
+    always 3. If some other value is given for Cardinal, it will be
+    ignored.
+
+bmat u matrix
+
+bmat v matrix
+
+    Free-form geometry statement.
+
+    Sets the basis matrices used for basis matrix curves and surfaces.
+    The u and v values must be specified in separate bmat statements.
+
+    NOTE: The deg statement must be given before the bmat statements
+    and the size of the matrix must be appropriate for the degree.
+
+    u specifies that the basis matrix is applied in the u direction.
+
+    v specifies that the basis matrix is applied in the v direction.
+
+    matrix lists the contents of the basis matrix with column subscript
+    j varying the fastest. If n is the degree in the given u or v
+    direction, the matrix (i,j) should be of size (n + 1) x (n + 1).
+
+    There is no default. A value must be supplied.
+
+    NOTE: The arrangement of the matrix is different from that commonly
+    found in other references. For more information, see the examples
+    at the end of this section and also the section, "Mathematics for
+    free-form curves and surfaces."
+
+step stepu stepv
+
+    Free-form geometry statement.
+
+    Sets the step size for curves and surfaces that use a basis
+    matrix.
+
+    stepu is the step size in the u direction. It is required for both
+    curves and surfaces that use a basis matrix.
+
+    stepv is the step size in the v direction. It is required only for
+    surfaces that use a basis matrix. There is no default. A value must
+    be supplied.
+
+    When a curve or surface is being evaluated and a transition from
+    one segment or patch to the next occurs, the set of control points
+    used is incremented by the step size. The appropriate step size
+    depends on the representation type, which is expressed through the
+    basis matrix, and on the degree.
+
+    That is, suppose we are given a curve with k control points:
+			{v , ... v }
+			  1       k
+
+    If the curve is of degree n, then n + 1 control points are needed
+    for each polynomial segment. If the step size is given as s, then
+    the ith polynomial segment, where i = 0 is the first segment, will
+    use the control points:
+			{v    ,...,v      }
+			  is+1      is+n+1
+
+    For example, for Bezier curves, s = n .
+
+    For surfaces, the above description applies independently to each
+    parametric direction.
+
+    When you create a file which uses the basis matrix type, be sure to
+    specify a step size appropriate for the current curve or surface
+    representation.
+
+Examples
+
+1.      Cubic Bezier surface made with a basis matrix
+
+    To create a cubic Bezier surface:
+
+	cstype bmatrix
+	deg 3 3
+	step 3 3
+	bmat u  1       -3      3       -1      \
+		0       3       -6      3       \
+		0       0       3       -3      \
+		0       0       0       1
+	bmat v  1       -3      3       -1      \
+		0       3       -6      3       \
+		0       0       3       -3      \
+		0       0       0       1
+
+2.      Hermite curve made with a basis matrix
+
+    To create a Hermite curve:
+
+	cstype bmatrix
+	deg 3
+	step 2
+	bmat u  1     0     -3      2      0       0       3      -2 \
+		0     1     -2      1      0       0      -1       1
+
+3.      Bezier in u direction with B-spline in v direction;
+	made with a basis matrix
+
+    To create a surface with a cubic Bezier in the u direction and
+    cubic uniform B-spline in the v direction:
+
+	cstype bmatrix
+	deg 3 3
+	step 3 1
+	bmat u  1      -3       3      -1 \
+		0       3      -6       3 \
+		0       0       3      -3 \
+		0       0       0       1
+	bmat v  0.16666 -0.50000  0.50000 -0.16666 \
+		0.66666  0.00000 -1.00000  0.50000 \
+		0.16666  0.50000  0.50000 -0.50000 \
+		0.00000  0.00000  0.00000  0.16666
+
+
+
+Elements
+
+For polygonal geometry, the element types available in the .obj file
+are:
+
+o       points
+
+o       lines
+
+o       faces
+
+For free-form geometry, the element types available in the .obj file
+are:
+
+o       curve
+
+o       2D curve on a surface
+
+o       surface
+
+All elements can be freely intermixed in the file.
+
+Referencing vertex data
+
+For all elements, reference numbers are used to identify geometric
+vertices, texture vertices, vertex normals, and parameter space
+vertices.
+
+Each of these types of vertices is numbered separately, starting with
+1. This means that the first geometric vertex in the file is 1, the
+second is 2, and so on. The first texture vertex in the file is 1, the
+second is 2, and so on. The numbering continues sequentially throughout
+the entire file. Frequently, files have multiple lists of vertex data.
+This numbering sequence continues even when vertex data is separated by
+other data.
+
+In addition to counting vertices down from the top of the first list in
+the file, you can also count vertices back up the list from an
+element's position in the file. When you count up the list from an
+element, the reference numbers are negative. A reference number of -1
+indicates the vertex immediately above the element. A reference number
+of -2 indicates two references above and so on.
+
+Referencing groups of vertices
+
+Some elements, such as faces and surfaces, may have a triplet of
+numbers that reference vertex data.These numbers are the reference
+numbers for a geometric vertex, a texture vertex, and a vertex normal.
+
+Each triplet of numbers specifies a geometric vertex, texture vertex,
+and vertex normal. The reference numbers must be in order and must
+separated by slashes (/).
+
+o       The first reference number is the geometric vertex.
+
+o       The second reference number is the texture vertex. It follows
+	the first slash.
+
+o       The third reference number is the vertex normal. It follows the
+	second slash.
+
+There is no space between numbers and the slashes. There may be more
+than one series of geometric vertex/texture vertex/vertex normal
+numbers on a line.
+
+The following is a portion of a sample file for a four-sided face
+element:
+
+    f 1/1/1 2/2/2 3/3/3 4/4/4
+
+Using v, vt, and vn to represent geometric vertices, texture vertices,
+and vertex normals, the statement would read:
+
+    f v/vt/vn v/vt/vn v/vt/vn v/vt/vn
+
+If there are only vertices and vertex normals for a face element (no
+texture vertices), you would enter two slashes (//). For example, to
+specify only the vertex and vertex normal reference numbers, you would
+enter:
+
+    f 1//1 2//2 3//3 4//4
+
+When you are using a series of triplets, you must be consistent in the
+way you reference the vertex data. For example, it is illegal to give
+vertex normals for some vertices, but not all.
+
+The following is an example of an illegal statement.
+
+    f 1/1/1 2/2/2 3//3 4//4
+
+Syntax
+
+The following syntax statements are listed in order of complexity of
+geometry.
+
+p  v1 v2 v3 . . .
+
+    Polygonal geometry statement.
+
+    Specifies a point element and its vertex. You can specify multiple
+    points with this statement. Although points cannot be shaded or
+    rendered, they are used by other Advanced Visualizer programs.
+
+    v is the vertex reference number for a point element. Each point
+    element requires one vertex. Positive values indicate absolute
+    vertex numbers. Negative values indicate relative vertex numbers.
+
+l  v1/vt1   v2/vt2   v3/vt3 . . .
+
+    Polygonal geometry statement.
+
+    Specifies a line and its vertex reference numbers. You can
+    optionally include the texture vertex reference numbers. Although
+    lines cannot be shaded or rendered, they are used by other Advanced
+    Visualizer programs.
+
+    The reference numbers for the vertices and texture vertices must be
+    separated by a slash (/). There is no space between the number and
+    the slash.
+
+    v is a reference number for a vertex on the line. A minimum of two
+    vertex numbers are required. There is no limit on the maximum.
+    Positive values indicate absolute vertex numbers. Negative values
+    indicate relative vertex numbers.
+
+    vt is an optional argument.
+
+    vt is the reference number for a texture vertex in the line
+    element. It must always follow the first slash.
+
+f  v1/vt1/vn1   v2/vt2/vn2   v3/vt3/vn3 . . .
+
+    Polygonal geometry statement.
+
+    Specifies a face element and its vertex reference number. You can
+    optionally include the texture vertex and vertex normal reference
+    numbers.
+
+    The reference numbers for the vertices, texture vertices, and
+    vertex normals must be separated by slashes (/). There is no space
+    between the number and the slash.
+
+    v is the reference number for a vertex in the face element. A
+    minimum of three vertices are required.
+
+    vt is an optional argument.
+
+    vt is the reference number for a texture vertex in the face
+    element. It always follows the first slash.
+
+    vn is an optional argument.
+
+    vn is the reference number for a vertex normal in the face element.
+    It must always follow the second slash.
+
+    Face elements use surface normals to indicate their orientation. If
+    vertices are ordered counterclockwise around the face, both the
+    face and the normal will point toward the viewer. If the vertex
+    ordering is clockwise, both will point away from the viewer. If
+    vertex normals are assigned, they should point in the general
+    direction of the surface normal, otherwise unpredictable results
+    may occur.
+
+    If a face has a texture map assigned to it and no texture vertices
+    are assigned in the f statement, the texture map is ignored when
+    the element is rendered.
+
+    NOTE: Any references to fo (face outline) are no longer valid as of
+    version 2.11. You can use f (face) to get the same results.
+    References to fo in existing .obj files will still be read,
+    however, they will be written out as f when the file is saved.
+
+curv u0 u1 v1 v2 . . .
+
+    Element statement for free-form geometry.
+
+    Specifies a curve, its parameter range, and its control vertices.
+    Although curves cannot be shaded or rendered, they are used by
+    other Advanced Visualizer programs.
+
+    u0 is the starting parameter value for the curve. This is a
+    floating point number.
+
+    u1 is the ending parameter value for the curve. This is a floating
+    point number.
+
+    v is the vertex reference number for a control point. You can
+    specify multiple control points. A minimum of two control points
+    are required for a curve.
+
+    For a non-rational curve, the control points must be 3D. For a
+    rational curve, the control points are 3D or 4D. The fourth
+    coordinate (weight) defaults to 1.0 if omitted.
+
+curv2  vp1  vp2   vp3. . .
+
+    Free-form geometry statement.
+
+    Specifies a 2D curve on a surface and its control points. A 2D
+    curve is used as an outer or inner trimming curve, as a special
+    curve, or for connectivity.
+
+    vp is the parameter vertex reference number for the control point.
+    You can specify multiple control points. A minimum of two control
+    points is required for a 2D curve.
+
+    The control points are parameter vertices because the curve must
+    lie in the parameter space of some surface. For a non-rational
+    curve, the control vertices can be 2D. For a rational curve, the
+    control vertices can be 2D or 3D. The third coordinate (weight)
+    defaults to 1.0 if omitted.
+
+surf  s0  s1  t0  t1  v1/vt1/vn1   v2/vt2/vn2 . . .
+
+    Element statement for free-form geometry.
+
+    Specifies a surface, its parameter range, and its control vertices.
+    The surface is evaluated within the global parameter range from s0
+    to s1 in the u direction and t0 to t1 in the v direction.
+
+    s0 is the starting parameter value for the surface in the u
+    direction.
+
+    s1 is the ending parameter value for the surface in the u
+    direction.
+
+    t0 is the starting parameter value for the surface in the v
+    direction.
+
+    t1 is the ending parameter value for the surface in the v
+    direction.
+
+    v is the reference number for a control vertex in the surface.
+
+    vt is an optional argument.
+
+    vt is the reference number for a texture vertex in the surface.  It
+    must always follow the first slash.
+
+    vn is an optional argument.
+
+    vn is the reference number for a vertex normal in the surface.  It
+    must always follow the second slash.
+
+    For a non-rational surface, the control vertices are 3D.  For a
+    rational surface the control vertices can be 3D or 4D.  The fourth
+    coordinate (weight) defaults to 1.0 if ommitted.
+
+    NOTE: For more information on the ordering of control points for
+    survaces, refer to the section on surfaces and control points in
+    "mathematics of free-form curves/surfaces" at the end of this
+    appendix.
+
+
+
+
+Examples
+
+These are examples for polygonal geometry.
+
+For examples using free-form geometry, see the examples at the end of
+the next section, "Free-form curve/surface body statements."
+
+1.	Square
+
+This example shows a square that measures two units on each side and
+faces in the positive direction (toward the camera).  Note that the
+ordering of the vertices is counterclockwise. This ordering determines
+that the square is facing forward.
+
+    v 0.000000 2.000000 0.000000
+    v 0.000000 0.000000 0.000000
+    v 2.000000 0.000000 0.000000
+    v 2.000000 2.000000 0.000000
+    f 1 2 3 4
+
+2.      Cube
+
+This is a cube that measures two units on each side. Each vertex is
+shared by three different faces.
+
+    v 0.000000 2.000000 2.000000
+    v 0.000000 0.000000 2.000000
+    v 2.000000 0.000000 2.000000
+    v 2.000000 2.000000 2.000000
+    v 0.000000 2.000000 0.000000
+    v 0.000000 0.000000 0.000000
+    v 2.000000 0.000000 0.000000
+    v 2.000000 2.000000 0.000000
+    f 1 2 3 4
+    f 8 7 6 5
+    f 4 3 7 8
+    f 5 1 4 8
+    f 5 6 2 1
+    f 2 6 7 3
+
+3.      Cube with negative reference numbers
+
+This is a cube with negative vertex reference numbers. Each element
+references the vertices stored immediately above it in the file. Note
+that vertices are not shared.
+
+v 0.000000 2.000000 2.000000
+v 0.000000 0.000000 2.000000
+v 2.000000 0.000000 2.000000
+v 2.000000 2.000000 2.000000
+f -4 -3 -2 -1
+
+v 2.000000 2.000000 0.000000
+v 2.000000 0.000000 0.000000
+v 0.000000 0.000000 0.000000
+v 0.000000 2.000000 0.000000
+f -4 -3 -2 -1
+
+v 2.000000 2.000000 2.000000
+v 2.000000 0.000000 2.000000
+v 2.000000 0.000000 0.000000
+v 2.000000 2.000000 0.000000
+f -4 -3 -2 -1
+
+v 0.000000 2.000000 0.000000
+v 0.000000 2.000000 2.000000
+v 2.000000 2.000000 2.000000
+v 2.000000 2.000000 0.000000
+f -4 -3 -2 -1
+
+v 0.000000 2.000000 0.000000
+v 0.000000 0.000000 0.000000
+v 0.000000 0.000000 2.000000
+v 0.000000 2.000000 2.000000
+f -4 -3 -2 -1
+
+v 0.000000 0.000000 2.000000
+v 0.000000 0.000000 0.000000
+v 2.000000 0.000000 0.000000
+v 2.000000 0.000000 2.000000
+f -4 -3 -2 -1
+
+
+
+Free-form curve/surface body statements
+
+You can specify additional information for free-form curve and surface
+elements using a series of statements called body statements. The
+series is concluded by an end statement.
+
+Body statements are valid only when they appear between the free-form
+element statement (curv, curv2, surf) and the end statement. If they
+are anywhere else in the .obj file, they do not have any effect.
+
+You can use body statements to specify the following values:
+
+o       parameter
+
+o       knot vector
+
+o       trimming loop
+
+o       hole
+
+o       special curve
+
+o       special point
+
+You cannot use any other statements between the free-form curve or
+surface statement and the end statement. Using any other of type of
+statement may cause unpredictable results.
+
+This portion of a sample file shows the knot vector values for a
+rational B-spline surface with a trimming loop. Notice the end
+statement to conclude the body statements.
+
+    cstype rat bspline
+    deg 2 2
+    surf -1.0 2.5 -2.0 2.0 -9 -8 -7 -6 -5 -4 -3 -2 -1
+    parm u -1.00 -1.00 -1.00 2.50 2.50 2.50
+    parm v -2.00 -2.00 -2.00 -2.00 -2.00 -2.00
+    trim 0.0 2.0 1
+    end
+
+Parameter values and knot vectors
+
+All curve and surface elements require a set of parameter values.
+
+For polynomial curves and surfaces, this specifies global parameter
+values. For B-spline curves and surfaces, this specifies the knot
+vectors.
+
+For surfaces, the parameter values must be specified for both the u and
+v directions. For curves, the parameter values must be specified for
+only the u direction.
+
+If multiple parameter value statements for the same parametric
+direction are used inside a single curve or surface body, the last
+statement is used.
+
+Trimming loops and holes
+
+The trimming loop statement builds a single outer trimming loop as a
+sequence of curves which lie on a given surface.
+
+The hole statement builds a single inner trimming loop as a sequence of
+curves which lie on a given surface. The inner loop creates a hole.
+
+The curves are referenced by number in the same way vertices are
+referenced by face elements.
+
+The individual curves must lie end-to-end to form a closed loop which
+does not intersect itself and which lies within the parameter range
+specified for the surface. The loop as a whole may be oriented in
+either direction (clockwise or counterclockwise).
+
+To cut one or more holes in a region, use a trim statement followed by
+one or more hole statements. To introduce another trimmed region in the
+same surface, use another trim statement followed by one or more hole
+statements. The ordering that associates holes and the regions they cut
+is important and must be maintained.
+
+If the first trim statement in the sequence is omitted, the enclosing
+outer trimming loop is taken to be the parameter range of the surface.
+If no trim or hole statements are specified, then the surface is
+trimmed at its parameter range.
+
+This portion of a sample file shows a non-rational Bezier surface with
+two regions, each with a single hole:
+
+    cstype bezier
+    deg 1 1
+    surf 0.0 2.0 0.0 2.0 1 2 3 4
+    parm u 0.00 2.00
+    parm v 0.00 2.00
+    trim 0.0 4.0 1
+    hole 0.0 4.0 2
+    trim 0.0 4.0 3
+    hole 0.0 4.0 4
+    end
+
+Special curve
+
+A special curve statement builds a single special curve as a sequence
+of curves which lie on a given surface.
+
+The curves are referenced by number in the same way vertices are
+referenced by face elements.
+
+A special curve is guaranteed to be included in any triangulation of
+the surface. This means that the line formed by approximating the
+special curve with a sequence of straight line segments will actually
+appear as a sequence of triangle edges in the final triangulation.
+
+Special point
+
+A special point statement specifies that special geometric points are
+to be associated with a curve or surface. For space curves and trimming
+curves, the parameter vertices must be 1D. For surfaces, the parameter
+vertices must be 2D.
+
+These special points will be included in any linear approximation of
+the curve or surface.
+
+For space curves, this means that the point corresponding to the given
+curve parameter is included as one of the vertices in an approximation
+consisting of a sequence of line segments.
+
+For surfaces, this means that the point corresponding to the given
+surface parameters is included as a triangle vertex in the
+triangulation.
+
+For trimming curves, the treatment is slightly different: a special
+point on a trimming curve is essentially the same as a special point on
+the surface it trims.
+
+The following portion of a sample files shows special points for a
+rational Bezier 2D curve on a surface.
+
+    vp -0.675  1.850  3.000
+    vp  0.915  1.930
+    vp  2.485  0.470  2.000
+    vp  2.485 -1.030
+    vp  1.605 -1.890 10.700
+    vp -0.745 -0.654  0.500
+    cstype rat bezier
+    curv2 -6 -5 -4 -3 -2 -1 -6
+    parm u 0.00 1.00 2.00
+    sp 2 3
+    end
+
+Syntax
+
+The following syntax statement are listed in order of normal use.
+
+parm u p1 p2 p3. . .
+
+parm v p1 p2 p3 . . .
+
+    Body statement for free-form geometry.
+
+    Specifies global parameter values. For B-spline curves and
+    surfaces, this specifies the knot vectors.
+
+    u is the u direction for the parameter values.
+
+    v is the v direction for the parameter values.
+
+    To set u and v values, use separate command lines.
+
+    p is the global parameter or knot value. You can specify multiple
+    values. A minimum of two parameter values are required. Parameter
+    values must increase monotonically. The type of surface and the
+    degree dictate the number of values required.
+
+trim  u0  u1  curv2d  u0  u1  curv2d . . .
+
+    Body statement for free-form geometry.
+
+    Specifies a sequence of curves to build a single outer trimming
+    loop.
+
+    u0 is the starting parameter value for the trimming curve curv2d.
+
+    u1 is the ending parameter value for the trimming curve curv2d.
+
+    curv2d is the index of the trimming curve lying in the parameter
+    space of the surface. This curve must have been previously defined
+    with the curv2 statement.
+
+hole  u0  u1  curv2d  u0  u1  curv2d . . .
+
+    Body statement for free-form geometry.
+
+    Specifies a sequence of curves to build a single inner trimming
+    loop (hole).
+
+    u0 is the starting parameter value for the trimming curve curv2d.
+
+    u1 is the ending parameter value for the trimming curve curv2d.
+
+    curv2d is the index of the trimming curve lying in the parameter
+    space of the surface. This curve must have been previously defined
+    with the curv2 statement.
+
+scrv u0 u1 curv2d u0 u1 curv2d . . .
+
+    Body statement for free-form geometry.
+
+    Specifies a sequence of curves which lie on the given surface to
+    build a single special curve.
+
+    u0 is the starting parameter value for the special curve curv2d.
+
+    u1 is the ending parameter value for the special curve curv2d.
+
+    curv2d is the index of the special curve lying in the parameter
+    space of the surface. This curve must have been previously defined
+    with the curv2 statement.
+
+sp vp1  vp. . .
+
+    Body statement for free-form geometry.
+
+    Specifies special geometric points to be associated with a curve or
+    surface. For space curves and trimming curves, the parameter
+    vertices must be 1D. For surfaces, the parameter vertices must be
+    2D.
+
+    vp is the reference number for the parameter vertex of a special
+    point to be associated with the parameter space point of the curve
+    or surface.
+
+end
+
+    Body statement for free-form geometry.
+
+    Specifies the end of a curve or surface body begun by a curv,
+    curv2, or surf statement.
+
+Examples
+
+1.      Taylor curve
+
+    For creating a single-segment Taylor polynomial curve of the form:
+
+                                   2         3         4
+	x =  3.00 +  2.30t +  7.98t  +  8.30t  +  6.34t 
+
+                                   2         3         4
+	y =  1.00 - 10.10t +  5.40t  -  4.70t  +  2.03t 
+
+                                   2         3         4
+	z = -2.50 +  0.50t -  7.00t  + 18.10t  +  0.08t 
+
+
+and evaluated between the global parameters 0.5 and 1.6:
+
+	v       3.000    1.000   -2.500
+	v       2.300  -10.100    0.500
+	v       7.980    5.400   -7.000
+	v       8.300   -4.700   18.100
+	v       6.340    2.030    0.080
+	cstype taylor
+	deg 4
+	curv 0.500 1.600 1 2 3 4 5
+	parm u 0.000 2.000
+	end
+
+2.      Bezier curve
+
+This example shows a non-rational Bezier curve with 13 control points.
+
+    v -2.300000 1.950000 0.000000
+    v -2.200000 0.790000 0.000000
+    v -2.340000 -1.510000 0.000000
+    v -1.530000 -1.490000 0.000000
+    v -0.720000 -1.470000 0.000000
+    v -0.780000 0.230000 0.000000
+    v 0.070000 0.250000 0.000000
+    v 0.920000 0.270000 0.000000
+    v 0.800000 -1.610000 0.000000
+    v 1.620000 -1.590000 0.000000
+    v 2.440000 -1.570000 0.000000
+    v 2.690000 0.670000 0.000000
+    v 2.900000 1.980000 0.000000
+    # 13 vertices
+
+    cstype bezier
+    ctech cparm 1.000000
+    deg 3
+    curv 0.000000 4.000000 1 2 3 4 5 6 7 8 9 10 \
+    11 12 13
+    parm u 0.000000 1.000000 2.000000 3.000000  \
+    4.000000
+    end
+    # 1 element
+
+
+
+3.      B-spline surface
+
+This is an example of a cubic B-spline surface.
+
+    g bspatch
+    v -5.000000 -5.000000 -7.808327
+    v -5.000000 -1.666667 -7.808327
+    v -5.000000 1.666667 -7.808327
+    v -5.000000 5.000000 -7.808327
+    v -1.666667 -5.000000 -7.808327
+    v -1.666667 -1.666667 11.977780
+    v -1.666667 1.666667 11.977780
+    v -1.666667 5.000000 -7.808327
+    v 1.666667 -5.000000 -7.808327
+    v 1.666667 -1.666667 11.977780
+    v 1.666667 1.666667 11.977780
+    v 1.666667 5.000000 -7.808327
+    v 5.000000 -5.000000 -7.808327
+    v 5.000000 -1.666667 -7.808327
+    v 5.000000 1.666667 -7.808327
+    v 5.000000 5.000000 -7.808327
+    # 16 vertices
+
+    cstype bspline
+    stech curv 0.5 10.000000
+    deg 3 3
+    8surf 0.000000 1.000000 0.000000 1.000000 13 14 \ 15 16 9 10 11 12 5 6
+    7 8 1 2 3 4
+    parm u -3.000000 -2.000000 -1.000000 0.000000  \
+    1.000000 2.000000 3.000000 4.000000
+    parm v -3.000000 -2.000000 -1.000000 0.000000  \
+    1.000000 2.000000 3.000000 4.000000
+    end
+    # 1 element
+
+
+4.      Cardinal surface
+
+This example shows a Cardinal surface.
+
+    v -5.000000 -5.000000 0.000000
+    v -5.000000 -1.666667 0.000000
+    v -5.000000 1.666667 0.000000
+    v -5.000000 5.000000 0.000000
+    v -1.666667 -5.000000 0.000000
+    v -1.666667 -1.666667 0.000000
+    v -1.666667 1.666667 0.000000
+    v -1.666667 5.000000 0.000000
+    v 1.666667 -5.000000 0.000000
+    v 1.666667 -1.666667 0.000000
+    v 1.666667 1.666667 0.000000
+    v 1.666667 5.000000 0.000000
+    v 5.000000 -5.000000 0.000000
+    v 5.000000 -1.666667 0.000000
+    v 5.000000 1.666667 0.000000
+    v 5.000000 5.000000 0.000000
+    # 16 vertices
+
+    cstype cardinal
+    stech cparma 1.000000 1.000000
+    deg 3 3
+    surf 0.000000 1.000000 0.000000 1.000000 13 14 \
+    15 16 9 10 11 12 5 6 7 8 1 2 3 4
+    parm u 0.000000 1.000000
+    parm v 0.000000 1.000000
+    end
+    # 1 element
+
+
+5.      Rational B-spline surface
+
+This example creates a second-degree, rational B-spline surface using
+open, uniform knot vectors. A texture map is applied to the surface.
+
+    v -1.3 -1.0  0.0
+    v  0.1 -1.0  0.4  7.6
+    v  1.4 -1.0  0.0  2.3
+    v -1.4  0.0  0.2
+    v  0.1  0.0  0.9  0.5
+    v  1.3  0.0  0.4  1.5
+    v -1.4  1.0  0.0  2.3
+    v  0.1  1.0  0.3  6.1
+    v  1.1  1.0  0.0  3.3
+    vt 0.0  0.0
+    vt 0.5  0.0
+    vt 1.0  0.0
+    vt 0.0  0.5
+    vt 0.5  0.5
+    vt 1.0  0.5
+    vt 0.0  1.0
+    vt 0.5  1.0
+    vt 1.0  1.0
+    cstype rat bspline
+    deg 2 2
+    surf 0.0 1.0 0.0 1.0 1/1 2/2 3/3 4/4 5/5 6/6 \
+    7/7 8/8 9/9
+    parm u 0.0 0.0 0.0 1.0 1.0 1.0
+    parm v 0.0 0.0 0.0 1.0 1.0 1.0
+    end
+
+
+6.      Trimmed NURB surface
+
+This is a complete example of a file containing a trimmed NURB surface
+with negative reference numbers for vertices.
+
+    # trimming curve
+    vp -0.675  1.850  3.000
+    vp  0.915  1.930
+    vp  2.485  0.470  2.000
+    vp  2.485 -1.030
+    vp  1.605 -1.890 10.700
+    vp -0.745 -0.654  0.500
+    cstype rat bezier
+    deg 3
+    curv2 -6 -5 -4 -3 -2 -1 -6
+    parm u 0.00 1.00 2.00
+    end
+    # surface
+    v -1.350 -1.030 0.000
+    v  0.130 -1.030 0.432 7.600
+    v  1.480 -1.030 0.000 2.300
+    v -1.460  0.060 0.201
+    v  0.120  0.060 0.915 0.500
+    v  1.380  0.060 0.454 1.500
+    v -1.480  1.030 0.000 2.300
+    v  0.120  1.030 0.394 6.100
+    v  1.170  1.030 0.000 3.300
+    cstype rat bspline
+    deg 2 2
+    surf -1.0 2.5 -2.0 2.0 -9 -8 -7 -6 -5 -4 -3 -2 -1
+    parm u -1.00 -1.00 -1.00 2.50 2.50 2.50
+    parm v -2.00 -2.00 -2.00 -2.00 -2.00 -2.00
+    trim 0.0 2.0 1
+    end
+
+
+7.      Two trimming regions with a hole
+
+This example shows a Bezier surface with two trimming regions, each
+with a hole in them.
+
+    # outer loop of first region
+    deg 1
+    cstype bezier
+    vp 0.100 0.100
+    vp 0.900 0.100
+    vp 0.900 0.900
+    vp 0.100 0.900
+    curv2 1 2 3 4 1
+    parm u 0.00 1.00 2.00 3.00 4.00
+    end
+    # hole in first region
+    vp 0.300 0.300
+    vp 0.700 0.300
+    vp 0.700 0.700
+    vp 0.300 0.700
+    curv2 5 6 7 8 5
+    parm u 0.00 1.00 2.00 3.00 4.00
+    end
+    # outer loop of second region
+    vp 1.100 1.100
+    vp 1.900 1.100
+    vp 1.900 1.900
+    vp 1.100 1.900
+    curv2 9 10 11 12 9
+    parm u 0.00 1.00 2.00 3.00 4.00
+    end
+    # hole in second region
+    vp 1.300 1.300
+    vp 1.700 1.300
+    vp 1.700 1.700
+    vp 1.300 1.700
+    curv2 13 14 15 16 13
+    parm u 0.00 1.00 2.00 3.00 4.00
+    end
+    # surface
+    v 0.000 0.000 0.000
+    v 1.000 0.000 0.000
+    v 0.000 1.000 0.000
+    v 1.000 1.000 0.000
+    deg 1 1
+    cstype bezier
+    surf 0.0 2.0 0.0 2.0 1 2 3 4
+    parm u 0.00 2.00
+    parm v 0.00 2.00
+    trim 0.0 4.0 1
+    hole 0.0 4.0 2
+    trim 0.0 4.0 3
+    hole 0.0 4.0 4
+    end
+
+
+8.      Trimming with a special curve
+This example is similar to the trimmed NURB surface example (6), except
+there is a special curve on the surface. This example uses negative
+vertex numbers.
+
+    # trimming curve
+    vp -0.675  1.850  3.000
+    vp  0.915  1.930
+    vp  2.485  0.470  2.000
+    vp  2.485 -1.030
+    vp  1.605 -1.890 10.700
+    vp -0.745 -0.654  0.500
+    cstype rat bezier
+    deg 3
+    curv2 -6 -5 -4 -3 -2 -1 -6
+    parm u 0.00 1.00 2.00
+    end
+    # special curve
+    vp -0.185  0.322
+    vp  0.214  0.818
+    vp  1.652  0.207
+    vp  1.652 -0.455
+    curv2 -4 -3 -2 -1
+    parm u 2.00 10.00
+    end
+    # surface
+    v -1.350 -1.030 0.000
+    v  0.130 -1.030 0.432 7.600
+    v  1.480 -1.030 0.000 2.300
+    v -1.460  0.060 0.201
+    v  0.120  0.060 0.915 0.500
+    v  1.380  0.060 0.454 1.500
+    v -1.480  1.030 0.000 2.300
+    v  0.120  1.030 0.394 6.100
+    v  1.170  1.030 0.000 3.300
+    cstype rat bspline
+    deg 2 2
+    surf -1.0 2.5 -2.0 2.0 -9 -8 -7 -6 -5 -4 -3 -2 -1
+    parm u -1.00 -1.00 -1.00 2.50 2.50 2.50
+    parm v -2.00 -2.00 -2.00 2.00 2.00 2.00
+    trim 0.0 2.0 1
+    scrv 4.2 9.7 2
+    end
+
+
+9.      Trimming with special points
+
+This example extends the trimmed NURB surface example (6) to include
+special points on both the trimming curve and surface. A space curve
+with a special point is also included. This example uses negative
+vertex numbers.
+
+    # special point and space curve data
+    vp 0.500
+    vp 0.700
+    vp 1.100
+    vp 0.200 0.950
+    v  0.300 1.500 0.100
+    v  0.000  0.000  0.000
+    v  1.000  1.000  0.000
+    v  2.000  1.000  0.000
+    v  3.000  0.000  0.000
+    cstype bezier
+    deg 3
+    curv 0.2 0.9 -4 -3 -2 -1
+    sp 1
+    parm u 0.00 1.00
+    end
+    # trimming curve
+    vp -0.675  1.850  3.000
+    vp  0.915  1.930
+    vp  2.485  0.470  2.000
+    vp  2.485 -1.030
+    vp  1.605 -1.890 10.700
+    vp -0.745 -0.654  0.500
+    cstype rat bezier
+    curv2 -6 -5 -4 -3 -2 -1 -6
+    parm u 0.00 1.00 2.00
+    sp 2 3
+    end
+    # surface
+    v -1.350 -1.030 0.000
+    v  0.130 -1.030 0.432 7.600
+    v  1.480 -1.030 0.000 2.300
+    v -1.460  0.060 0.201
+    v  0.120  0.060 0.915 0.500
+    v  1.380  0.060 0.454 1.500
+    v -1.480  1.030 0.000 2.300
+    v  0.120  1.030 0.394 6.100
+    v  1.170  1.030 0.000 3.300
+    cstype rat bspline
+    deg 2 2
+    surf -1.0 2.5 -2.0 2.0 -9 -8 -7 -6 -5 -4 -3 -2 -1
+    parm u -1.00 -1.00 -1.00 2.50 2.50 2.50
+    parm v -2.00 -2.00 -2.00 2.00 2.00 2.00
+    trim 0.0 2.0 1
+    sp 4
+    end
+
+Connectivity between free-form surfaces
+
+Connectivity connects two surfaces along their trimming curves.
+
+The con statement specifies the first surface with its trimming curve
+and the second surface with its trimming curve. This information is
+useful for edge merging. Without this surface and curve data,
+connectivity must be determined numerically at greater expense and with
+reduced accuracy using the mg statement.
+
+Connectivity between surfaces in different merging groups is ignored.
+Also, although connectivity which crosses points of C1discontinuity in
+trimming curves is legal, it is not recommended. Instead, use two
+connectivity statements which meet at the point of discontinuity.
+
+The two curves and their starting and ending parameters should all map
+to the same curve and starting and ending points in object space.
+
+Syntax
+
+con  surf_1  q0_1  q1_1   curv2d_1   surf_2  q0_2  q1_2  curv2d_2
+
+    Free-form geometry statement.
+
+    Specifies connectivity between two surfaces.
+
+    surf_1 is the index of the first surface.
+
+    q0_1 is the starting parameter for the curve referenced by
+    curv2d_1.
+
+    q1_1 is the ending parameter for the curve referenced by curv2d_1.
+
+    curv2d_1 is the index of a curve on the first surface. This curve
+    must have been previously defined with the curv2 statement.
+
+    surf_2 is the index of the second surface.
+
+    q0_2 is the starting parameter for the curve referenced by
+    curv2d_2.
+
+    q1_2 is the ending parameter for the curve referenced by curv2d_2.
+
+    curv2d_2 is the index of a curve on the second surface. This curve
+    must have been previously defined with the curv2 statement.
+
+Example
+
+1.      Connectivity between two surfaces
+
+This example shows the connectivity between two surfaces with trimming
+curves.
+
+    cstype bezier
+    deg 1 1
+
+    v 0 0 0
+    v 1 0 0
+    v 0 1 0
+    v 1 1 0
+
+    vp 0 0
+    vp 1 0
+    vp 1 1
+    vp 0 1
+
+    curv2 1 2 3 4 1
+    parm u 0.0 1.0 2.0 3.0 4.0
+    end
+
+    surf 0.0 1.0 0.0 1.0 1 2 3 4
+    parm u 0.0 1.0
+    parm v 0.0 1.0
+    trim 0.0 4.0 1
+    end
+
+    v 1 0 0
+    v 2 0 0
+    v 1 1 0
+    v 2 1 0
+
+    surf 0.0 1.0 0.0 1.0 5 6 7 8
+    parm u 0.0 1.0
+    parm v 0.0 1.0
+    trim 0.0 4.0 1
+    end
+
+    con 1 2.0 2.0 1 2 4.0 3.0 1
+
+
+Grouping
+
+There are four statements in the .obj file to help you manipulate groups
+of elements:
+
+o	Gropu name statements are used to organize collections of
+	elements and simplify data manipulation for operations in
+	Model.
+
+o	Smoothing group statements let you identify elements over which
+	normals are to be interpolated to give those elements a smooth,
+	non-faceted appearance.  This is a quick way to specify vertex
+	normals.
+
+o	Merging group statements are used to ideneify free-form elements
+	that should be inspected for adjacency detection.  You can also
+	use merging groups to exclude surfaces which are close enough to
+	be considered adjacent but should not be merged.
+
+o	Object name statements let you assign a name to an entire object
+	in a single file.
+
+All grouping statements are state-setting.  This means that once a
+group statement is set, it alpplies to all elements that follow
+until the next group statement.
+
+This portion of a sample file shows a single element which belongs to
+three groups.  The smoothing group is turned off.
+
+    g square thing all
+    s off
+    f 1 2 3 4
+
+This example shows two surfaces in merging group 1 with a merge
+resolution of 0.5.
+
+    mg 1 .5
+    surf 0.0 1.0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
+    surf 0.0 1.0 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
+
+Syntax
+
+g group_name1 group_name2 . . .
+
+    Polygonal and free-form geometry statement.
+
+    Specifies the group name for the elements that follow it. You can
+    have multiple group names. If there are multiple groups on one
+    line, the data that follows belong to all groups. Group information
+    is optional.
+
+    group_name is the name for the group. Letters, numbers, and
+    combinations of letters and numbers are accepted for group names.
+    The default group name is default.
+
+s group_number
+
+    Polygonal and free-form geometry statement.
+
+    Sets the smoothing group for the elements that follow it. If you do
+    not want to use a smoothing group, specify off or a value of 0.
+
+    To display with smooth shading in Model and PreView, you must
+    create vertex normals after you have assigned the smoothing groups.
+    You can create vertex normals with the vn statement or with the
+    Model program.
+
+    To smooth polygonal geometry for rendering with Image, it is
+    sufficient to put elements in some smoothing group. However, vertex
+    normals override smoothing information for Image.
+
+    group_number is the smoothing group number. To turn off smoothing
+    groups, use a value of 0 or off. Polygonal elements use group
+    numbers to put elements in different smoothing groups. For
+    free-form surfaces, smoothing groups are either turned on or off;
+    there is no difference between values greater than 0.
+
+mg group_number res
+
+    Free-form geometry statement.
+
+    Sets the merging group and merge resolution for the free-form
+    surfaces that follow it. If you do not want to use a merging group,
+    specify off or a value of 0.
+
+    Adjacency detection is performed only within groups, never between
+    groups. Connectivity between surfaces in different merging groups
+    is not allowed. Surfaces in the same merging group are merged
+    together along edges that are within the distance res apart.
+
+    NOTE: Adjacency detection is an expensive numerical comparison
+    process.  It is best to restrict this process to as small a domain
+    as possible by using small merging groups.
+
+    group_number is the merging group number. To turn off adjacency
+    detection, use a value of 0 or off.
+
+    res is the maximum distance between two surfaces that will be
+    merged together. The resolution must be a value greater than 0.
+    This is a required argument only when using merging groups.
+
+o object_name
+
+    Polygonal and free-form geometry statement.
+
+    Optional statement; it is not processed by any Wavefront programs.
+    It specifies a user-defined object name for the elements defined
+    after this statement.
+
+    object_name is the user-defined object name. There is no default.
+
+Examples
+
+1.      Cube with group names
+
+The following example is a cube with each of its faces placed in a
+separate group. In addition, all elements belong to the group cube.
+
+    v 0.000000 2.000000 2.000000
+    v 0.000000 0.000000 2.000000
+    v 2.000000 0.000000 2.000000
+    v 2.000000 2.000000 2.000000
+    v 0.000000 2.000000 0.000000
+    v 0.000000 0.000000 0.000000
+    v 2.000000 0.000000 0.000000
+    v 2.000000 2.000000 0.000000
+    # 8 vertices
+
+    g front cube
+    f 1 2 3 4
+    g back cube
+    f 8 7 6 5
+    g right cube
+    f 4 3 7 8
+    g top cube
+    f 5 1 4 8
+    g left cube
+    f 5 6 2 1
+    g bottom cube
+    f 2 6 7 3
+    # 6 elements
+
+
+2.      Two adjoining squares with a smoothing group
+
+This example shows two adjoining squares that share a common edge. The
+squares are placed in a smoothing group to ensure that their common
+edge will be smoothed when rendered with Image.
+
+    v 0.000000 2.000000 0.000000
+    v 0.000000 0.000000 0.000000
+    v 2.000000 0.000000 0.000000
+    v 2.000000 2.000000 0.000000
+    v 4.000000 0.000000 -1.255298
+    v 4.000000 2.000000 -1.255298
+    # 6 vertices
+
+    g all
+    s 1
+    f 1 2 3 4
+    f 4 3 5 6
+    # 2 elements
+
+
+3.      Two adjoining squares with vertex normals
+
+This example also shows two squares that share a common edge. Vertex
+normals have been added to the corners of each square to ensure that
+their common edge will be smoothed during display in Model and PreView
+and when rendered with Image.
+
+    v 0.000000 2.000000 0.000000
+    v 0.000000 0.000000 0.000000
+    v 2.000000 0.000000 0.000000
+    v 2.000000 2.000000 0.000000
+    v 4.000000 0.000000 -1.255298
+    v 4.000000 2.000000 -1.255298
+    vn 0.000000 0.000000 1.000000
+    vn 0.000000 0.000000 1.000000
+    vn 0.276597 0.000000 0.960986
+    vn 0.276597 0.000000 0.960986
+    vn 0.531611 0.000000 0.846988
+    vn 0.531611 0.000000 0.846988
+    # 6 vertices
+
+    # 6 normals
+
+    g all
+    s 1
+    f 1//1 2//2 3//3 4//4
+    f 4//4 3//3 5//5 6//6
+    # 2 elements
+
+
+4.      Merging group
+
+This example shows two Bezier surfaces that meet at a common edge. They
+have both been placed in the same merging group to ensure continuity at
+the edge where they meet. This prevents "cracks" from appearing along
+the seam between the two surfaces during rendering. Merging groups will
+be ignored during flat-shading, smooth-shading, and material shading of
+the surface.
+
+    v -4.949854 -5.000000 0.000000
+    v -4.949854 -1.666667 0.000000
+    v -4.949854 1.666667 0.000000
+    v -4.949854 5.000000 0.000000
+    v -1.616521 -5.000000 0.000000
+    v -1.616521 -1.666667 0.000000
+    v -1.616521 1.666667 0.000000
+    v -1.616521 5.000000 0.000000
+    v 1.716813 -5.000000 0.000000
+    v 1.716813 -1.666667 0.000000
+    v 1.716813 1.666667 0.000000
+    v 1.716813 5.000000 0.000000
+    v 5.050146 -5.000000 0.000000
+    v 5.050146 -1.666667 0.000000
+    v 5.050146 1.666667 0.000000
+    v 5.050146 5.000000 0.000000
+    v -15.015566 -4.974991 0.000000
+    v -15.015566 -1.641658 0.000000
+    v -15.015566 1.691675 0.000000
+    v -15.015566 5.025009 0.000000
+    v -11.682233 -4.974991 0.000000
+    v -11.682233 -1.641658 0.000000
+    v -11.682233 1.691675 0.000000
+    v -11.682233 5.025009 0.000000
+    v -8.348900 -4.974991 0.000000
+    v -8.348900 -1.641658 0.000000
+    v -8.348900 1.691675 0.000000
+    v -8.348900 5.025009 0.000000
+    v -5.015566 -4.974991 0.000000
+    v -5.015566 -1.641658 0.000000
+    v -5.015566 1.691675 0.000000
+    v -5.015566 5.025009 0.000000
+
+    mg 1 0.500000
+
+    cstype bezier
+    deg 3 3
+    surf 0.000000 1.000000 0.000000 1.000000 13 14 \
+    15 16 9 10 11 12 5 6 7 8 1 2 3 4
+    parm u 0.000000 1.000000
+    parm v 0.000000 1.000000
+    end
+    surf 0.000000 1.000000 0.000000 1.000000 29 30 31 32 25 26 27 28 21 22 \
+    23 24 17 18 19 20
+    parm u 0.000000 1.000000
+    parm v 0.000000 1.000000
+    end
+
+
+Display/render attributes
+
+Display and render attributes describe how an object looks when
+displayed in Model and PreView or when rendered with Image.
+
+Some attributes apply to both free-form and polygonal geometry, such as
+material name and library, ray tracing, and shadow casting.
+Interpolation attributes apply only to polygonal geometry. Curve and
+surface resolutions are used for only free-form geometry.
+
+The following chart shows the display and render statements available
+for polygonal and free-form geometry.
+
+Table B1-1.     Display and render attributes
+
+polygonal only		polygonal or free-form	free-form only
+--------------		----------------------	--------------
+bevel			lod			ctech
+c_interp		usemtl			stech
+d_interp		mtllib
+			shadow_obj
+			trace_obj
+
+All display and render attribute statements are state-setting. This
+means that once an attribute statement is set, it applies to all
+elements that follow until it is reset to a different value.
+
+The following sample shows rendering and display statements for a face
+element.:
+
+    s 1
+    usemtl blue
+    usemap marble
+    f 1 2 3 4
+
+Syntax
+
+The following syntax statements are listed by the type of geometry.
+First are statements for polygonal geometry. Second are statements for
+both free-form and polygonal geometry. Third are statements for
+free-form geometry only.
+
+bevel on/off
+
+    Polygonal geometry statement.
+
+    Sets bevel interpolation on or off. It works only with beveled
+    objects, that is, objects with sides separated by beveled faces.
+
+    Bevel interpolation uses normal vector interpolation to give an
+    illusion of roundness to a flat bevel. It does not affect the
+    smoothing of non-bevelled faces.
+
+    Bevel interpolation does not alter the geometry of the original
+    object.
+
+    on turns on bevel interpolation.
+
+    off turns off bevel interpolation. The default is off.
+
+    NOTE: Image cannot render bevel-interpolated elements that have
+    vertex normals.
+
+c_interp on/off
+
+    Polygonal geometry statement.
+
+    Sets color interpolation on or off.
+
+    Color interpolation creates a blend across the surface of a polygon
+    between the materials assigned to its vertices. This creates a
+    blending of colors across a face element.
+
+    To support color interpolation, materials must be assigned per
+    vertex, not per element. The illumination models for all materials
+    of vertices attached to the polygon must be the same. Color
+    interpolation applies to the values for ambient (Ka), diffuse (Kd),
+    specular (Ks), and specular highlight (Ns) material properties.
+
+    on turns on color interpolation.
+
+    off turns off color interpolation. The default is off.
+
+d_interp on/off
+
+    Polygonal geometry statement.
+
+    Sets dissolve interpolation on or off.
+
+    Dissolve interpolation creates an interpolation or blend across a
+    polygon between the dissolve (d) values of the materials assigned
+    to its vertices. This feature is used to create effects exhibiting
+    varying degrees of apparent transparency, as in glass or clouds.
+
+    To support dissolve interpolation, materials must be assigned per
+    vertex, not per element. All the materials assigned to the vertices
+    involved in the dissolve interpolation must contain a dissolve
+    factor command to specify a dissolve.
+
+    on turns on dissolve interpolation.
+
+    off turns off dissolve interpolation. The default is off.
+
+lod level
+
+    Polygonal and free-form geometry statement.
+
+    Sets the level of detail to be displayed in a PreView animation.
+    The level of detail feature lets you control which elements of an
+    object are displayed while working in PreView.
+
+    level is the level of detail to be displayed. When you set the
+    level of detail to 0 or omit the lod statement, all elements are
+    displayed.  Specifying an integer between 1 and 100 sets the level
+    of detail to be displayed when reading the .obj file.
+
+maplib filename1 filename2 . . .
+
+    This is a rendering identifier that specifies the map library file
+    for the texture map definitions set with the usemap identifier. You
+    can specify multiple filenames with maplib. If multiple filenames
+    are specified, the first file listed is searched first for the map
+    definition, the second file is searched next, and so on.
+
+    When you assign a map library using the Model program, Model allows
+    only one map library per .obj file. You can assign multiple
+    libraries using a text editor.
+
+    filename is the name of the library file where the texture maps are
+    defined. There is no default.
+
+usemap map_name/off
+
+    This is a rendering identifier that specifies the texture map name
+    for the element following it. To turn off texture mapping, specify
+    off instead of the map name.
+
+    If you specify texture mapping for a face without texture vertices,
+    the texture map will be ignored.
+
+    map_name is the name of the texture map.
+
+    off turns off texture mapping. The default is off.
+
+usemtl material_name
+
+    Polygonal and free-form geometry statement.
+
+    Specifies the material name for the element following it. Once a
+    material is assigned, it cannot be turned off; it can only be
+    changed.
+
+    material_name is the name of the material. If a material name is
+    not specified, a white material is used.
+
+mtllib filename1 filename2 . . .
+
+    Polygonal and free-form geometry statement.
+
+    Specifies the material library file for the material definitions
+    set with the usemtl statement. You can specify multiple filenames
+    with mtllib. If multiple filenames are specified, the first file
+    listed is searched first for the material definition, the second
+    file is searched next, and so on.
+
+    When you assign a material library using the Model program, only
+    one map library per .obj file is allowed. You can assign multiple
+    libraries using a text editor.
+
+    filename is the name of the library file that defines the
+    materials.  There is no default.
+
+shadow_obj filename
+
+    Polygonal and free-form geometry statement.
+
+    Specifies the shadow object filename. This object is used to cast
+    shadows for the current object. Shadows are only visible in a
+    rendered image; they cannot be seen using hardware shading. The
+    shadow object is invisible except for its shadow.
+
+    An object will cast shadows only if it has a shadow object. You can
+    use an object as its own shadow object. However, a simplified
+    version of the original object is usually preferable for shadow
+    objects, since shadow casting can greatly increase rendering time.
+
+    filename is the filename for the shadow object. You can enter any
+    valid object filename for the shadow object. The object file can be
+    an .obj or .mod file. If a filename is given without an extension,
+    an extension of .obj is assumed.
+
+    Only one shadow object can be stored in a file. If more than one
+    shadow object is specified, the last one specified will be used.
+
+trace_obj filename
+
+    Polygonal and free-form geometry statement.
+
+    Specifies the ray tracing object filename. This object will be used
+    in generating reflections of the current object on reflective
+    surfaces.  Reflections are only visible in a rendered image; they
+    cannot be seen using hardware shading.
+
+    An object will appear in reflections only if it has a trace object.
+    You can use an object as its own trace object. However, a
+    simplified version of the original object is usually preferable for
+    trace objects, since ray tracing can greatly increase rendering
+    time.
+
+    filename is the filename for the ray tracing object. You can enter
+    any valid object filename for the trace object. You can enter any
+    valid object filename for the shadow object. The object file can be
+    an .obj or .mod file. If a filename is given without an extension,
+    an extension of .obj is assumed.
+
+    Only one trace object can be stored in a file. If more than one is
+    specified, the last one is used.
+
+ctech  technique  resolution
+
+    Free-form geometry statement.
+
+    Specifies a curve approximation technique. The arguments specify
+    the technique and resolution for the curve.
+
+    You must select from one of the following three techniques.
+
+    ctech cparm res
+
+	Specifies a curve with constant parametric subdivision using
+	one resolution parameter. Each polynomial segment of the curve
+	is subdivided n times in parameter space, where n is the
+	resolution parameter multiplied by the degree of the curve.
+
+	res is the resolution parameter. The larger the value, the
+	finer the resolution. If res has a value of 0, each polynomial
+	curve segment is represented by a single line segment.
+
+    ctech cspace maxlength
+
+	Specifies a curve with constant spatial subdivision. The curve
+	is approximated by a series of line segments whose lengths in
+	real space are less than or equal to the maxlength.
+
+	maxlength is the maximum length of the line segments. The
+	smaller the value, the finer the resolution.
+
+    ctech curv maxdist maxangle
+
+	Specifies curvature-dependent subdivision using separate
+	resolution parameters for the maximum distance and the maximum
+	angle.
+
+	The curve is approximated by a series of line segments in which
+	1) the distance in object space between a line segment and the
+	actual curve must be less than the maxdist parameter and 2) the
+	angle in degrees between tangent vectors at the ends of a line
+	segment must be less than the maxangle parameter.
+
+	maxdist is the distance in real space between a line segment
+	and the actual curve.
+
+	maxangle is the angle (in degrees) between tangent vectors at
+	the ends of a line segment.
+
+	The smaller the values for maxdist and maxangle, the finer the
+	resolution.
+
+    NOTE: Approximation information for trimming, hole, and special
+    curves is stored in the corresponding surface. The ctech statement
+    for the surface is used, not the ctech statement applied to the
+    curv2 statement. Although untrimmed surfaces have no explicit
+    trimming loop, a loop is constructed which bounds the legal
+    parameter range. This implicit loop follows the same rules as any
+    other loop and is approximated according to the ctech information
+    for the surface.
+
+stech  technique  resolution
+
+    Free-form geometry statement.
+
+    Specifies a surface approximation technique. The arguments specify
+    the technique and resolution for the surface.
+
+    You must select from one of the following techniques:
+
+    stech cparma ures vres
+
+	Specifies a surface with constant parametric subdivision using
+	separate resolution parameters for the u and v directions. Each
+	patch of the surface is subdivided n times in parameter space,
+	where n is the resolution parameter multiplied by the degree of
+	the surface.
+
+	ures is the resolution parameter for the u direction.
+
+	vres is the resolution parameter for the v direction.
+
+	The larger the values for ures and vres, the finer the
+	resolution.  If you enter a value of 0 for both ures and vres,
+	each patch is approximated by two triangles.
+
+    stech cparmb uvres
+
+	Specifies a surface with constant parametric subdivision, with
+	refinement using one resolution parameter for both the u and v
+	directions.
+
+	An initial triangulation is performed using only the points on
+	the trimming curves. This triangulation is then refined until
+	all edges are of an appropriate length. The resulting triangles
+	are not oriented along isoparametric lines as they are in the
+	cparma technique.
+
+	uvres is the resolution parameter for both the u and v
+	directions.  The larger the value, the finer the resolution.
+
+    stech cspace maxlength
+
+	Specifies a surface with constant spatial subdivision.
+
+	The surface is subdivided in rectangular regions until the
+	length in real space of any rectangle edge is less than the
+	maxlength.  These rectangular regions are then triangulated.
+
+	maxlength is the length in real space of any rectangle edge.
+	The smaller the value, the finer the resolution.
+
+    stech curv maxdist maxangle
+
+	Specifies a surface with curvature-dependent subdivision using
+	separate resolution parameters for the maximum distance and the
+	maximum angle.
+
+	The surface is subdivided in rectangular regions until 1) the
+	distance in real space between the approximating rectangle and
+	the actual surface is less than the maxdist (approximately) and
+	2) the angle in degrees between surface normals at the corners
+	of the rectangle is less than the maxangle. Following
+	subdivision, the regions are triangulated.
+
+	maxdist is the distance in real space between the approximating
+	rectangle and the actual surface.
+
+	maxangle is the angle in degrees between surface normals at the
+	corners of the rectangle.
+
+	The smaller the values for maxdist and maxangle, the finer the
+	resolution.
+
+Examples
+
+1.      Cube with materials
+
+This cube has a different material applied to each of its faces.
+
+    mtllib master.mtl
+
+    v 0.000000 2.000000 2.000000
+    v 0.000000 0.000000 2.000000
+    v 2.000000 0.000000 2.000000
+    v 2.000000 2.000000 2.000000
+    v 0.000000 2.000000 0.000000
+    v 0.000000 0.000000 0.000000
+    v 2.000000 0.000000 0.000000
+    v 2.000000 2.000000 0.000000
+    # 8 vertices
+
+    g front
+    usemtl red
+    f 1 2 3 4
+    g back
+    usemtl blue
+    f 8 7 6 5
+    g right
+    usemtl green
+    f 4 3 7 8
+    g top
+    usemtl gold
+    f 5 1 4 8
+    g left
+    usemtl orange
+    f 5 6 2 1
+    g bottom
+    usemtl purple
+    f 2 6 7 3
+    # 6 elements
+
+
+2.      Cube casting a shadow
+
+In this example, the cube casts a shadow on the other objects when it
+is rendered with Image. The cube, which is stored in the file cube.obj,
+references itself as the shadow object.
+
+    mtllib master.mtl
+    shadow_obj cube.obj
+
+    v 0.000000 2.000000 2.000000
+    v 0.000000 0.000000 2.000000
+    v 2.000000 0.000000 2.000000
+    v 2.000000 2.000000 2.000000
+    v 0.000000 2.000000 0.000000
+    v 0.000000 0.000000 0.000000
+    v 2.000000 0.000000 0.000000
+    v 2.000000 2.000000 0.000000
+    # 8 vertices
+
+    g front
+    usemtl red
+    f 1 2 3 4
+    g back
+    usemtl blue
+    f 8 7 6 5
+    g right
+    usemtl green
+    f 4 3 7 8
+    g top
+    usemtl gold
+    f 5 1 4 8
+    g left
+    usemtl orange
+    f 5 6 2 1
+    g bottom
+    usemtl purple
+    f 2 6 7 3
+    # 6 elements
+
+
+3.      Cube casting a reflection
+
+This cube casts its reflection on any reflective objects when it is
+rendered with Image. The cube, which is stored in the file cube.obj,
+references itself as the trace object.
+
+    mtllib master.mtl
+    trace_obj cube.obj
+
+    v 0.000000 2.000000 2.000000
+    v 0.000000 0.000000 2.000000
+    v 2.000000 0.000000 2.000000
+    v 2.000000 2.000000 2.000000
+    v 0.000000 2.000000 0.000000
+    v 0.000000 0.000000 0.000000
+    v 2.000000 0.000000 0.000000
+    v 2.000000 2.000000 0.000000
+    # 8 vertices
+
+    g front
+    usemtl red
+    f 1 2 3 4
+    g back
+    usemtl blue
+    f 8 7 6 5
+    g right
+    usemtl green
+    f 4 3 7 8
+    g top
+    usemtl gold
+    f 5 1 4 8
+    g left
+    usemtl orange
+    f 5 6 2 1
+    g bottom
+    usemtl purple
+    f 2 6 7 3
+    # 6 elements
+
+
+
+4.      Texture-mapped square
+
+This example describes a 2 x 2 square. It is mapped with a 1 x 1 square
+texture. The texture is stretched to fit the square exactly.
+
+mtllib master.mtl
+
+v 0.000000 2.000000 0.000000
+v 0.000000 0.000000 0.000000
+v 2.000000 0.000000 0.000000
+v 2.000000 2.000000 0.000000
+vt 0.000000 1.000000 0.000000
+vt 0.000000 0.000000 0.000000
+vt 1.000000 0.000000 0.000000
+vt 1.000000 1.000000 0.000000
+# 4 vertices
+
+usemtl wood
+f 1/1 2/2 3/3 4/4
+# 1 element
+
+5.      Approximation technique for a surface
+
+This example shows a B-spline surface which will be approximated using
+curvature-dependent subdivision specified by the stech command.
+
+    g bspatch
+    v -5.000000 -5.000000 -7.808327
+    v -5.000000 -1.666667 -7.808327
+    v -5.000000 1.666667 -7.808327
+    v -5.000000 5.000000 -7.808327
+    v -1.666667 -5.000000 -7.808327
+    v -1.666667 -1.666667 11.977780
+    v -1.666667 1.666667 11.977780
+    v -1.666667 5.000000 -7.808327
+    v 1.666667 -5.000000 -7.808327
+    v 1.666667 -1.666667 11.977780
+    v 1.666667 1.666667 11.977780
+    v 1.666667 5.000000 -7.808327
+    v 5.000000 -5.000000 -7.808327
+    v 5.000000 -1.666667 -7.808327
+    v 5.000000 1.666667 -7.808327
+    v 5.000000 5.000000 -7.808327
+    # 16 vertices
+
+    g bspatch
+    cstype bspline
+    stech curv 0.5 10.000000
+    deg 3 3
+    surf 0.000000 1.000000 0.000000 1.000000 13 14 \ 15 16 9 10 11 12 5 6 7
+    8 1 2 3 4
+    parm u -3.000000 -2.000000 -1.000000 0.000000  \
+    1.000000 2.000000 3.000000 4.000000
+    parm v -3.000000 -2.000000 -1.000000 0.000000  \
+    1.000000 2.000000 3.000000 4.000000
+    end
+    # 1 element
+
+
+
+6.      Approximation technique for a curve
+
+This example shows a Bezier curve which will be approximated using
+constant parametric subdivision specified by the ctech command.
+
+    v -2.300000 1.950000 0.000000
+    v -2.200000 0.790000 0.000000
+    v -2.340000 -1.510000 0.000000
+    v -1.530000 -1.490000 0.000000
+    v -0.720000 -1.470000 0.000000
+    v -0.780000 0.230000 0.000000
+    v 0.070000 0.250000 0.000000
+    v 0.920000 0.270000 0.000000
+    v 0.800000 -1.610000 0.000000
+    v 1.620000 -1.590000 0.000000
+    v 2.440000 -1.570000 0.000000
+    v 2.690000 0.670000 0.000000
+    v 2.900000 1.980000 0.000000
+    # 13 vertices
+
+    g default
+    cstype bezier
+    ctech cparm 1.000000
+    deg 3
+    curv 0.000000 4.000000 1 2 3 4 5 6 7 8 9 10 \
+    11 12 13
+    parm u 0.000000 1.000000 2.000000 3.000000  \
+    4.000000
+    end
+    # 1 element
+
+
+
+Comments
+
+Comments can appear anywhere in an .obj file. They are used to annotate
+the file; they are not processed.
+
+Here is an example:
+
+    # this is a comment
+
+The Model program automatically inserts comments when it creates .obj
+files. For example, it reports the number of geometric vertices,
+texture vertices, and vertex normals in a file.
+
+    # 4 vertices
+    # 4 texture vertices
+    # 4 normals
+
+Mathematics for free-form curves/surfaces
+
+[I apologize but this section will make absolutely no sense whatsoever
+ without the equations and diagrams and there was just no easy way to
+ include them in a pure ASCII document.  You should probably just skip
+ ahead to the section "Superseded statements."  -Jim]
+
+General forms
+
+Rational and non-rational curves and surfaces
+
+In general, any non-rational curve segment may be written as:
+
+where
+
+K + 1    is the number of control points
+
+di       are the control points
+
+n        is the degree of the curve
+
+Ni,n(t)          are the degree n basis functions
+
+Extending this to the bivariate case, any non-rational surface patch
+may be written as:
+
+where:
+
+K1 + 1   is the number of control points in the u direction
+
+K2 + 1   is the number of control points in the v direction
+
+di,j     are the control points
+
+m        is the degree of the surface in the u direction
+
+n        is the degree of the surface in the v direction
+
+Ni,m(u)          are the degree m basis functions in the u direction
+
+Nj,n(v)          are the degree n basis functions in the v direction
+
+NOTE: The front of the surface is defined as the side where the u
+parameter increases to the right and the v parameter increases upward.
+
+We may extend this curve to the rational case as:
+
+
+
+where wi are the weights associated with the control points di.
+Similarly, a rational surface may be expressed as:
+
+where wi,j  are the weights associated with the control points di,j.
+
+NOTE: If a curve or surface in an .obj file is rational, it must use
+the rat option with the cstype statement and it requires some weight
+values for each control point.
+
+
+
+The weights for the rational form are given as a third control point
+coordinate (for trimming curves) or fourth coordinate (for space curves
+and surfaces). These weights are optional and default to 1.0 if not
+given.
+
+
+
+This default weight is only reasonable for curves and surfaces whose
+basis functions sum to 1.0, such as Bezier, Cardinal, and NURB. It does
+not make sense for Taylor and may or may not make sense for a
+representation given in basis-matrix form.
+
+For all forms other than B-spline, the final curve or surface is
+constructed by piecing together the individual curve segments or
+surface patches. A global parameter space is then defined over the
+entire composite curve or surface using the parameter vector given with
+the parm statement.
+
+The parameter vector for a curve is a list of p global parameter values
+{t1, . . . , tp}. If t1  t < ti+1 is a point in global parameter space,
+then:
+
+is the corresponding point in local parameter space for the ith
+polynomial segment. It is this t which is used when evaluating a given
+segment of the piecewise curve. For surfaces, this mapping from global
+to local parameter space is applied independently in both the u and v
+parametric directions.
+
+B-splines require a knot vector rather than a parameter vector,
+although this is also given with the parm statement. Refer to the
+description of B-splines below.
+
+The following discussion of each type is expressed in terms of the
+above definitions.
+
+NOTE: The maximum degree for all curve and surface types is currently
+set at 20, which is high enough for most purposes.
+
+
+
+Free-form curve and surface types
+
+B-spline
+
+Type bspline specifies arbitrary degree non-uniform B-splines which are
+commonly referred to as NURBs in their rational form. The basis
+functions are defined by the Cox-deBoor recursion formulas as:
+
+and:
+
+where, by convention, 0/0 = 0.
+
+The xi  {x0, . . . ,xq} form a set known as the knot vector which is
+given by the parm statement. It is required that
+
+1.      xi  xi + 1,
+
+2.      x0 < xn + 1,
+
+3.      xq -n -1 < xq,
+
+4.      xi < xi + n for 0 < i < q - n - 1,
+
+5.      xn  t min < tmax  xK+ 1, where [tmin, tmax] is the parameter
+over which the B-spline is to be evaluated, and
+
+6.      K = q - n - 1.
+
+A knot is said to be of multiplicity r if its value is repeated r times
+in the knot vector. The second through fourth conditions above restrict
+knots to be of at most multiplicity n + 1 at the ends of the vector and
+at most n everywhere else.
+
+The last condition requires that the number of control points is equal
+to one less than the number of knots minus the degree. For surfaces,
+all of the above conditions apply independently for the u and v
+parametric directions.
+
+Bezier
+
+Type bezier specifies arbitrary degree Bezier curves and surfaces. This
+basis function is defined as:
+
+where:
+
+When using type bezier, the number of global parameter values given
+with the parm statement must be K/n + 1, where K is the number of
+control points. For surfaces, this requirement applies independently
+for the u and v parametric directions.
+
+Cardinal
+
+Type cardinal specifies a cubic, first derivative, continuous curve or
+surface. For curves, this interpolates all but the first and last
+control points. For surfaces, all but the first and last row and column
+of control points are interpolated.
+
+Cardinal splines, also known as Catmull-Rom splines, are best
+understood by considering the conversion from Cardinal to Bezier
+control points for a single curve segment:
+
+Here, the ci variables are the Cardinal control points and the bi
+variables are the Bezier control points. We see that the second and
+third Cardinal points are the beginning and ending points for the
+segment, respectively. Also, the beginning tangent lies along the
+vector from the first to the third point, and the ending tangent along
+the vector from the second to the last point.
+
+If we let Bi(t) be the cubic Bezier basis functions (i.e. what was
+given above for Bezier as Ni,n(t) with n = 3), then we may write the
+Cardinal basis functions as:
+
+Note that Cardinal splines are only defined for the cubic case.
+
+When using type cardinal, the number of global parameter values given
+with the parm statement must be K - n + 2, where K is the number of
+control points. For surfaces, this requirement applies independently
+for the u and v parametric directions.
+
+Taylor
+
+Type taylor specifies arbitrary degree Taylor polynomial curves and
+surfaces. The basis function is simply:
+
+NOTE: The control points in this case are the polynomial coefficients
+and have no obvious geometric significance.
+
+When using type taylor, the number of global parameter values given
+with the parm statement must be (K + 1)/(n + 1) + 1, where K is the
+number of control points. For surfaces, this requirement applies
+independently for the u and v parametric directions.
+
+Basis matrix
+
+Type bmatrix specifies general, arbitrary-degree curves defined through
+the use of a basis matrix rather than an explicit type such as Bezier.
+The basis functions are defined as:
+
+where the basis matrix is the bi,j. In order to make the matrix nature
+of this more obvious, we may also write:
+
+When constructing basis matrices, you should keep this definition in
+mind, as different authors write this in different ways. A more common
+matrix representation is:
+
+To use such matrices in the .obj file, simply transpose the matrix and
+reverse the column ordering.
+
+When using type basis, the number of global parameter values given with
+the parm statement must be (K - n)/s + 2, where K is the number of
+control points and s is the step size given with the step statement.
+For surfaces, this requirement applies independently for the u and v
+parametric directions.
+
+Surface vertex data
+
+Control points
+
+The control points for a surface consisting of a single patch are
+listed in the order i = 0 to K1 for j = 0, followed by i = 0 to K1 for
+j = 1, and so on until j = K2.
+
+For surfaces made up of many patches, which is the usual case, the
+control points are ordered as if the surface were a single large patch.
+For example, the control points for a bicubic Bezier surface consisting
+of four patches would be arranged as follows:
+
+where (m, n) is the global parameter space of the surface and the
+numbers indicate the ordering of the vertex indices in the surf
+statement.
+
+Texture vertices and texture mapping
+
+When texture vertices are not supplied, the original surface
+parameterization is used for texture mapping. However, if texture
+vertices are supplied, they are interpreted as additional information
+to be interpolated or approximated separately from, but using the same
+interpolation functions as the control vertices.
+
+That is, whereas the surface itself, in the non-rational case, was
+given in the section "Rational and non-rational curves and surfaces"
+as:
+
+
+
+the texture vertices are interpolated or approximated by:
+
+where ti,j are the texture vertices and the basis functions are the
+same as for S(u,v). It is T(u,v), rather than the surface
+parameterization (u,v), which is used when a texture map is applied.
+
+Vertex normals and normal mapping
+
+Vertex normals are treated exactly like texture vertices. When vertex
+normals are not supplied, the true surface normals are used. If vertex
+normals are supplied, they are calculated as:
+
+where qi,j are the vertex normals and the basis functions are the same
+as for S(u,v) and T(u,v).
+
+NOTE: Vertex normals do not affect the shape of the surface; they are
+simply associated with the triangle vertices in the final
+triangulation. As with faces, supplying vertex normals only affects
+lighting calculations for the surface.
+
+The treatment of both texture vertices and vertex normals in the case
+of rational surfaces is identical. It is important to notice that even
+when the surface S(u,v) is rational, the texture and normal surfaces,
+T(u,v) and Q(u,v), are not rational. This is because the control points
+(the texture vertices and vertex normals) are never rational.
+
+Curve and surface operations
+
+Special points
+
+The following equations give a more precise description of special
+points for space curves and discuss the extension to trimming curves
+and surfaces.
+
+Let C(t) be a space curve with the global parameter t. We can
+approximate this curve by a set of k-1 line segments which connect the
+points:
+
+for some set of k global parameter values {t1,...,tk}
+
+Given a special point ts in the parameter space of the curve
+(referenced by vp), we guarantee that ts  {t1, . . . ,tk}. More
+specifically, we approximate the curve by:
+
+where, at the point i where ts is inserted, we have ti  ts < ti+1.
+
+Special curves
+
+The following equations give a more precise description of a special
+curve.
+
+Let T(t) be a special curve with the global parameter t. We have:
+
+where (m,n) is a point in the global parameter space of a surface. We
+can approximate this curve by a set of k-1 line segments which connect
+the points:
+
+for some set of k global parameter values.
+
+Let S(m,n) be a surface with the global parameters m and n. We can
+approximate this surface by a triangulation of a set of p points.
+
+which lie on the surface. We further define E as the set of all edges
+such that ei,j  E implies that S(mi,ni) and S(mj,nj) are connected in
+the triangulation. Finally, we guarantee that there exists some subset
+of E:
+
+such that the points:
+
+are connected in the triangulation.
+
+Connectivity
+
+Recall that the syntax of the con statement is:
+
+con surf_1 q0_1 q1_1 curv2d_1 surf_2 q0_2 q1_2 curv2d_2
+
+If we let:
+
+T1(t1)  be the curve referenced by curv2d_1
+
+S1(m1, n1)      be the surface referenced by surf1 on which T1(t1) lies
+
+T2(t2)  be the curve referenced by curv2d_2
+
+S2(m2, n2)      be the surface referenced by surf2 on which T2(t2) lies
+
+then S1(T1(t1)), S2(T2(t2)) must be identical up to reparameterization.
+Moreover, it must be the case that:
+
+S1(T1(q0_1)) = S2(T2(q0_2))
+
+and:
+
+S1(T1(q1_1)) = S2(T2(q1_2))
+
+It is along the curve S1(T1(t1)) between t1 = q0_1 and t1 = q1_1, and
+the curve S2(T2(t2)) between t2 = q0_2 and t2 = q1_2 that the surface
+S1(m1, n1) is connected to the surface S2(m2, n2).
+
+
+
+Superseded statements
+
+The new .obj file format has eliminated the need for several patch and
+curve statements. These statements have been replaced by free-form
+geometry statements.
+
+In the 3.0 release, the following keywords have been superseded:
+
+o       bsp
+
+o       bzp
+
+o       cdc
+
+o       cdp
+
+o       res
+
+You can still read these statements in this version 3.0, however, the
+system will no longer write files in this format.
+
+This release is the last release that will read these statements. If
+you want to save any data from this format, read in the file and write
+it out. The system will convert the data to the new .obj format.
+
+For more information on the new syntax statements, see "Specifying
+free-form curves and surfaces."
+
+Syntax
+
+The following syntax statements are for the superseded keywords.
+
+bsp v1 v2 . . . v16
+
+    Specifies a B-spline patch. B-spline patches have sixteen control
+    points, defined as vertices. Only four of the control points are
+    distributed over the surface of the patch; the remainder are
+    distributed around the perimeter of the patch.
+
+    Patches must be tessellated in Model before they can be correctly
+    shaded or rendered.
+
+    v is the vertex number for a control point. Sixteen vertex numbers
+    are required. Positive values indicate absolute vertex numbers.
+    Negative values indicate relative vertex numbers.
+
+bzp v1 v2 . . . v16
+
+    Specifies a Bezier patch. Bezier patches have sixteen control
+    points, defined as vertices. The control points are distributed
+    uniformly over its surface.
+
+    Patches must be tessellated in Model before they can be correctly
+    shaded or rendered.
+
+    v is the vertex number for a control point. Sixteen vertex numbers
+    are required. Positive values indicate absolute vertex numbers.
+    Negative values indicate relative vertex numbers.
+
+cdc v1 v2 v3 v4 v5 . . .
+
+    Specifies a Cardinal curve. Cardinal curves have a minimum of four
+    control points, defined as vertices.
+
+    Cardinal curves cannot be correctly shaded or rendered. They can be
+    tessellated and then extruded in Model to create 3D shapes.
+
+    v is the vertex number for a control point. A minimum of four
+    vertex numbers are required. There is no limit on the maximum.
+    Positive values indicate absolute vertex numbers. Negative values
+    indicate relative vertex numbers.
+
+cdp v1 v2 v3 . . . v16
+
+    Specifies a Cardinal patch. Cardinal patches have sixteen control
+    points, defined as vertices. Four of the control points are
+    attached to the corners of the patch.
+
+    Patches must be tessellated in Model before they can be correctly
+    shaded or rendered.
+
+    v is the vertex number for a control point. Sixteen vertex numbers
+    are required. Positive values indicate absolute vertex numbers.
+    Negative values indicate relative vertex numbers.
+
+res useg vseg
+
+    Reference and display statement.
+
+    Sets the number of segments for Bezier, B-spline and Cardinal
+    patches that follow it.
+
+    useg is the number of segments in the u direction (horizontal or x
+    direction). The minimum setting is 3 and the maximum setting is
+    120.  The default is 4.
+
+    vseg is the number of segments in the v direction (vertical or y
+    direction). The minimum setting is 3 and the maximum setting is
+    120.  The default is 4.
+
+Comparison of 2.11 and 3.0 syntax
+
+Cardinal curve
+
+The following example shows the 2.11 syntax and the 3.0 syntax for the
+same Cardinal curve.
+
+2.11 Cardinal curve
+
+    # 2.11 Cardinal Curve
+
+    v 2.570000 1.280000 0.000000
+    v 0.940000 1.340000 0.000000
+    v -0.670000 0.820000 0.000000
+    v -0.770000 -0.940000 0.000000
+    v 1.030000 -1.350000 0.000000
+    v 3.070000 -1.310000 0.000000
+    # 6 vertices
+
+    cdc 1 2 3 4 5 6
+
+
+3.0 Cardinal curve
+
+    # 3.0 Cardinal curve
+
+    v 2.570000 1.280000 0.000000
+    v 0.940000 1.340000 0.000000
+    v -0.670000 0.820000 0.000000
+    v -0.770000 -0.940000 0.000000
+    v 1.030000 -1.350000 0.000000
+    v 3.070000 -1.310000 0.000000
+    # 6 vertices
+
+    cstype cardinal
+    deg 3
+    curv 0.000000 3.000000 1 2 3 4 5 6
+    parm u 0.000000 1.000000 2.000000 3.000000
+    end
+    # 1 element
+
+Bezier patch
+
+ The following example shows the 2.11 syntax and the 3.0 syntax for the
+ same Bezier patch.
+
+2.11 Bezier patch
+
+    # 2.11 Bezier Patch
+    v -5.000000 -5.000000 0.000000
+    v -5.000000 -1.666667 0.000000
+    v -5.000000 1.666667 0.000000
+    v -5.000000 5.000000 0.000000
+    v -1.666667 -5.000000 0.000000
+    v -1.666667 -1.666667 0.000000
+    v -1.666667 1.666667 0.000000
+    v -1.666667 5.000000 0.000000
+    v 1.666667 -5.000000 0.000000
+    v 1.666667 -1.666667 0.000000
+    v 1.666667 1.666667 0.000000
+    v 1.666667 5.000000 0.000000
+    v 5.000000 -5.000000 0.000000
+    v 5.000000 -1.666667 0.000000
+    v 5.000000 1.666667 0.000000
+    v 5.000000 5.000000 0.000000
+    # 16 vertices
+
+    bzp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
+    # 1 element
+
+3.0 Bezier patch
+
+    #   3.0 Bezier patch
+
+    v -5.000000 -5.000000 0.000000
+    v -5.000000 -1.666667 0.000000
+    v -5.000000 1.666667 0.000000
+    v -5.000000 5.000000 0.000000
+    v -1.666667 -5.000000 0.000000
+    v -1.666667 -1.666667 0.000000
+    v -1.666667 1.666667 0.000000
+    v -1.666667 5.000000 0.000000
+    v 1.666667 -5.000000 0.000000
+    v 1.666667 -1.666667 0.000000
+    v 1.666667 1.666667 0.000000
+    v 1.666667 5.000000 0.000000
+    v 5.000000 -5.000000 0.000000
+    v 5.000000 -1.666667 0.000000
+    v 5.000000 1.666667 0.000000
+    v 5.000000 5.000000 0.000000
+    # 16 vertices
+
+    cstype bezier
+    deg 3 3
+    surf 0.000000 1.000000 0.000000 1.000000 13 14 \
+    15 16 9 10 11 12 5 6 7 8 1 2 3 4
+    parm u 0.000000 1.000000
+    parm v 0.000000 1.000000
+    end
+    # 1 element
+
diff --git a/Docs/SceneGeneration/SceneryGeneration.tex b/Docs/Scenery/SceneGeneration/SceneryGeneration.tex
similarity index 99%
rename from Docs/SceneGeneration/SceneryGeneration.tex
rename to Docs/Scenery/SceneGeneration/SceneryGeneration.tex
index cf741041a..0d84beacd 100644
--- a/Docs/SceneGeneration/SceneryGeneration.tex
+++ b/Docs/Scenery/SceneGeneration/SceneryGeneration.tex
@@ -549,6 +549,9 @@ Generates the width of a 1/8 x 1/8 degree tile at various latitudes.
 
 %------------------------------------------------------------------------
 % $Log$
+% Revision 1.1  1999/04/05 21:32:34  curt
+% Initial revision
+%
 % Revision 1.4  1999/03/21 15:12:51  curt
 % Updated to reflect current scenery progress.
 %
diff --git a/Docs/SceneGeneration/ref.fig b/Docs/Scenery/SceneGeneration/ref.fig
similarity index 100%
rename from Docs/SceneGeneration/ref.fig
rename to Docs/Scenery/SceneGeneration/ref.fig
diff --git a/Docs/Scenery/SceneGeneration/terrain.outline b/Docs/Scenery/SceneGeneration/terrain.outline
new file mode 100644
index 000000000..596130fcd
--- /dev/null
+++ b/Docs/Scenery/SceneGeneration/terrain.outline
@@ -0,0 +1,50 @@
+Basically what I'm doing is starting with the 3 arcsec DEM files (a
+point every 100 meters roughly.)
+
+I start out at one corner and walk down a horizonal row.  I start with
+the first 2 points and do a least squares fit, I then add the next
+point, and the next, and the next until my least squares fit exceeds
+some error tolerance from the original data.  At that point, I back up
+one point and include that point in the output set of points.  This
+point then becomes my new starting point for the least squares fit.  I
+repeat this until I finish the row.  I do this for each row to produce
+an "irregular" set of output points from the original.  I'm sure from
+a pure mathematical perspective you can see some potential flaws in
+this approach, but the actual real life result is actually quite good.
+
+I then do a Delauney triangulation of these points (and add in more to
+keep the triangles from getting too long and skinny.)
+
+I have to go through additional pain to make sure that all the points
+coincide on the edge between two adjacent areas (and the normals to so
+there is continuity in the shading.)
+
+I then run a "tri-striper" program to connect up all the individual
+triangles into more efficient opengl strips.
+
+Finally I post process everything to compensate for bugs in our lousy
+tri-striper and to add in a few other things that our render requires.
+
+There is a wee bit of documentation at:
+
+http://www.menet.umn.edu/~curt/fgfs/Docs/Scenery/CoordinateSystem/CoordinateSystem.html
+
+Here I lay out our basic coordinate system.  Essentially the scenery
+tiles that result in the above process are just cutouts of the Earths
+surface.  The maintain the curved shape and spacial orientation.  The
+renderer translates everything to near (0,0,0) to compensate for
+GLfloat precision limitations.
+
+All the tools I use to do this are distributed with the FG source, so
+feel free to download them, play around, and ask questions.
+
+Our resulting scenery tile format is structured to facilitate view
+frustum culling on a per tile basis as well as a per "fragment" basis.
+
+The next thing I plan to work on is sorting by material properties.
+As I walk through the tile structures doing my view frustum culling,
+instead of immediately rendering the visible fragments, I plan to toss
+them into buckets by material property.  Then I make a pass through
+each of these buckets, rendering all the items with like properties.
+This should minimize opengl state and texture changes which should
+help keep the performance from going in the dumpster.
diff --git a/Docs/SceneGeneration/trap.fig b/Docs/Scenery/SceneGeneration/trap.fig
similarity index 100%
rename from Docs/SceneGeneration/trap.fig
rename to Docs/Scenery/SceneGeneration/trap.fig
diff --git a/Docs/Sky/Sky.tex b/Docs/Scenery/Sky/Sky.tex
similarity index 99%
rename from Docs/Sky/Sky.tex
rename to Docs/Scenery/Sky/Sky.tex
index f8e0b5ede..da39e9b2a 100644
--- a/Docs/Sky/Sky.tex
+++ b/Docs/Scenery/Sky/Sky.tex
@@ -223,6 +223,9 @@ determine the proper angle for the sky dome rotation.
 
 %------------------------------------------------------------------------
 % $Log$
+% Revision 1.1  1999/04/05 21:32:34  curt
+% Initial revision
+%
 % Revision 1.1  1999/02/14 19:12:21  curt
 % Initial revisions.
 %
diff --git a/Docs/Sky/dome.fig b/Docs/Scenery/Sky/dome.fig
similarity index 100%
rename from Docs/Sky/dome.fig
rename to Docs/Scenery/Sky/dome.fig
diff --git a/Docs/Sky/earth.fig b/Docs/Scenery/Sky/earth.fig
similarity index 100%
rename from Docs/Sky/earth.fig
rename to Docs/Scenery/Sky/earth.fig
diff --git a/Docs/Sky/local.fig b/Docs/Scenery/Sky/local.fig
similarity index 100%
rename from Docs/Sky/local.fig
rename to Docs/Scenery/Sky/local.fig
diff --git a/Docs/Time/Events/Events.tex b/Docs/Time/Events/Events.tex
new file mode 100644
index 000000000..fa9308fad
--- /dev/null
+++ b/Docs/Time/Events/Events.tex
@@ -0,0 +1,152 @@
+%
+% `Events.tex' -- describes the FG Event Manager
+%
+%  Written by Curtis Olson.  Started December, 1997.
+%
+% $Id$
+%------------------------------------------------------------------------
+
+
+\documentclass[12pt]{article}
+
+\usepackage{anysize}
+\papersize{11in}{8.5in}
+\marginsize{1in}{1in}{1in}{1in}
+
+\usepackage{amsmath}
+
+\usepackage{epsfig}
+
+\usepackage{setspace}
+\onehalfspacing
+
+\usepackage{url}
+
+
+\begin{document}
+
+
+\title{
+  Flight Gear Periodic Event Manager and Scheduler
+}
+
+
+\author{
+    Curtis L. Olson\\ 
+    (\texttt{curt@me.umn.edu})
+}
+
+
+\maketitle
+
+
+\section{Introduction}
+
+Many tasks within the simulator need to only run periodically.  These
+are typically tasks that calculate values that don't change
+significantly in 1/60th of a second, but instead change noticeably on
+the order of seconds, minutes, or hours.
+
+Running these tasks every iteration would needless degrade
+performance.  Instead, we would like to spread these out over time to
+minimize the impact they might have on frame rates, and minimize the
+chance of pauses and hesitations.
+
+\section{Overview}
+
+The goal of the event manager is to provide a way for events to be run
+periodically, and to spread this load out so that the processing time
+spent at any particular iteration is minimized.
+
+The scheduler consists of two parts.  The first part is simply a list
+of registered events along with any management information associated
+with that event.  The second part is a run queue.  When events are
+triggered, they are placed in the run queue.  The system executes only
+one pending event per iteration in order to balance the load.
+
+\section{The Events List}
+
+\subsection{Event List Structure}
+
+All registered events are maintained in a list.  Currently, this list
+is simply an array of event structures.  Each event structure stores
+the following information.
+
+\begin{itemize}
+  \item An ASCII description or event identifier.  This is used when
+    outputting event statistics.
+
+  \item A pointer to the event function.
+
+  \item An event status flag.  The flag marks the process as ready to
+    run, queued in the run queue, or suspended from eligibility to
+    run.
+    
+  \item A time interval specifying how often to schedule and run this
+    event.
+                      
+  \item The absolute time this event was last run.
+  
+  \item The next absolute time this event is scheduled to run.
+    
+  \item The cumulative run time for this process (in ms.)
+    
+  \item The least time consumed by a single run of this event (in ms.)
+
+  \item The most time consumed by a single run of this event (in ms.)
+
+  \item The number of times this event has been run.
+\end{itemize}
+
+\subsection{Event List Operation}
+
+To use the event list, you must first initialize it by calling
+\texttt{fgEventInit()}.  
+
+Once the list has been initialized, you can register events by calling
+\texttt{fgEventRegister()}.  A typical usage might be:
+\texttt{fgEventRegister(``fgUpdateWeather()'', fgUpdateWeather,
+  FG\_EVENT\_READY, 60000)}.  This tells the event manager to schedule
+and run the event, \texttt{fgUpdateWeather()}, every 60 seconds.  The
+first field is an ASCII description of the function, the second field
+is a pointer to the function, the third field is the status flag, and
+the last field is the time interval.  Event functions should return
+\texttt{void} and accept no parameters.  The status flag can set to
+either \texttt{FG\_EVENT\_SUSP}, \texttt{FG\_EVENT\_READY}, or
+\texttt{FG\_EVENT\_QUEUED}.  \texttt{FG\_EVENT\_SUSP} means register
+the event, but never schedule it to run.  \texttt{FG\_EVENT\_READY}
+means register the event and schedule and run it normally.
+\texttt{FG\_EVENT\_QUEUED} is mostly used internally so that an event
+will never have more than one entry in the run queue.
+
+Finally, in your main loop, you must add a call to
+\texttt{fgEventProcess()} to run it every iteration.  This routine
+will schedule all pending events (push them onto the run queue) and
+then execute the first thing in the run queue.
+
+\section{The Run Queue}
+
+The run queue is a very simple queue who's elements are just a pointer
+to an event list element.  When an event needs to be scheduled, a
+pointer to that event is pushed onto the back of the queue.  Each time
+\texttt{fgEventProcess()} is called, the first element on the run
+queue will be executed.
+
+\section{Profiling Events}
+
+As stated before, each event record contains simple event statistics
+such as the total time spent running this event, the quickest run, the
+slowest run, and the total number of times run.  We can output the
+list of events along with these statistics in order to determine if any of
+them are consuming an excessive amount of time, or if there is any
+chance that a particular event could run slow enough to be responsible
+for a perceived hesitation or pause in the flow of the simulation.
+
+\end{document}
+
+
+%------------------------------------------------------------------------
+% $Log$
+% Revision 1.1  1999/04/05 21:32:34  curt
+% Initial revision
+%
diff --git a/Hints/aaa b/Hints/aaa
new file mode 100644
index 000000000..45744f164
--- /dev/null
+++ b/Hints/aaa
@@ -0,0 +1,306 @@
+From fatcity!root@news.cts.com  Wed Aug 20 16:34:24 1997
+X-VM-v5-Data: ([nil nil nil nil nil nil nil nil nil]
+	["3412" "Wed" "20" "August" "1997" "14:14:39" "-0800" "Steve Baker" "steve@mred.bgm.link.com" nil "83" "Re: culling with view frustrum before view transformation" "^From:" nil nil "8" nil nil nil nil nil]
+	nil)
+Received: from mailhub.cts.com (mailhub.cts.com [204.216.216.130])
+	by meserv.me.umn.edu (8.8.6/8.8.6) with SMTP id QAA04291
+	for ; Wed, 20 Aug 1997 16:34:23 -0500 (CDT)
+Received: from donews.cts.com(really [192.188.72.21]) by mailhub.cts.com
+	via smail with smtp
+	id 
+	for ; Wed, 20 Aug 97 14:25:48 -0700 (PDT)
+	(Smail-3.1.92 1996-Mar-19 #3 built 1996-Apr-21)
+Received: from fatcity by donews.cts.com with uucp
+	(Smail3.1.29.1 #5) id m0x1IG4-000007a; Wed, 20 Aug 97 14:25 PDT
+Received: by fatcity.com (06-Aug-97/v1.0d-b55/bab) via UUCP id 0C90BB6D; Wed, 20 Aug 1997 14:14:39 -0800
+Message-ID: 
+X-Comment: OpenGL Game Developers Mailing List
+X-Sender: steve@mred.bgm.link.com (Steve Baker)
+Reply-To: OPENGL-GAMEDEV-L@fatcity.com
+Errors-To: ML-ERRORS@fatcity.com
+Mime-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
+Content-Transfer-Encoding: 7bit
+Organization: Fat City Network Services, San Diego, California
+X-ListServer: v1.0d, build 55; ListGuru (c) 1996-1997 Bruce A. Bergman
+Precedence: bulk
+From: steve@mred.bgm.link.com (Steve Baker)
+Sender: root@fatcity.com
+To: Multiple recipients of list OPENGL-GAMEDEV-L 
+Subject: Re: culling with view frustrum before view transformation
+Date: Wed, 20 Aug 1997 14:14:39 -0800
+
+> >Brian Hook wrote:
+> >> You can do bounding spheres,
+> >> bounding boxes, or a combination of both (sphere first, then box).
+> >
+> >Which is faster to test for being completely inside, outside, or
+> >partial, of the view frustrum?
+> 
+> Obviously bounding sphere will be the fastest, but since it's, well, a
+> sphere, it's not going to be particularly accurate (since it's rotationally
+> invariant).  
+> 
+> if ( distance( obj.position, plane ) >= obj_sphere.radius )
+>    trivial_reject = true;
+> 
+> (I assume you also check the sign of the distance)
+
+I echo your sentiments that bounding spheres are the fastest approach to
+culling to FOV frustum - also for some kinds of collision detection.
+
+The most important thing to bear in mind about culling is that the first
+trivial-reject test you apply is by far the most time-critical. This test
+is always applied to more nodes than any of the subsequent tests.
+
+So, do the cheapest test first.
+
+This is typically the NEAR plane test. Everything behind the viewers head
+gets chopped out - and it's an especially cheap test.
+
+   if ( obj_sphere.center.z < near_plane - obj_sphere.radius )
+     REJECT!!
+
+...next do the second cheapest test (assuming you know that your database
+could possibly beyond the far clip plane)...
+
+   if ( obj_sphere.center.z - obj_sphere.radius > far_plane )
+     REJECT!!
+
+...and *then* do...
+
+   if ( distance( obj.position, plane ) >= obj_sphere.radius )
+     REJECT!!
+
+It's also useful to know that in many applications, you cull more objects from
+the left and right faces of the frustum than you do from the top and bottom - so
+test left, then right, then bottom then top.
+
+Also, with bounding sphere tests, you shouldn't forget to do total-accept
+as well as total-reject tests. Once you know that an object's sphere is
+TOTALLY on screen, you don't have to descend into the daughter objects to
+cull-test them...you *know* they are all on-screen.
+
+Another way to look at that it to remember which of the six possible plane tests
+didn't even touch the sphere - as you work your way down the object hierarchy,
+you can accumulate those flags and avoid even testing those planes that a parent
+sphere has already cleanly passed. If you do this then a vast percentage of
+your spheres will only need to be tested against one plane.
+
+Sphere-based culling can be extremely cost-effective. It's so cheap that even if
+you feel the need to use a bounding cubeoid (or even a yet more complex shape),
+it's still worth doing a sphere-based cull first just to get rid of the trivial
+accept and reject cases.
+
+
+Steve Baker                     817-619-1361 (Vox-Lab)
+Hughes Training Inc.            817-619-8776 (Vox-Office/Vox-Mail)
+2200 Arlington Downs Road       817-619-4028 (Fax)
+Arlington, Texas. TX 76005-6171 Steve@MrEd.bgm.link.com (eMail)
+http://www.hti.com              http://web2.airmail.net/sjbaker1 (personal)
+
+** Beware of Geeks bearing GIF's. **
+
+
+-- 
+Author: Steve Baker
+  INET: steve@mred.bgm.link.com
+
+Fat City Network Services    -- (619) 538-5030
+San Diego, California        -- Public Internet Access
+-------------------------------------------------------------------
+To REMOVE yourself from this mailing list, send an E-Mail message
+to: ListGuru@fatcity.com (note EXACT spelling of 'ListGuru') and in
+the message BODY, include a line containing: UNSUB OPENGL-GAMEDEV-L
+(or the name of mailing list you want to be removed from).
+
+From fatcity!root@news.cts.com  Thu Aug 21 09:19:20 1997
+X-VM-v5-Data: ([nil nil nil nil nil nil nil nil nil]
+	["2834" "Thu" "21" "August" "1997" "07:00:54" "-0800" "Steve Baker" "steve@mred.bgm.link.com" nil "77" "Re: culling with view FRUSTUM before view transformation" "^From:" nil nil "8" nil nil nil nil nil]
+	nil)
+Received: from mailhub.cts.com (mailhub.cts.com [204.216.216.130])
+	by meserv.me.umn.edu (8.8.6/8.8.6) with SMTP id JAA02567
+	for ; Thu, 21 Aug 1997 09:19:20 -0500 (CDT)
+Received: from donews.cts.com(really [192.188.72.21]) by mailhub.cts.com
+	via smail with smtp
+	id 
+	for ; Thu, 21 Aug 97 07:16:00 -0700 (PDT)
+	(Smail-3.1.92 1996-Mar-19 #3 built 1996-Apr-21)
+Received: from fatcity by donews.cts.com with uucp
+	(Smail3.1.29.1 #5) id m0x1Y1f-0000Qaa; Thu, 21 Aug 97 07:15 PDT
+Received: by fatcity.com (06-Aug-97/v1.0d-b55/bab) via UUCP id 0C90BDD1; Thu, 21 Aug 1997 07:00:54 -0800
+Message-ID: 
+X-Comment: OpenGL Game Developers Mailing List
+X-Sender: steve@mred.bgm.link.com (Steve Baker)
+Reply-To: OPENGL-GAMEDEV-L@fatcity.com
+Errors-To: ML-ERRORS@fatcity.com
+Mime-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
+Content-Transfer-Encoding: 7bit
+Organization: Fat City Network Services, San Diego, California
+X-ListServer: v1.0d, build 55; ListGuru (c) 1996-1997 Bruce A. Bergman
+Precedence: bulk
+From: steve@mred.bgm.link.com (Steve Baker)
+Sender: root@fatcity.com
+To: Multiple recipients of list OPENGL-GAMEDEV-L 
+Subject: Re: culling with view FRUSTUM before view transformation
+Date: Thu, 21 Aug 1997 07:00:54 -0800
+
+> OK, this is probably explained in books etc., but what is the fastest way
+> to find the distance between a point and a plane?
+
+A plane can be represented by the equation
+
+     Ax + By + Cz + D = 0 ;
+
+A,B,C is just the surface normal of the plane and D is the shortest
+distance from the origin to the plane.
+
+So, if you need to find the distance of a point from the plane, just
+imagine a new plane that goes through your test point and is parallel
+to the plane you want to test. The plane equation of that new plane would be:
+
+     A'x + B'y + C'z + D' = 0 ;
+
+Since the two planes are parallel, their surface normals are the same, so
+
+   A' == A
+   B' == B
+   C' == C
+   D' == D + distance_between_the_two_planes
+
+...the only thing that's different is their D values - which differ by the
+distance of your test point from the original plane.
+
+So, for a point (x,y,z), the distance from the plane (A,B,C,D) is
+
+   dist = D' - D
+        = -A'x - B'y - C'z - D
+        = -Ax - By - Cz - D
+        = -( [ABC]dot[xyz] + D )
+
+That's the general result - but culling to the view frustum is a very
+special case...if you are working in eye-relative coordinates (IMHO this
+is best), then since all top,bot,left,right planes of the frustum meet
+at the eye - and since the eye is at the origin (by definition), then
+D is always zero for those plane and that saves you a subtract.
+
+If you are feeling even more in need of optimisation - then you can save one
+multiply per plane by realising that (for rectangular screens) one of the
+three components of the plane equation will always be zero.
+
+  eg for the LEFT clip plane, the Y component of the normal of the plane
+     is zero, so the distance to the left or right plane is just
+
+        - ( A x' + C z' )
+
+     and to the top or bottom plane it's just:
+
+        - ( A x' + B y' )
+
+     Since you are only using this for culling, you don't need the minus sign
+     so the cost of a test can be as little as two multiplies and one add
+     per plane.
+
+
+Steve Baker                     817-619-1361 (Vox-Lab)
+Hughes Training Inc.            817-619-8776 (Vox-Office/Vox-Mail)
+2200 Arlington Downs Road       817-619-4028 (Fax)
+Arlington, Texas. TX 76005-6171 Steve@MrEd.bgm.link.com (eMail)
+http://www.hti.com              http://web2.airmail.net/sjbaker1 (personal)
+
+** Beware of Geeks bearing GIF's. **
+
+
+-- 
+Author: Steve Baker
+  INET: steve@mred.bgm.link.com
+
+Fat City Network Services    -- (619) 538-5030
+San Diego, California        -- Public Internet Access
+-------------------------------------------------------------------
+To REMOVE yourself from this mailing list, send an E-Mail message
+to: ListGuru@fatcity.com (note EXACT spelling of 'ListGuru') and in
+the message BODY, include a line containing: UNSUB OPENGL-GAMEDEV-L
+(or the name of mailing list you want to be removed from).
+
+From fatcity!root@news.cts.com  Fri Aug 22 08:51:10 1997
+X-VM-v5-Data: ([nil nil nil nil nil nil nil nil nil]
+	["2087" "Fri" "22" "August" "1997" "06:31:24" "-0800" "Steve Baker" "steve@mred.bgm.link.com" nil "47" "Re: culling with view FRUSTUM before view transformation" "^From:" nil nil "8" nil nil nil nil nil]
+	nil)
+Received: from mailhub.cts.com (mailhub.cts.com [204.216.216.130])
+	by meserv.me.umn.edu (8.8.6/8.8.6) with SMTP id IAA21767
+	for ; Fri, 22 Aug 1997 08:51:09 -0500 (CDT)
+Received: from donews.cts.com(really [192.188.72.21]) by mailhub.cts.com
+	via smail with smtp
+	id 
+	for ; Fri, 22 Aug 97 06:46:19 -0700 (PDT)
+	(Smail-3.1.92 1996-Mar-19 #3 built 1996-Apr-21)
+Received: from fatcity by donews.cts.com with uucp
+	(Smail3.1.29.1 #5) id m0x1u2a-0000PHa; Fri, 22 Aug 97 06:46 PDT
+Received: by fatcity.com (06-Aug-97/v1.0d-b55/bab) via UUCP id 0C90C1C4; Fri, 22 Aug 1997 06:31:24 -0800
+Message-ID: 
+X-Comment: OpenGL Game Developers Mailing List
+X-Sender: steve@mred.bgm.link.com (Steve Baker)
+Reply-To: OPENGL-GAMEDEV-L@fatcity.com
+Errors-To: ML-ERRORS@fatcity.com
+Mime-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
+Content-Transfer-Encoding: 7bit
+Organization: Fat City Network Services, San Diego, California
+X-ListServer: v1.0d, build 55; ListGuru (c) 1996-1997 Bruce A. Bergman
+Precedence: bulk
+From: steve@mred.bgm.link.com (Steve Baker)
+Sender: root@fatcity.com
+To: Multiple recipients of list OPENGL-GAMEDEV-L 
+Subject: Re: culling with view FRUSTUM before view transformation
+Date: Fri, 22 Aug 1997 06:31:24 -0800
+
+> > > Actually, I find it easier to scale the whole such that D = 1, then you
+> > > only need to store the non-degenerate (A', B', C') vector (i.e., A' =
+> > > A/D, etc...).  Storing a already-normalized (A, B, C) + D quadruple is
+> > > worth it only if you know before hand that the planes will never be
+> > > scaled before their normals are used.  In the general case where a
+> > > scaling is possible, you'll have to renormalize anyway.
+> > 
+> > Normally, I might agree with you - but in the case of Frustum clipping,
+> > scaling the normal by dividing by 'D' is a bad move since D==0 in the
+> > case of all four 'interesting' planes. :-)
+> 
+> Interesting point. This is of course only true when the eyepoint is in
+> the origin, which brings us back to the issue of clipping before or
+> after the modelview transformation.
+ 
+Well - that's a dangerous thing to assume - I mean, the eye might just happen
+to move to the true world coordinate origin (by flook) and crash your program
+with a bunch of divide by zero errors.
+
+In any case, you are going to run into nasty precision problems as your eye
+approaches the origin - even if it doesn't reach it.
+
+> Learn something new every day.... :-)
+
+...Forget something important every night... :-)
+
+
+Steve Baker                     817-619-1361 (Vox-Lab)
+Hughes Training Inc.            817-619-8776 (Vox-Office/Vox-Mail)
+2200 Arlington Downs Road       817-619-4028 (Fax)
+Arlington, Texas. TX 76005-6171 Steve@MrEd.bgm.link.com (eMail)
+http://www.hti.com              http://web2.airmail.net/sjbaker1 (personal)
+
+** Beware of Geeks bearing GIF's. **
+
+
+-- 
+Author: Steve Baker
+  INET: steve@mred.bgm.link.com
+
+Fat City Network Services    -- (619) 538-5030
+San Diego, California        -- Public Internet Access
+-------------------------------------------------------------------
+To REMOVE yourself from this mailing list, send an E-Mail message
+to: ListGuru@fatcity.com (note EXACT spelling of 'ListGuru') and in
+the message BODY, include a line containing: UNSUB OPENGL-GAMEDEV-L
+(or the name of mailing list you want to be removed from).
+
diff --git a/Hints/endian-ness b/Hints/endian-ness
new file mode 100644
index 000000000..8800ebd4d
--- /dev/null
+++ b/Hints/endian-ness
@@ -0,0 +1,71 @@
+From fatcity!root@news.cts.com  Fri May 15 08:52:18 1998
+X-VM-v5-Data: ([nil nil nil nil nil nil nil nil nil]
+	["1426" "Fri" "15" "May" "1998" "06:30:53" "-0800" "Steve Baker" "sbaker@link.com" nil "39" "Re: Endian swapping" "^From:" nil nil "5" nil nil nil nil nil]
+	nil)
+Received: from mh2.cts.com (root@mh2.cts.com [205.163.24.68])
+	by meserv.me.umn.edu (8.8.8/8.8.8) with ESMTP id IAA18883
+	for ; Fri, 15 May 1998 08:52:18 -0500 (CDT)
+Received: from king.cts.com (root@king.cts.com [198.68.168.21]) by mh2.cts.com (8.8.7/8.8.5) with ESMTP id GAA12800; Fri, 15 May 1998 06:52:14 -0700 (PDT)
+Received: from donews.cts.com (root@donews.cts.com [192.188.72.21])
+	by king.cts.com (8.8.7/8.8.7) with SMTP id GAA18786;
+	Fri, 15 May 1998 06:52:13 -0700 (PDT)
+Received: from fatcity by donews.cts.com with uucp
+	(Smail3.1.29.1 #5) id m0yaKtA-00001sa; Fri, 15 May 98 06:51 PDT
+Received: by fatcity.com (10-Feb-1998/v1.0f-b64/bab) via UUCP id 00027B2C; Fri, 15 May 1998 06:30:53 -0800
+Message-ID: 
+X-Comment: OpenGL Game Developers Mailing List
+X-Sender: Steve Baker 
+Reply-To: OPENGL-GAMEDEV-L@fatcity.com
+Errors-To: ML-ERRORS@fatcity.com
+Organization: Fat City Network Services, San Diego, California
+X-ListServer: v1.0f, build 64; ListGuru (c) 1996-1998 Bruce A. Bergman
+Precedence: bulk
+Mime-Version: 1.0
+Content-Type: TEXT/PLAIN; charset=US-ASCII
+Content-Transfer-Encoding: 7bit
+From: Steve Baker 
+Sender: root@fatcity.com
+To: Multiple recipients of list OPENGL-GAMEDEV-L 
+Subject: Re: Endian swapping
+Date: Fri, 15 May 1998 06:30:53 -0800
+
+On Fri, 15 May 1998, Sean L. Palmer wrote:
+
+> I'm trying to make this library as cross-platform as humanly possible with
+> my limited resources, so if anyone has any code to detect whether the target
+> is Big- or Little-endian, please e-mail it my way.
+ 
+/*
+  Return TRUE if this machine is little endian,
+  FALSE otherwise.
+*/
+
+int is_little_endian ()
+{
+  int i = 1 ;
+
+  return *((char *) &i) ;
+}
+
+...this works because the address of an integer on a little-endian machine is
+the address of the low order byte (whose value is 1) and on a big-endian machine,
+it's the address of the high order byte (whose value is 0).
+
+Steve Baker                (817)619-8776 (Vox/Vox-Mail)
+Raytheon Systems Inc.      (817)619-4028 (Fax)
+Work: SBaker@link.com      http://www.hti.com
+Home: SJBaker1@airmail.net http://web2.airmail.net/sjbaker1
+
+-- 
+Author: Steve Baker
+  INET: sbaker@link.com
+
+Fat City Network Services    -- (619) 538-5051  FAX: (619) 538-5051
+San Diego, California        -- Public Internet access / Mailing Lists
+--------------------------------------------------------------------
+To REMOVE yourself from this mailing list, send an E-Mail message
+to: ListGuru@fatcity.com (note EXACT spelling of 'ListGuru') and in
+the message BODY, include a line containing: UNSUB OPENGL-GAMEDEV-L
+(or the name of mailing list you want to be removed from).  You may
+also send the HELP command for other information (like subscribing).
+
diff --git a/Hints/gamma b/Hints/gamma
new file mode 100644
index 000000000..0cef4f13f
--- /dev/null
+++ b/Hints/gamma
@@ -0,0 +1,186 @@
+From owner-flight-gear@me.umn.edu  Thu Apr 23 08:45:16 1998
+X-VM-v5-Data: ([nil nil nil nil nil nil nil nil nil]
+	["7258" "Thu" "23" "April" "1998" "09:44:56" "-0500" "Steve Baker" "sbaker@link.com" nil "158" "Re: [FGFS] lighting question" "^From:" nil nil "4" nil nil nil nil nil]
+	nil)
+Received: (from majordom@localhost)
+	by meserv.me.umn.edu (8.8.8/8.8.8) id IAA05148
+	for flight-gear-outgoing; Thu, 23 Apr 1998 08:45:16 -0500 (CDT)
+X-Authentication-Warning: meserv.me.umn.edu: majordom set sender to owner-flight-gear@me.umn.edu using -f
+Received: from lfkw10.bgm.link.com (bgm.link.com [130.210.2.10])
+	by meserv.me.umn.edu (8.8.8/8.8.8) with ESMTP id IAA05144
+	for ; Thu, 23 Apr 1998 08:45:10 -0500 (CDT)
+Received: from sutcliffe.bgm.link.com (sutcliffe.bgm.link.com [130.210.236.18])
+          by lfkw10.bgm.link.com (8.8.6/HTI-Hack-8.8.4) with SMTP
+	  id IAA29813 for ; Thu, 23 Apr 1998 08:44:39 -0500 (CDT)
+X-Sender: steve@sutcliffe.bgm.link.com
+In-Reply-To: <199804230119.UAA13239@kenai.me.umn.edu>
+Message-ID: 
+MIME-Version: 1.0
+Content-Type: TEXT/PLAIN; charset=US-ASCII
+Precedence: bulk
+Reply-To: flight-gear@me.umn.edu
+From: Steve Baker 
+Sender: owner-flight-gear@me.umn.edu
+To: flight-gear@me.umn.edu
+Subject: Re: [FGFS] lighting question
+Date: Thu, 23 Apr 1998 09:44:56 -0500 (CDT)
+
+On Wed, 22 Apr 1998, Curtis L. Olson wrote:
+
+> Here's a lighting question for someone.
+> 
+> Let's say it's noon-ish.  If I set the ambient light component to
+> about 0.3 and the diffuse light component to about 1.0 I get a
+> reasonably bright scene with good contrast in the shadowy areas.
+> 
+> Now, I'm running into problems when the sun is low in the sky.  Even
+> with a high diffuse lighting component (1.0) the angle the sun light
+> makes with the horizontal ground is very small so the diffuse lighting
+> component ends up being virtually nothing.  I'm fiddling around with
+> trying to increase the ambient component to 1.0, but I still get a
+> very dark scene.
+ 
+...simple question - long answer - sorry...
+
+First the "Why does this look bad?" answer...
+
+  Well, when the sun is low in the sky, that is exactly what really
+  does happen - the angle between sun and (flattish) ground gets small
+  and it gets dark.
+
+  The problem is that our eyes have automatic gain control. When the
+  world gets darker, we increase our pupil apartures to increase the
+  amount of light we allow in. That only works when the whole world
+  goes darker - and not in a room in normal daylight containing a
+  small, dim CRT.
+
+  Also, in the real world, the sun lights things much more brightly
+  than a CRT phosphor can reproduce. When you drop that brightness
+  by (say) a factor of ten because it's dusk then the sun is still
+  pretty bright - but 1/10th the brightness on a CRT phosphor is pretty
+  dim.
+
+  If you watch your sunset scenes in a darkened room, they'll look
+  much better. However, for a desktop simulation, that may not help.
+
+  The other reason there is a problem is that the CRT phosphor is 
+  not a linear device - if you double the number for the pixel
+  brightness - you don't get twice the brightness coming out the
+  other side. This non-linearity is *supposed* to be corrected
+  by a process called 'gamma correction' which works by boosting
+  the contrast of the dark pixels and reducing the contrast of
+  the bright ones.
+
+  Fixing the gamma will help noon-time scenes as well as dusk
+  and dawn since the amount of stuff you can see in shadowed
+  areas will be better if the gamma is set right.
+
+  The required amount of gamma modification changes with the
+  age of the CRT and which particular choice of phosphor layer
+  the CRT manufacturer made. You may also need more gamma correction
+  in (say) the BLUE channel than in RED or GREEN.
+
+  Fancy machines like SGI ONYX's have hardware gamma tables on
+  the output of the machine to do this correction - I doubt that
+  all the PC-based 'toy' 3D cards have this feature.
+
+Now, the "What can we do to improve matters?" answer...
+
+  Well, you seem to be on the right track - you basically have to increase
+  the ambient light to make up for the missing light on the horizontal
+  surfaces. However, this tends to reduce the amount of contrast between
+  the dark regions and the vertical surfaces that are being brightly lit
+  just as the sun goes down. That is the opposite of the real world since
+  the shadows are much more contrasty late in the day than they are at noon.
+  (That is a subjective thing - I could be wrong about that)
+
+  You said:
+
+  > I'm fiddling around with trying to increase the ambient component to 1.0,
+  > but I still get a very dark scene.
+
+  ...that suprises me - you ought to be getting a very bright scene
+  with ambient==1.0 since all surfaces are being lit with a very bright
+  light that is ignoring their orientation. The scene should be brighter
+  than at noon.
+
+  Perhaps you don't have the ambient component of the glMaterial set
+  up right?
+
+  On the gamma front, there are two experiments you can try:
+
+    Curt: I know you have access to an SGI RE2 machine - and that
+    you can run FGFS on it. So, run FGFS up and set the time of
+    day to dusk - so you have the too-dark scene. Now open another
+    shell window and try running 'gamma 1.0' then 'gamma 1.5' then
+    'gamma 2.0'. If I'm right about the gamma setting being the problem
+    then gamma 1.0 should look just like it does on the PC, and
+    (depending on the age of your CRT), 1.5 or 2.0 (or something like
+    that) should make it look much better.
+
+    If you can't get to an SGI machine then do a screen dump of your
+    image into a file, then load that file into Xview (under Linux)
+    or something like photoshop. Image processing programs like this
+    usually let you change the gamma for an image interactively by
+    recomputing the pixels (this eliminates the need for gamma hardware).
+    In XView, pick the colour editor window and click on the gamma
+    button next to the intensity graph. Type in 2.0 (or whatever) and
+    you'll notice that the curve in the window looks like this:
+
+
+                    ****
+                  **
+                 *
+                *
+               *
+               *
+              *
+              *
+              *
+  
+     (pardon the ASCII art)
+
+     ....which means that the dark areas have been increased in contrast
+     and the light areas reduced in contrast.
+
+   If either of these tests shows that gamma is indeed your problem then
+   you need to think about how to set the gamma on your hardware.
+
+   For software OpenGL with Mesa - I think Mesa has a gamma setting
+   extension (or an environment variable or something) - the 3Dfx
+   card (IIRC) has a way to set the gamma too - although I don't
+   know how. The general way to set the gamma is not through OpenGL,
+   so doing this in a portable way from inside FGFS is going to be hard.
+   You may have to rely on the user setting it up in some external
+   tool (a windoze control panel most likely).
+
+> I may have something fouled up, or may not understand something
+> correctly, but does anyone have any suggestions as to what the ambient
+> and diffuse lighting components ought to be set to in order for the
+> scenery to be "realistically" lit  when the sun is low in the sky?
+
+Well, 'realistically' is a hard thing - the human eye can discern detail
+in a scene lit at a gazillion candelas - all the way down to a gazillionth
+of a candela, lots of orders of magnitude. A CRT can only display the
+number of brightness levels provided in the frame buffer (256 if you are
+lucky - a mere 2.5 orders of magnitude) - and is VERY dim in any case.
+
+Getting 'realistic' brightnesses just isn't going to happen on a desktop
+display system - so it's all a matter of compromise.
+
+On 'real' flight simulators, the fight for better contrast and brightness
+and more orders of magnitude of brightness variation is a continual battle
+that results in some pretty exotic display technologies. (Things like
+shining an arc-lamp onto a million tiny mirrors that are tilted using
+pizo-electric effects to modulate the brightness...ugh!)
+
+Steve Baker                (817)619-8776 (Vox/Vox-Mail)
+Raytheon Systems Inc.      (817)619-4028 (Fax)
+Work: SBaker@link.com      http://www.hti.com
+Home: SJBaker1@airmail.net http://web2.airmail.net/sjbaker1
+
+-------------------------------------
+Please visit the FGFS web page:  http://www.menet.umn.edu/~curt/fgfs/
+For help on using this list (especially unsubscribing), send a message to
+"flight-gear-request@me.umn.edu" with a single line of text: "help".
+
diff --git a/Hints/joystick b/Hints/joystick
new file mode 100644
index 000000000..048d88ed1
--- /dev/null
+++ b/Hints/joystick
@@ -0,0 +1,73 @@
+From owner-fgfs-devel@flightgear.org  Mon Sep 14 10:44:02 1998
+X-VM-v5-Data: ([nil nil nil nil nil nil nil nil nil]
+	["1542" "Mon" "14" "September" "1998" "10:41:38" "-0500" "Steve Baker" "sbaker@link.com" nil "42" "Re: FGFS: Windows Joystick support" "^From:" nil nil "9" nil nil nil nil nil]
+	nil)
+Received: from mailhub.woodsoup.org (IDENT:root@anduin.physics.iastate.edu [129.186.82.1])
+	by meserv.me.umn.edu (8.9.1a/8.9.1) with ESMTP id KAA21095
+	for ; Mon, 14 Sep 1998 10:44:00 -0500 (CDT)
+Received: from majordom by mailhub.woodsoup.org with local (Exim 1.92 #1)
+	for fgfs-devel-outgoing@flightgear.org
+	id 0zIamX-0005os-00; Mon, 14 Sep 1998 10:43:13 -0500
+Received: from bgm.link.com ([130.210.2.10] helo=lfkw10.bgm.link.com)
+	by mailhub.woodsoup.org with esmtp (Exim 1.92 #1)
+	for fgfs-devel@flightgear.org
+	id 0zIamW-0005ok-00; Mon, 14 Sep 1998 10:43:12 -0500
+Received: from samantha.bgm.link.com (samantha.bgm.link.com [130.210.65.19])
+          by lfkw10.bgm.link.com (8.8.6/RSC-RTI-1.0) with SMTP
+	  id KAA21757; Mon, 14 Sep 1998 10:42:23 -0500 (CDT)
+X-Sender: steve@samantha.bgm.link.com
+Reply-To: Steve Baker 
+In-Reply-To: <3.0.5.32.19980913154136.007e8440@umr.edu>
+Message-ID: 
+MIME-Version: 1.0
+Content-Type: TEXT/PLAIN; charset=US-ASCII
+Precedence: bulk
+From: Steve Baker 
+Sender: owner-fgfs-devel@flightgear.org
+To: William Riley 
+cc: fgfs-devel@flightgear.org
+Subject: Re: FGFS: Windows Joystick support
+Date: Mon, 14 Sep 1998 10:41:38 -0500 (CDT)
+
+On Sun, 13 Sep 1998, William Riley wrote:
+
+> Is anyone working on joystick support for Win9x/NT?  I'm a fledgling
+> programmer and was thinking about tacking this task.  If anyone has started
+> (or finished) please email me directly or through the list.  Thanks.
+ 
+There is basic joystick support in GLUT - I presume the simplest thing
+to do to start with is to use that since the result will be portable to
+all of our target systems.
+
+The downside is that IIRC, GLUT only supports a very simple joystick
+setup (single stick, two axes, two buttons).
+
+Whatever API we finally choose needs to consider the portability issues.
+
+IMHO, it would be better to extend GLUT and offer any improvements back
+into the general Freeware community rather than to settle on an ad'hoc
+FGFS-specific solution.
+
+Joystick info for Linux can be found here:
+
+  http://atrey.karlin.mff.cuni.cz/~vojtech/joystick/
+
+Joystick programming info for Windoze is here:
+
+  http://www.hut.fi/Misc/Electronics/docs/joystick/pc_joystick.html#programming
+
+That same site has a TON of interesting joystick info:
+
+  http://www.hut.fi/Misc/Electronics/docs/joystick/
+
+GLUT's joystick support is not documented yet since it's only present in the
+very latest GLUT 3.7 beta. However, if you check the source code for that
+release of GLUT, you'll see how it's done there.
+
+
+Steve Baker                (817)619-2657 (Vox/Vox-Mail)
+Raytheon Systems Inc.      (817)619-4028 (Fax)
+Work: SBaker@link.com      http://www.hti.com
+Home: SJBaker1@airmail.net http://web2.airmail.net/sjbaker1
+
+
diff --git a/Hints/lights.c b/Hints/lights.c
new file mode 100644
index 000000000..026680ee9
--- /dev/null
+++ b/Hints/lights.c
@@ -0,0 +1,288 @@
+From curt@infoplane.com  Fri Nov 13 06:10:29 1998
+X-VM-v5-Data: ([nil nil nil nil nil nil nil nil nil]
+	["6615" "Fri" "13" "November" "1998" "06:10:23" "-0600" "curt@infoplane.com" "curt@infoplane.com" nil "271" "fuzzy-light-effect" "^From:" nil nil "11" nil nil nil nil nil]
+	nil)
+Received: from dorthy.state.net (dorthy.state.net [209.234.62.254])
+	by meserv.me.umn.edu (8.9.1a/8.9.1) with ESMTP id GAA15847
+	for ; Fri, 13 Nov 1998 06:10:28 -0600 (CST)
+Received: from sledge.infoplane.com (curt@sledge.infoplane.com [204.120.151.21]) by dorthy.state.net (8.8.8/8.7.2) with ESMTP id GAA25998 for ; Fri, 13 Nov 1998 06:10:08 -0600 (CST)
+Received: (from curt@localhost)
+	by sledge.infoplane.com (8.8.8/8.8.8/Debian/GNU) id GAA24798
+	for curt@me.umn.edu; Fri, 13 Nov 1998 06:10:23 -0600
+Message-Id: <199811131210.GAA24798@sledge.infoplane.com>
+From: curt@infoplane.com
+To: curt@me.umn.edu
+Subject: fuzzy-light-effect
+Date: Fri, 13 Nov 1998 06:10:23 -0600
+
+/* stars - draws a twisting sphere of eerie lights
+   Copyright (C) 1998 James Bowman
+
+stars 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, or (at your option)
+any later version.
+
+gpasm 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 gpasm; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#include 
+#include 
+#include 
+#include        /* for cos(), sin(), and sqrt() */
+#include 
+#ifdef WIN32
+#include 
+#else
+#include 
+#endif
+#include 
+
+static int phi;                 /* Global clock */
+static int texWidth = 64;       /* 64x64 is plenty */
+
+/************************************************************************/
+
+/* Generate a pleasing, light-shaped texture. */
+
+static void
+setTexture(void)
+{
+  int texSize;
+  void *textureBuf;
+  GLubyte *p;
+  int i,j;
+  double radius;
+
+  texSize = texWidth*texWidth;
+
+  textureBuf = malloc(texSize);
+  if (NULL == textureBuf) return;
+
+  p = (GLubyte *)textureBuf;
+
+  radius = (double)(texWidth / 2);
+
+  for (i=0; i < texWidth; i++) {
+    for (j=0; j < texWidth; j++) {
+      double x, y, d;
+            
+      x = fabs((double)(i - (texWidth / 2)));
+      y = fabs((double)(j - (texWidth / 2)));
+
+      d = sqrt((x * x) + (y * y));
+      if (d < radius) {
+        double t = 1.0 - (d / radius); /* t is 1.0 at center,
+                                          0.0 at edge */
+
+        /* inverse square looks nice */
+        *p = (int)((double)0xff * (t * t));
+      } else
+        *p = 0x00;
+      p++;
+    }
+  }
+
+  gluBuild2DMipmaps(GL_TEXTURE_2D, 1, texWidth, texWidth, 
+                    GL_LUMINANCE,
+                    GL_UNSIGNED_BYTE, textureBuf);
+  free(textureBuf);
+}
+
+/************************************************************************/
+
+static int W, H;
+
+#define NUM_STARS 100
+
+#define frand()  ((float)(rand() & 0xfff) / (float)0x1000)  /* 0.0 - 1.0 */
+#define frand2() (1.0f - (2.0f * frand()))                  /* -1 - +1   */
+
+/* Normalise the input vector */
+static void vecNormalise(float *vv)
+{
+  double mag;
+
+  mag = sqrt((vv[0] * vv[0]) + (vv[1] * vv[1]) + (vv[2] * vv[2]));
+  vv[0] /= mag;
+  vv[1] /= mag;
+  vv[2] /= mag;
+}
+
+void
+redraw_viewing(void)
+{
+  static int cold = 1;
+  static float stars[NUM_STARS * 3];
+  GLfloat fb_buffer[NUM_STARS * 4];
+  int i;
+
+  if (cold) {
+    /* Position all the stars more-or-less randomly on the surface
+     * of a unit sphere. */
+    for (i = 0; i < NUM_STARS; i++) {
+      stars[3 * i + 0] = frand2();
+      stars[3 * i + 1] = frand2();
+      stars[3 * i + 2] = frand2();
+      vecNormalise(&stars[3 * i]);
+    }
+    cold = 0;
+  }
+
+  glClear(GL_COLOR_BUFFER_BIT);
+
+  /* First use feedback to determine the screen positions of the
+     stars. */
+  glFeedbackBuffer(NUM_STARS * 4, GL_3D, fb_buffer);
+  glRenderMode(GL_FEEDBACK);
+
+  glMatrixMode(GL_MODELVIEW);
+  glPushMatrix();
+  glRotatef(phi % 360, 0.0f, 1.0f, 0.0f); /* Constant spin */
+  glRotatef(sin((double)phi / 300.0) * 150.0,   /* Periodic twist */
+            0.1f, 0.6f, -0.5f);
+  glBegin(GL_POINTS);
+  for (i = 0; i < NUM_STARS; i++)
+    glVertex3fv(&stars[3 * i]);
+  glEnd();
+  glPopMatrix();
+  glRenderMode(GL_RENDER);      /* No more feedback */
+
+  /* Now draw the stars as sprites. */
+  glEnable(GL_TEXTURE_2D);
+  glEnable(GL_BLEND);           /* Simple additive blend is fine */
+  glBlendFunc(GL_ONE, GL_ONE);
+
+  /* Choose a color triple like this so that when the sprites overlap
+   * and the color saturates, red will clamp first, then green, then
+   * blue. */
+  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+  glColor3f(1.0f, 0.75f, 0.5f);
+
+  /* Set up projection and modelview matrix that gives us a 1:1
+   * mapping to screen coordinates. */
+  glMatrixMode(GL_PROJECTION);
+  glPushMatrix();
+  glLoadIdentity();
+  glMatrixMode(GL_MODELVIEW);
+  glPushMatrix();
+  glLoadIdentity();
+  glScalef(2.0f / (GLfloat)W, 2.0f / (GLfloat)H, 1.0f);
+  glTranslatef(0.5f * -(GLfloat)W, 0.5f * -(GLfloat)H, 0.0f);
+
+  {
+    float width;
+    float x, y, z;
+    int i;
+
+    glBegin(GL_QUADS);
+
+    for (i = 0; i < NUM_STARS; i++) {
+      /* Skip the GL_POINT_TOKEN */
+      x = fb_buffer[4 * i + 1];
+      y = fb_buffer[4 * i + 2];
+      z = fb_buffer[4 * i + 3];
+
+      width = 10.0 * (2.0 - z); /* Arbitrary distance attenuation */
+
+      glTexCoord2f(0.0f, 0.0f);
+      glVertex2f(x - width, y - width);
+
+      glTexCoord2f(1.0f, 0.0f);
+      glVertex2f(x + width, y - width);
+
+      glTexCoord2f(1.0f, 1.0f);
+      glVertex2f(x + width, y + width);
+      
+      glTexCoord2f(0.0f, 1.0f);
+      glVertex2f(x - width, y + width);
+    }
+
+    glEnd();
+  }
+
+  glMatrixMode(GL_MODELVIEW);
+  glPopMatrix();
+  glMatrixMode(GL_PROJECTION);
+  glPopMatrix();
+  
+  glutSwapBuffers();
+}
+
+void
+reshape_viewing(int w, int h)
+{
+  glViewport(0, 0, w, h);
+  W = w;
+  H = h;
+}
+
+/************************************************************************/
+
+void
+animate(void)
+{
+  phi++;
+  redraw_viewing();
+}
+
+void
+key(unsigned char key, int x, int y)
+{
+  switch (key) {
+  case 27:
+  case 'q':
+    exit(0);
+  }
+}
+
+int
+main(int argc, char **argv)
+{
+  glutInit(&argc, argv);
+
+  glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
+  glutInitWindowSize(640, 480);
+
+  glutCreateWindow("stars");  
+  glutReshapeFunc(reshape_viewing);
+  glutDisplayFunc(redraw_viewing);
+
+  glutIdleFunc(animate);
+  glutKeyboardFunc(key);
+
+  glDisable(GL_DEPTH_TEST);
+  glDisable(GL_LIGHTING);
+
+  glMatrixMode(GL_MODELVIEW);
+
+  setTexture();
+  glTexParameteri(GL_TEXTURE_2D,
+                  GL_TEXTURE_MIN_FILTER,
+                  GL_LINEAR_MIPMAP_NEAREST);
+  glTexParameteri(GL_TEXTURE_2D,
+                  GL_TEXTURE_MAG_FILTER,
+                  GL_LINEAR);
+
+  glMatrixMode(GL_PROJECTION);
+  gluPerspective( /* field of view in degree */ 40.0f,
+                  /* aspect ratio             */ 1.0f,
+                  /* Z near */ 3.0f,
+                  /* Z far */ 5.0f);
+  glMatrixMode(GL_MODELVIEW);
+  gluLookAt(0.0f, 0.0f, 4.0f,   /* eye position */
+    0.0f, 0.0f, 0.0f,           /* looking at */
+    0.0f, 1.0f, 0.0f);          /* up vector */
+
+  glutMainLoop();
+  return 0;             /* ANSI C requires main to return int. */
+}
+
diff --git a/Hints/mip-mapping b/Hints/mip-mapping
new file mode 100644
index 000000000..d3dd74863
--- /dev/null
+++ b/Hints/mip-mapping
@@ -0,0 +1,118 @@
+From sbaker@link.com  Thu Mar 12 22:51:27 1998
+X-VM-v5-Data: ([nil nil nil nil t nil nil nil nil]
+	["4342" "Thu" "12" "March" "1998" "22:50:07" "-0600" "Steve Baker" "sbaker@link.com" "" "95" "Re: Texturing (finally)" "^From:" nil nil "3" nil nil nil nil nil]
+	nil)
+Received: from lfkw10.bgm.link.com (bgm.link.com [130.210.2.10])
+	by meserv.me.umn.edu (8.8.8/8.8.8) with ESMTP id WAA13969
+	for ; Thu, 12 Mar 1998 22:51:26 -0600 (CST)
+Received: from lechter.bgm.link.com (lechter.bgm.link.com [130.210.239.45])
+          by lfkw10.bgm.link.com (8.8.6/HTI-Hack-8.8.4) with SMTP
+   id WAA25775 for ; Thu, 12 Mar 1998 22:50:51 -0600 (CST)
+X-Sender: steve@lechter.bgm.link.com
+Reply-To: Steve Baker 
+In-Reply-To: <199803121856.MAA05616@kenai.me.umn.edu>
+Message-ID: 
+MIME-Version: 1.0
+Content-Type: TEXT/PLAIN; charset=US-ASCII
+Status: RO
+From: Steve Baker 
+To: "Curtis L. Olson" 
+Subject: Re: Texturing (finally)
+Date: Thu, 12 Mar 1998 22:50:07 -0600 (CST)
+
+On Thu, 12 Mar 1998, Curtis L. Olson wrote:
+
+> Steve Baker writes:
+> > So you have the texture into OpenGL using glGenTextures /
+> > glBindTexture and you have a number for each texture?  Does the
+> > routine generate the MIPmaps for you?
+> 
+> I found some code that looks like it might do the mipmapping ... I'll
+> fiddle around with that a bit if I get a chance.
+ 
+Once you have an image in memory, the code in the RedBook is all you need.
+
+There is a glu function for generating the MIPmaps. It works OK for
+starters - but eventually you'll want to rewrite it. Since the sources
+for glu are provided with Mesa (and they work with ANY OpenGL), you
+can easily take the standard glu code and hack it yourself later.
+
+The main thing that I find I need to do with MIPmapping is to control
+the final alpha value of MIPmapped transparency textures. Simply averaging
+all the high level texel Alpha's together to get the lowest LOD doesn't
+work very well in some applications for translucent texture.
+
+However, that won't matter to you for a LONG while yet - so just steal
+the RedBook examples.
+
+> > As a starter (just to get something going), you could simply divide
+> > the latitude and longitude of each terrain vertex by some suitable
+> > constant and use that as the texture coordinate. Alternatively, you
+> > could let OpenGL do the work using glTexGenf.
+> 
+> Tell me more about glTexGenf().
+
+I have to come clean here and mention that I have never actually used
+glTexGenf.
+
+Basically, it provides a mechanism where OpenGL will generate the
+texture coordinates for you automatically using other vertex information.
+I forget all the modes it has - but IIRC, one of them allows you to specify
+the equation of a plane (A,B,C,D where: Ax+By+Cz+D==0) - and the texture
+coordinates are computed by projecting each vertex (x,y,z) onto that
+plane.
+
+If you set that plane to be a plane that is tangential to the earth
+at the center of the terrain tile that you are rendering, then the
+texture would 'drape' itself nicely over the terrain - but there would
+be seams at the edge of each tile.
+
+>  All my coordinates come off the disk
+> in (X, Y, Z) so it would take some computational effort to convert
+> back to lon/lat ...
+
+Yes - you'd need to store (X,Y,Z,S,T) for each vertex on disk and compute
+the texture coordinates in the terrain tool. You'd need to do that
+eventually anyway since the number you use to multiply the lat/long
+to convert to S,T will be different for each kind of texture map - and
+for databases at different latitudes (otherwise the texture gets all
+squashed up near the poles).
+
+I guess if you don't want to change your file format that much, you
+could store a matrix at the top of the file that could be used to
+transform (X,Y,Z) into (S,T,garbage).  But that's really the same
+thing as using glTexGen to do the work - and you'll still get seams
+at the edge of every terrain tile whenever the matrix changes.
+
+Since OpenGL supports the idea of a texture matrix, you could simply
+load your per-tile matrix onto the OpenGL texture matrix stack and
+use glTexCoord3f(x,y,z) [where (x,y,z) is the same vertex coordinate
+that you pass to glVertex3f()].
+
+However, in your quest to DO THE RIGHT THING, there is little choice
+but to store the texture S,T in the file along with the other vertex
+information - any other approach is going to produce seams in the texture
+and sooner or later, you'll get dissatisfied with that.
+
+I suggest that in the short term, you use the texture matrix approach
+since that gets you a textured image *quickly*. It will also let you
+debug the texture loader, the MIPmapping, the glTexBind, etc stuff
+and so on. You'll be able to find some nice textures and make some
+new (and v.cool) screen shots. Switching to stored (S,T) coords is
+something you can attack later when the seams get too annoying.
+
+>  Right now I'm using fg_random() to specify
+> texture coordinates :-) It seems to work, but has some strange
+> effects. :-)
+
+Strange!!...I'm not suprised!
+
+Steve Baker                     817-619-8776 (Vox/Vox-Mail)
+Raytheon Systems Inc.           817-619-4028 (Fax)
+2200 Arlington Downs Road       SBaker@link.com (eMail)
+Arlington, Texas. TX 76005-6171 SJBaker1@airmail.net (Personal eMail)
+http://www.hti.com        http://web2.airmail.net/sjbaker1 (personal)
+
+** Beware of Geeks bearing GIF's. **
+
+
diff --git a/Hints/nmea b/Hints/nmea
new file mode 100644
index 000000000..27cfbb670
--- /dev/null
+++ b/Hints/nmea
@@ -0,0 +1,101 @@
+From curt@me.umn.edu  Fri Nov 13 17:02:31 1998
+X-VM-v5-Data: ([nil nil nil nil nil nil nil nil nil]
+	["209" "Fri" "13" "November" "1998" "17:02:29" "-0600" "Curtis L. Olson" "curt@me.umn.edu" nil "6" "nmea stuff 3" "^From:" nil nil "11" nil nil nil nil nil]
+	nil)
+Received: from kenai.me.umn.edu (curt@kenai.me.umn.edu [134.84.18.22])
+	by meserv.me.umn.edu (8.9.1a/8.9.1) with ESMTP id RAA29774
+	for ; Fri, 13 Nov 1998 17:02:31 -0600 (CST)
+Received: (from curt@localhost)
+	by kenai.me.umn.edu (8.9.1/8.9.1) id RAA32468;
+	Fri, 13 Nov 1998 17:02:30 -0600
+MIME-Version: 1.0
+Content-Type: text/plain; charset=us-ascii
+Content-Transfer-Encoding: 7bit
+Message-ID: <13900.47749.734021.549964@kenai.me.umn.edu>
+X-Mailer: VM 6.61 under Emacs 19.34.1
+From: "Curtis L. Olson" 
+To: curt@me.umn.edu
+Subject: nmea stuff 3
+Date: Fri, 13 Nov 1998 17:02:29 -0600 (CST)
+
+http://www.marinesoft.com/Navigation/Technical/index.htm
+-- 
+Curtis Olson                        University of MN, ME Dept.
+curt@me.umn.edu                     
+http://www.menet.umn.edu/~curt      Try Linux!
+
+From curt@me.umn.edu  Fri Nov 13 16:41:49 1998
+X-VM-v5-Data: ([nil nil nil nil nil nil nil nil nil]
+	["730" "Fri" "13" "November" "1998" "16:41:47" "-0600" "Curtis L. Olson" "curt@me.umn.edu" nil "21" "nmea stuff 2" "^From:" nil nil "11" nil nil nil nil nil]
+	nil)
+Received: from kenai.me.umn.edu (curt@kenai.me.umn.edu [134.84.18.22])
+	by meserv.me.umn.edu (8.9.1a/8.9.1) with ESMTP id QAA29467
+	for ; Fri, 13 Nov 1998 16:41:48 -0600 (CST)
+Received: (from curt@localhost)
+	by kenai.me.umn.edu (8.9.1/8.9.1) id QAA32325;
+	Fri, 13 Nov 1998 16:41:47 -0600
+MIME-Version: 1.0
+Content-Type: text/plain; charset=us-ascii
+Content-Transfer-Encoding: 7bit
+Message-ID: <13900.46507.212248.131431@kenai.me.umn.edu>
+X-Mailer: VM 6.61 under Emacs 19.34.1
+From: "Curtis L. Olson" 
+To: curt@me.umn.edu
+Subject: nmea stuff 2
+Date: Fri, 13 Nov 1998 16:41:47 -0600 (CST)
+
+http://www.fet.uni-hannover.de/~purnhage/gps/gps.html
+
+garman hacking project
+    http://www.abnormal.com/~thogard/gps/grmnhack.html
+
+nmea code documents
+    http://www.oce.orst.edu/Wecoma/Docs/Computing/XMidas/Formatter_ID.html
+    http://www.oce.orst.edu/Wecoma/Docs/Computing/XMidas/NMEA_0183_Format.html
+
+http://www.cl.cam.ac.uk/users/ijl20/nmea.txt
+
+http://www.cl.cam.ac.uk/users/ijl20/gps_file.html
+
+(*) http://vancouver-webpages.com/pub/peter/index.html
+    http://vancouver-webpages.com/pub/peter/idx_nmeadoc.html
+    http://vancouver-webpages.com/pub/peter/nmeafaq.txt
+-- 
+Curtis Olson                        University of MN, ME Dept.
+curt@me.umn.edu                     
+http://www.menet.umn.edu/~curt      Try Linux!
+
+From curt@me.umn.edu  Fri Nov 13 15:10:29 1998
+X-VM-v5-Data: ([nil nil nil nil nil nil nil nil nil]
+	["376" "Fri" "13" "November" "1998" "15:10:27" "-0600" "Curtis L. Olson" "curt@me.umn.edu" nil "14" "nmea stuff" "^From:" nil nil "11" nil nil nil nil nil]
+	nil)
+Received: from kenai.me.umn.edu (curt@kenai.me.umn.edu [134.84.18.22])
+	by meserv.me.umn.edu (8.9.1a/8.9.1) with ESMTP id PAA27473
+	for ; Fri, 13 Nov 1998 15:10:28 -0600 (CST)
+Received: (from curt@localhost)
+	by kenai.me.umn.edu (8.9.1/8.9.1) id PAA31952;
+	Fri, 13 Nov 1998 15:10:27 -0600
+MIME-Version: 1.0
+Content-Type: text/plain; charset=us-ascii
+Content-Transfer-Encoding: 7bit
+Message-ID: <13900.41027.169267.293790@kenai.me.umn.edu>
+X-Mailer: VM 6.61 under Emacs 19.34.1
+From: "Curtis L. Olson" 
+To: curt@me.umn.edu
+Subject: nmea stuff
+Date: Fri, 13 Nov 1998 15:10:27 -0600 (CST)
+
+http://pfranc.com/projects/g45contr/assemb.htm
+http://pfranc.com/ - gps connector
+http://pfranc.com/projects/g45contr/beans.htm
+
+http://www.thecapn.com/
+http://www.thecapn.com/nmea.htm
+http://vancouver-webpages.com/peter/
+
+
+-- 
+Curtis Olson                        University of MN, ME Dept.
+curt@me.umn.edu                     
+http://www.menet.umn.edu/~curt      Try Linux!
+
diff --git a/Hints/opengl-optimization b/Hints/opengl-optimization
new file mode 100644
index 000000000..773ff5277
--- /dev/null
+++ b/Hints/opengl-optimization
@@ -0,0 +1,60 @@
+Original Article: http://www.egroups.com/list/opengl-gamedev-l/?start=11533
+Ben Carter writes:
+>
+>  Hmm.. Here's a question - is it worth optimising out redundant state
+> changes? In other words, if I do :
+> 
+>  glEnable(GL_TEXTURE_2D);
+>  
+>  glEnable(GL_TEXTURE_2D);
+>  
+
+   Generally, yes.  There's usually a validation step that's scheduled
+after a call to glEnable().  It updates the internals caches and what
+not based on state that was set prior to the enable call.  Its difficult 
+to estimate what every driver does, but there's still internal updating
+that probably occurs.
+
+   Additionally, its much better to write, for example:
+
+	glLightfv( GL_LIGHT0, ... );
+	glLightfv( GL_LIGHT0, ... );
+	glLightfv( GL_LIGHT0, ... );
+	glEnable( GL_LIGHT0 );
+	glEnable( GL_LIGHTING );
+
+than the opposite.  Its less important to do this in initialization, but 
+if you're dynamically changing things like lighting or texturing, you'll 
+only validate on the glEnable(), as compared to each glLight() call if
+you glEnable() first.
+
+>  Is there going to be a performance hit from the second glEnable call?
+> Would it be worthwhile writing a wrapper around the state system that
+> kept the current state somewhere and only made calls that were
+> necessary, or are the drivers smart enough to do that?
+
+   Some drivers might be smart enough, but I think the underlying
+assumption is that its easier to just reprocess like something's
+changed, than actually try to keep track of which state's changed, and
+localize that validation.
+ 
+   The wrapper idea could be useful; I guess it depends if the apps
+design can't guard against it.  FWIW.
+
+Thanx,
+Dave
+
+  ---------------------------------------------------------------------
+
+   Dave Shreiner                                   
+   Silicon Graphics, Inc.                            (650) 933-4899
+----- 
+FAQ and OpenGL Resources at:
+  http://www.geocities.com/SiliconValley/Hills/9956/OpenGL
+
+-- 
+Author: Dave Shreiner
+  INET: shreiner@sgi.com
+
+Fat City Network Services    -- (619) 538-5051  FAX: (619) 538-5051
+San Diego, California        -- Public Internet access / Mailing Lists
diff --git a/Hints/polygon-offset b/Hints/polygon-offset
new file mode 100644
index 000000000..fd5d71b40
--- /dev/null
+++ b/Hints/polygon-offset
@@ -0,0 +1,269 @@
+From fatcity!root@news.cts.com  Thu Mar 26 17:57:48 1998
+X-VM-v5-Data: ([nil nil nil nil nil nil nil nil nil]
+	["8204" "Thu" "26" "March" "1998" "15:32:55" "-0800" "akin@pobox.com" "akin@pobox.com" nil "162" "Re: poly offset " "^From:" nil nil "3" nil nil nil nil nil]
+	nil)
+Received: from mh2.cts.com (root@mh2.cts.com [205.163.24.68])
+	by meserv.me.umn.edu (8.8.8/8.8.8) with ESMTP id RAA07001
+	for ; Thu, 26 Mar 1998 17:57:43 -0600 (CST)
+Received: from king.cts.com (root@king.cts.com [198.68.168.21]) by mh2.cts.com (8.8.7/8.8.5) with ESMTP id PAA05457; Thu, 26 Mar 1998 15:55:40 -0800 (PST)
+Received: from donews.cts.com (root@donews.cts.com [192.188.72.21])
+	by king.cts.com (8.8.7/8.8.7) with SMTP id PAA21507;
+	Thu, 26 Mar 1998 15:55:38 -0800 (PST)
+Received: from fatcity by donews.cts.com with uucp
+	(Smail3.1.29.1 #5) id m0yIMSJ-0000NEa; Thu, 26 Mar 98 15:53 PST
+Received: by fatcity.com (10-Feb-1998/v1.0f-b64/bab) via UUCP id 00016F4B; Thu, 26 Mar 1998 15:32:55 -0800
+Message-ID: 
+X-Comment: OpenGL Game Developers Mailing List
+X-Sender: akin@pobox.com
+Reply-To: OPENGL-GAMEDEV-L@fatcity.com
+Errors-To: ML-ERRORS@fatcity.com
+Organization: Fat City Network Services, San Diego, California
+X-ListServer: v1.0f, build 64; ListGuru (c) 1996-1998 Bruce A. Bergman
+Precedence: bulk
+Mime-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
+Content-Transfer-Encoding: 7bit
+From: akin@pobox.com
+Sender: root@fatcity.com
+To: Multiple recipients of list OPENGL-GAMEDEV-L 
+Subject: Re: poly offset 
+Date: Thu, 26 Mar 1998 15:32:55 -0800
+
+
+Bryan Gibson-Winge wrote:
+| I was curious to see if anyone would describe a method of using poly offset
+| that didn't eventually conclude with "and mess with the numbers 'till it
+| works".
+
+There is such a method, but since it's not in any of the usual OpenGL
+literature it's not widely discussed.  I'll try to summarize it; maybe
+the result could go into the FAQ.
+
+The purpose of polygon offset is to separate two or more primitives
+by just enough distance in Z that they can be depth-buffered without
+artifacts caused by depth computation roundoff errors, differences in
+sampling algorithms for different types of primitives, etc.
+
+The ``factor'' argument provides separation in the case where the
+primitives are not parallel.  The factor value to use depends on the
+screen sizes of the primitives involved.
+
+	The canonical example is highlighting the edge of a triangle
+	by drawing a line between the two associated triangle vertices.
+	The depth value for each pixel on the line depends only on the
+	depth values at the two vertices of the triangle edge.	However,
+	the depth value for each pixel in the triangle depends on all
+	three of the triangle's vertices.  Since lines and triangles are
+	sampled differently (e.g. diamond-exit rule for lines vs. point
+	sampling for triangles), at a given pixel the depth computed
+	for the edge line usually differs from the depth computed
+	for the underlying triangle.  This can cause ``stitching'' or
+	other unpleasant artifacts in the image, because depth buffering
+	sometimes places the line in front of the triangle and sometimes
+	behind it.
+
+	How much separation is needed to ensure that the line is always
+	in front of the triangle?  If you look at the rasterization
+	arithmetic or play with a few diagrams, you can see that at some
+	pixels the depth value for the triangle is computed at a point
+	almost one pixel away from the ideal edge (which produces the
+	depth values for the line).  Since the triangle can have an almost
+	arbitrarily large depth slope, there is no fixed offset that will
+	guarantee separation between the two primitives in all cases.
+	However, a (variable) separation of 1.0 times the depth slope of
+	the triangle is always sufficient.  (For the purposes of this
+	discussion, the depth slope is max(|dz/dx|,|dz/dy|).  The spec
+	has additional information.)  It's sometimes more than you need,
+	but it's always large enough to work.
+
+	If the line were two pixels wide rather than one, then 1.0
+	times the depth slope wouldn't be enough separation, because
+	some pixels on the line might have depth values derived from an
+	edge point more than one pixel away from the underlying point
+	on the triangle.  2.0 would be sufficient, though.
+
+	So now you understand the factor argument.  It should be
+	nonzero when you're attempting to separate two primitives that
+	aren't parallel, and its value should be roughly the size of
+	the screen-space overlap (measured in pixels) between the two
+	primitives.  For any given triangle, the factor is multiplied
+	by the triangle's depth slope to compute the amount of separation.
+
+The ``units'' or ``bias'' argument provides separation in the case
+where the primitives are roughly parallel.  The value to use
+depends on how many primitives you're trying to stack up.
+
+	Consider the edged-triangle case again.  What happens when the
+	depth slope of the triangle is zero?  Since the depth slope is
+	zero, no matter what the factor argument is, you won't get any
+	separation between the triangle and the edge line.  However,
+	you still want some separation between the two primitives,
+	so that you get a consistent result (i.e., one that doesn't
+	depend on the order in which you draw things or on whether the
+	depth-comparison function tests for equality).
+
+	The bias argument guarantees a little separation even in the case
+	where the depth slope is zero.	Furthermore, it generalizes to
+	the case where the depth slopes of the primitives are nonzero,
+	but the primitives are roughly parallel (for example, when using
+	one polygon as a decal on another).
+
+	The original version of polygon offset allowed you to specify
+	a bias that was simply added to the depth value at each pixel.
+	However, it was quite difficult to choose an appropriate value,
+	because the choice depends not only on the number of bits in the
+	depth buffer (offsets smaller than the depth buffer precision
+	don't do you much good!) but also on the precision of various
+	computations inside the OpenGL driver and the hardware.
+	Perspective projection can also make a difference, since
+	resolution is better at the near clipping plane than it is at
+	the far clipping plane.
+
+	The current version of polygon offset specifies the bias in
+	multiples of a ``minimum resolvable difference,'' which is some
+	value determined by the driver developer.  The minimum resolvable
+	difference is sufficient to separate two parallel primitives,
+	taking into account the perspective projection, size of the
+	depth buffer, hardware precision, etc.
+
+	Since one unit is sufficient to separate two primitives, you
+	can use more than one unit to separate additional primitives.
+	For example, by using bias values of 1, 2, 3, ... you can stack
+	up an arbitrary set of polygons on a base polygon.
+
+	Since some OpenGL implementations add the bias before the
+	perspective divide, a bias of 1.0 unit might be much larger
+	than is needed for primitives close to the near clipping plane.
+	If your app is smart enough to know exactly how the driver
+	behaves, and roughly where in the view volume the primitives
+	will fall, then it can use a bias of less than 1.0 to separate
+	primitives close to the near clipping plane.  Most of the time
+	this is *not* worth the effort, though.
+
+Some practical examples:
+
+	Drawing lines of width 1.0 pixel on the edge of a triangle
+	should use a factor of 1.0 (to guarantee separation when the
+	triangle depth slope is nonzero) and a bias of 1.0 (to guarantee
+	separation when the triangle depth slope is zero).
+
+	Drawing wider lines requires larger factors.  A good rule of
+	thumb might be to use a factor equal to ceil(lineWidth/2 + 0.5).
+
+	Drawing decal polygons needs a zero factor and a nonzero bias,
+	provided that you can guarantee that all of the vertices of
+	the decal polygons are on the same side of the plane of the
+	base polygon, and not on that plane.  (If intersections occur,
+	you might need a nonzero factor, because the depth slopes of
+	the primitives might be different.)  Use a bias of 1.0 for the
+	lowest-level decal (the one closest to the base), 2.0 for the
+	next-highest, and so on.
+
+	Positive factors and biases push primitives in one direction;
+	negative factors and biases push primitives in the other
+	direction.  Sometimes it makes a difference (for example, if you
+	want to use the values in the depth buffer for a subsequent pass).
+
+If you run into trouble, the most likely cause is that the driver
+developer underestimated the value of the minimum resolvable difference.
+(I know of no way to predict this value; I think you just have to
+measure it.  The basic idea is to binary-search across the range of depth
+values, drawing two parallel polygons at each stage and determining if
+depth-buffering artifacts occur.  Do this once at the near plane, and
+once at the far plane, and take the largest result.  Repeat for extreme
+depthrange values.)  Tweaking the bias argument is probably the only
+way to resolve this. :-)
+
+Finally, as Steve Baker and I have discussed in the past, the
+reference_plane extension is often a cleaner solution than polygon offset,
+if your OpenGL implementation supports it.
+
+Allen
+-- 
+Author: 
+  INET: akin@pobox.com
+
+Fat City Network Services    -- (619) 538-5051  FAX: (619) 538-5051
+San Diego, California        -- Public Internet access / Mailing Lists
+--------------------------------------------------------------------
+To REMOVE yourself from this mailing list, send an E-Mail message
+to: ListGuru@fatcity.com (note EXACT spelling of 'ListGuru') and in
+the message BODY, include a line containing: UNSUB OPENGL-GAMEDEV-L
+(or the name of mailing list you want to be removed from).  You may
+also send the HELP command for other information (like subscribing).
+
+From fatcity!root@news.cts.com  Fri Jan 16 04:45:15 1998
+X-VM-v5-Data: ([nil nil nil nil nil nil nil nil nil]
+	["1385" "Fri" "16" "January" "1998" "02:06:11" "-0800" "Mark Kilgard" "mjk@fangio.engr.sgi.com" nil "43" "Re: glPolygonOffset" "^From:" nil nil "1" nil nil nil nil nil]
+	nil)
+Received: from mh2.cts.com (root@mh2.cts.com [205.163.24.68])
+	by meserv.me.umn.edu (8.8.8/8.8.6) with ESMTP id EAA19075
+	for ; Fri, 16 Jan 1998 04:45:14 -0600 (CST)
+Received: from king.cts.com (root@king.cts.com [198.68.168.21]) by mh2.cts.com (8.8.7/8.8.5) with ESMTP id CAA19264; Fri, 16 Jan 1998 02:39:16 -0800 (PST)
+Received: from donews.cts.com (root@donews.cts.com [192.188.72.21])
+	by king.cts.com (8.8.7/8.8.7) with SMTP id CAA07365;
+	Fri, 16 Jan 1998 02:39:07 -0800 (PST)
+Received: from fatcity by donews.cts.com with uucp
+	(Smail3.1.29.1 #5) id m0xt8sd-00008Sa; Fri, 16 Jan 98 02:20 PST
+Received: by fatcity.com (02-Jan-98/v1.0f-b63/bab) via UUCP id 0C92BDFF; Fri, 16 Jan 1998 02:06:11 -0800
+Message-ID: 
+X-Comment: OpenGL Game Developers Mailing List
+X-Sender: mjk@fangio.engr.sgi.com (Mark Kilgard)
+Reply-To: OPENGL-GAMEDEV-L@fatcity.com
+Errors-To: ML-ERRORS@fatcity.com
+Organization: Fat City Network Services, San Diego, California
+X-ListServer: v1.0f, build 63; ListGuru (c) 1996-1998 Bruce A. Bergman
+Precedence: bulk
+Mime-Version: 1.0
+Content-Type: text/plain; charset=US-ASCII
+Content-Transfer-Encoding: 7bit
+From: mjk@fangio.engr.sgi.com (Mark Kilgard)
+Sender: root@fatcity.com
+To: Multiple recipients of list OPENGL-GAMEDEV-L 
+Subject: Re: glPolygonOffset
+Date: Fri, 16 Jan 1998 02:06:11 -0800
+
+opengl-gamedev,
+
+> At one time I came across web site with example for glPolygonOffset, but I 
+> can not find it again. Does anybody know web site. 
+
+Polygon offset is used to "lift" the projected planar shadows off of
+the floor to avoid Z fighting in my dinoshade.c example.  See:
+
+  http://reality.sgi.com/mjk/tips/TexShadowReflectLight.html
+
+Other cool OpenGL rendering techniques are shown at:
+
+  http://reality.sgi.com/mjk/tips/
+
+There are also several polygon offset examples in the GLUT 3.6 source
+code distribution.  See:
+
+  http://reality.sgi.com/mjk/glut3/glut3.html
+
+In particular, look at:
+
+  progs/examples/origami.c
+  progs/examples/surfgrid.c
+  progs/examples/dinoshade.c
+  progs/examples/halomagic.c
+  progs/redbook/polyoff.c
+  progs/advanced/haloed.c
+
+I hope this helps.
+
+- Mark
+-- 
+Author: Mark Kilgard
+  INET: mjk@fangio.engr.sgi.com
+
+Fat City Network Services    -- (619) 538-5030  FAX: (619) 538-5051
+San Diego, California        -- Public Internet Access
+--------------------------------------------------------------------
+To REMOVE yourself from this mailing list, send an E-Mail message
+to: ListGuru@fatcity.com (note EXACT spelling of 'ListGuru') and in
+the message BODY, include a line containing: UNSUB OPENGL-GAMEDEV-L
+(or the name of mailing list you want to be removed from).  You may
+also send the HELP command for other information (like subscribing).
+
diff --git a/Hints/portable-sound b/Hints/portable-sound
new file mode 100644
index 000000000..7bb6999ce
--- /dev/null
+++ b/Hints/portable-sound
@@ -0,0 +1,331 @@
+From fatcity!root@news.cts.com  Mon Jan  5 14:50:59 1998
+X-VM-v5-Data: ([nil nil nil nil t nil nil nil nil]
+	["1623" "Mon" "5" "January" "1998" "12:03:38" "-0800" "Chris Schoeneman" "crs@millpond.engr.sgi.com" "" "41" "Re: [Q] OpenGL + Arbitrary display mode in Win32" "^From:" nil nil "1" nil nil nil nil nil]
+	nil)
+Received: from mh2.cts.com (root@mh2.cts.com [205.163.24.68])
+	by meserv.me.umn.edu (8.8.8/8.8.6) with ESMTP id OAA05604
+	for ; Mon, 5 Jan 1998 14:50:58 -0600 (CST)
+Received: from king.cts.com (root@king.cts.com [198.68.168.21]) by mh2.cts.com (8.8.7/8.8.5) with ESMTP id MAA20781; Mon, 5 Jan 1998 12:43:38 -0800 (PST)
+Received: from donews.cts.com (root@donews.cts.com [192.188.72.21])
+	by king.cts.com (8.8.7/8.8.7) with SMTP id MAA01273;
+	Mon, 5 Jan 1998 12:41:39 -0800 (PST)
+Received: from fatcity by donews.cts.com with uucp
+	(Smail3.1.29.1 #5) id m0xpJ0S-0000Hga; Mon, 5 Jan 98 12:20 PST
+Received: by fatcity.com (02-Jan-98/v1.0f-b63/bab) via UUCP id 0C927564; Mon, 05 Jan 1998 12:03:38 -0800
+Message-ID: 
+X-Comment: OpenGL Game Developers Mailing List
+X-Sender: crs@millpond.engr.sgi.com (Chris Schoeneman)
+Reply-To: OPENGL-GAMEDEV-L@fatcity.com
+Errors-To: ML-ERRORS@fatcity.com
+Organization: Fat City Network Services, San Diego, California
+X-ListServer: v1.0f, build 63; ListGuru (c) 1996-1998 Bruce A. Bergman
+Precedence: bulk
+Mime-Version: 1.0
+Content-Type: text/plain; charset=US-ASCII
+Content-Transfer-Encoding: 8bit
+From: crs@millpond.engr.sgi.com (Chris Schoeneman)
+Sender: root@fatcity.com
+To: Multiple recipients of list OPENGL-GAMEDEV-L 
+Subject: Re: [Q] OpenGL + Arbitrary display mode in Win32
+Date: Mon, 05 Jan 1998 12:03:38 -0800
+
+Doty, Lee wrote:
+> 
+> Any sound gurus out there?  I agree that if we could get 3d sound in
+> there, life would get exponentially happier.
+
+I'm willing to donate the sound code from bzflag.  It's supports:
+
+  arbitrary number of simultaneous sounds (limited by CPU speed)
+  attenuation with distance
+  propagation delay
+  doppler effects
+  stereo panning
+
+It runs in a separate thread and has a very simple interface.  I have
+it running on Windows 95/NT and Irix, and Daryll Strauss ported it to
+Linux.  The Windows version would work better if DirectSound didn't
+suck so bad, but it works reasonably well now.
+
+A drawback is that it can suck up a lot of CPU time since it has to
+do its own filtering and mixing.  It also needs support for a better
+HRTF, reverb with distance, high-frequency rolloff with distance, and
+a way to set the volume on individual sounds.  That last one is trivial
+but the others are more involved.
+
+Mark, you interested?  I've also got fullscreen and resolution changing
+code for Irix.
+
+Cheers,
+-chris
+-- 
+Author: Chris Schoeneman
+  INET: crs@millpond.engr.sgi.com
+
+Fat City Network Services    -- (619) 538-5030  FAX: (619) 538-5051
+San Diego, California        -- Public Internet Access
+--------------------------------------------------------------------
+To REMOVE yourself from this mailing list, send an E-Mail message
+to: ListGuru@fatcity.com (note EXACT spelling of 'ListGuru') and in
+the message BODY, include a line containing: UNSUB OPENGL-GAMEDEV-L
+(or the name of mailing list you want to be removed from).  You may
+also send the HELP command for other information (like subscribing).
+
+From crs@millpond.engr.sgi.com  Mon Jan  5 15:36:10 1998
+X-VM-v5-Data: ([nil nil nil nil t nil nil nil nil]
+	["1034" "Mon" "5" "January" "1998" "13:35:59" "-0800" "Chris Schoeneman" "crs@millpond.engr.sgi.com" "<199801052135.NAA21198@millpond.engr.sgi.com>" "23" "Re: bzflag sound playing code" "^From:" nil nil "1" nil nil nil nil nil]
+	nil)
+Received: from sgi.sgi.com (SGI.COM [192.48.153.1])
+	by meserv.me.umn.edu (8.8.8/8.8.6) with SMTP id PAA07002
+	for ; Mon, 5 Jan 1998 15:36:07 -0600 (CST)
+Received: from cthulhu.engr.sgi.com (cthulhu.engr.sgi.com [192.26.80.2]) by sgi.sgi.com (950413.SGI.8.6.12/970507) via ESMTP id NAA08189
+	for <@sgi.engr.sgi.com:curt@me.umn.edu>; Mon, 5 Jan 1998 13:36:04 -0800
+	env-from (crs@millpond.engr.sgi.com)
+Received: from millpond.engr.sgi.com (millpond.engr.sgi.com [150.166.55.67]) by cthulhu.engr.sgi.com (950413.SGI.8.6.12/960327.SGI.AUTOCF) via ESMTP id NAA07557 for <@cthulhu.engr.sgi.com:curt@me.umn.edu>; Mon, 5 Jan 1998 13:36:00 -0800
+Received: (from crs@localhost) by millpond.engr.sgi.com (950413.SGI.8.6.12/960327.SGI.AUTOCF) id NAA21198 for curt@me.umn.edu; Mon, 5 Jan 1998 13:35:59 -0800
+Message-Id: <199801052135.NAA21198@millpond.engr.sgi.com>
+In-Reply-To: <199801052103.PAA30512@kenai.me.umn.edu> from "Curtis L. Olson" at Jan 5, 98 03:03:52 pm
+X-Mailer: ELM [version 2.4 PL23]
+MIME-Version: 1.0
+Content-Type: text/plain; charset=US-ASCII
+Content-Transfer-Encoding: 8bit
+From: crs@millpond.engr.sgi.com (Chris Schoeneman)
+To: curt@me.umn.edu (Curtis L. Olson)
+Subject: Re: bzflag sound playing code
+Date: Mon, 5 Jan 1998 13:35:59 -0800 (PST)
+
+Curtis L. Olson wrote:
+> 
+> Is the licensing of the bzflag sound code such that I could use it to
+> build in sounds support for our project?  We would want to have a
+> continuously looping engine sound (plus wind sound, and maybe rain
+> hitting the windshield sound.)  Then we'd need to intersperse the
+> other sounds such as flaps, stall horn, landing gear, thunder, crash,
+> etc.  It sounds like it might be exactly the sort of thing we need.
+
+Hmm, it's not a perfect match.  Most of your sounds are purely local,
+so you don't need the stereo panning, propagation delay, and doppler
+effect.  However, that's no reason not to try it!
+
+Ripping my sound code out from bzflag shouldn't be too much work
+but I'm really busy at the moment.  Could you wait about a week?
+
+BTW, as far as licensing goes I'd just want the copyright notice to
+stay on the source files (we'll have to tweek the legal notice) and
+a mention in the credits, if you have a credits list.  A right to
+use enhancements to the code would be cool, too.
+
+Cheers,
+-chris
+
+From crs@millpond.engr.sgi.com  Mon Jan  5 16:22:27 1998
+X-VM-v5-Data: ([nil nil nil nil t nil nil nil nil]
+	["1125" "Mon" "5" "January" "1998" "14:22:22" "-0800" "Chris Schoeneman" "crs@millpond.engr.sgi.com" "<199801052222.OAA21481@millpond.engr.sgi.com>" "27" "Re: bzflag sound playing code" "^From:" nil nil "1" nil nil nil nil nil]
+	nil)
+Received: from sgi.sgi.com (SGI.COM [192.48.153.1])
+	by meserv.me.umn.edu (8.8.8/8.8.6) with SMTP id QAA08463
+	for ; Mon, 5 Jan 1998 16:22:26 -0600 (CST)
+Received: from cthulhu.engr.sgi.com (cthulhu.engr.sgi.com [192.26.80.2]) by sgi.sgi.com (950413.SGI.8.6.12/970507) via ESMTP id OAA22876
+	for <@sgi.engr.sgi.com:curt@me.umn.edu>; Mon, 5 Jan 1998 14:22:25 -0800
+	env-from (crs@millpond.engr.sgi.com)
+Received: from millpond.engr.sgi.com (millpond.engr.sgi.com [150.166.55.67]) by cthulhu.engr.sgi.com (950413.SGI.8.6.12/960327.SGI.AUTOCF) via ESMTP id OAA25764 for <@cthulhu.engr.sgi.com:curt@me.umn.edu>; Mon, 5 Jan 1998 14:22:22 -0800
+Received: (from crs@localhost) by millpond.engr.sgi.com (950413.SGI.8.6.12/960327.SGI.AUTOCF) id OAA21481 for curt@me.umn.edu; Mon, 5 Jan 1998 14:22:22 -0800
+Message-Id: <199801052222.OAA21481@millpond.engr.sgi.com>
+In-Reply-To: <199801052204.QAA31163@kenai.me.umn.edu> from "Curtis L. Olson" at Jan 5, 98 04:04:44 pm
+X-Mailer: ELM [version 2.4 PL23]
+MIME-Version: 1.0
+Content-Type: text/plain; charset=US-ASCII
+Content-Transfer-Encoding: 8bit
+From: crs@millpond.engr.sgi.com (Chris Schoeneman)
+To: curt@me.umn.edu (Curtis L. Olson)
+Subject: Re: bzflag sound playing code
+Date: Mon, 5 Jan 1998 14:22:22 -0800 (PST)
+
+Curtis L. Olson wrote:
+> 
+> Does your code support continuously looping sounds?  Or would this be
+> fairly straight forward to implement?  I've done virtually nothing
+> with sound in my life other than listen to it. :-)
+
+It does/should.  bzflag doesn't use this code though so it may suffer
+from bit rot.  I used it to test the Doppler effect.
+
+There may also be some issues around having a very large world.  Imagine
+the sound as a spherical shell.  Outside the shell, sound hasn't reached
+you yet;  inside the shell, the sound has passed by.  In bzflag I need
+to keep sounds around for as long as any part of the shell is inside the
+world because it's possible to move from one place to another instantly.
+Seems to me you have this same situation if you want external views.
+
+The sound engine is clever enough not to process sounds unless you're in
+the shell, so a large world probably won't cause any problems.  I'm just
+not sure at the moment.
+
+
+> This all sounds completely reasonable.  All our stuff is released
+> under the basic "GPL".
+
+Should be fine.  I've no problem releasing my code under the GPL.
+Cheers,
+-chris
+
+From crs@millpond.engr.sgi.com  Mon Jan  5 17:33:03 1998
+X-VM-v5-Data: ([nil nil nil nil t nil nil nil nil]
+	["660" "Mon" "5" "January" "1998" "15:32:53" "-0800" "Chris Schoeneman" "crs@millpond.engr.sgi.com" "<199801052332.PAA21873@millpond.engr.sgi.com>" "18" "Re: bzflag sound playing code" "^From:" nil nil "1" nil nil nil nil nil]
+	nil)
+X-VM-Message-Order:
+	(1 2 3 4 6 5 7 8 9 10 11 12 13 14 15
+	 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
+	 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
+	 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
+	 61 62 63 64)
+X-VM-Summary-Format: "%n %*%a %-17.17F %-3.3m %2d %4l/%-5c %I\"%s\"\n"
+X-VM-Labels: ("r")
+X-VM-VHeader: ("Resent-" "From:" "Sender:" "To:" "Apparently-To:" "Cc:" "Subject:" "Date:") nil
+X-VM-Bookmark: 57
+Received: from sgi.sgi.com (SGI.COM [192.48.153.1])
+	by meserv.me.umn.edu (8.8.8/8.8.6) with SMTP id RAA10765
+	for ; Mon, 5 Jan 1998 17:33:01 -0600 (CST)
+Received: from cthulhu.engr.sgi.com (cthulhu.engr.sgi.com [192.26.80.2]) by sgi.sgi.com (950413.SGI.8.6.12/970507) via ESMTP id PAA14176
+	for <@sgi.engr.sgi.com:curt@me.umn.edu>; Mon, 5 Jan 1998 15:33:00 -0800
+	env-from (crs@millpond.engr.sgi.com)
+Received: from millpond.engr.sgi.com (millpond.engr.sgi.com [150.166.55.67]) by cthulhu.engr.sgi.com (950413.SGI.8.6.12/960327.SGI.AUTOCF) via ESMTP id PAA19353 for <@cthulhu.engr.sgi.com:curt@me.umn.edu>; Mon, 5 Jan 1998 15:32:53 -0800
+Received: (from crs@localhost) by millpond.engr.sgi.com (950413.SGI.8.6.12/960327.SGI.AUTOCF) id PAA21873 for curt@me.umn.edu; Mon, 5 Jan 1998 15:32:53 -0800
+Message-Id: <199801052332.PAA21873@millpond.engr.sgi.com>
+In-Reply-To: <199801052322.RAA32525@kenai.me.umn.edu> from "Curtis L. Olson" at Jan 5, 98 05:22:08 pm
+X-Mailer: ELM [version 2.4 PL23]
+MIME-Version: 1.0
+Content-Type: text/plain; charset=US-ASCII
+Content-Transfer-Encoding: 8bit
+From: crs@millpond.engr.sgi.com (Chris Schoeneman)
+To: curt@me.umn.edu (Curtis L. Olson)
+Subject: Re: bzflag sound playing code
+Date: Mon, 5 Jan 1998 15:32:53 -0800 (PST)
+
+Curtis L. Olson wrote:
+> 
+> Our code is all GPL'd, so if you can keep within those license
+> restrictions feel free to borrow code.  (Or does bzflag take place a
+> long time ago in a galaxy far, far away ... I haven't tried running it
+> yet myself.) :-)
+
+Actually, it's already got accurate sun, moon, and stars.  The star
+magnitudes are relatively okay (there's not enough dynamic range on
+a monitor anyway).  You can specify any position on the earth, and
+the positions are accurately based on the time and date.  Great minds
+think alike, eh?
+
+I don't have the planets as I thought I'd gone overboard myself.  Guess
+I hadn't gone far enough!
+
+Cheers,
+-chris
+
+From curt@me.umn.edu  Thu Apr 30 09:02:28 1998
+X-VM-v5-Data: ([nil nil nil nil nil nil nil nil nil]
+	["3542" "" "30" "April" "1998" "09:02:26" "-0500" "Curtis L. Olson" "curt@me.umn.edu" nil "88" "[comp.os.linux.announce] Enlightened Sound Daemon version 0.2" "^From:" nil nil "4" nil nil nil nil nil]
+	nil)
+Received: from kenai.me.umn.edu (curt@kenai.me.umn.edu [134.84.18.22])
+	by meserv.me.umn.edu (8.8.8/8.8.8) with ESMTP id JAA10406
+	for ; Thu, 30 Apr 1998 09:02:28 -0500 (CDT)
+Received: (from curt@localhost)
+	by kenai.me.umn.edu (8.8.5/8.8.5) id JAA19157;
+	Thu, 30 Apr 1998 09:02:27 -0500
+Message-ID: 
+Lines: 88
+X-Mailer: Gnus v5.3/Emacs 19.34
+From: curt@me.umn.edu (Curtis L. Olson)
+Sender: curt@me.umn.edu
+To: curt@me.umn.edu
+Subject: [comp.os.linux.announce] Enlightened Sound Daemon version 0.2
+Date: 30 Apr 1998 09:02:26 -0500
+
+
+-- 
+Curtis Olson                        University of MN, ME Dept.
+curt@me.umn.edu                     
+http://www.menet.umn.edu/~curt      Try Linux!
+------- Start of forwarded message -------
+From: "Eric B. Mitchell" 
+Newsgroups: comp.os.linux.announce
+Subject: Enlightened Sound Daemon version 0.2
+Followup-To: comp.os.linux.misc
+Date: Thu, 30 Apr 1998 08:25:43 GMT
+Organization: Altair Aerospace Corporation
+Message-ID: 
+Reply-To: emitchell@altaira.com
+
+-----BEGIN PGP SIGNED MESSAGE-----
+
+
+I am pleased to announce the preliminary release of the 
+Enlightened Sound Daemon (EsounD version 0.2) for Linux.  
+More details at .
+This program is designed to mix together several digitized 
+audio streams for playback by a single device.  The current 
+list of features includes the following functionality:
+
+ o  A simple authentication scheme is implemented.  The first
+    process to present a 16 byte key to the daemon determines
+    the ownership of the daemon.  The owner of the daemon may
+    allow or disallow connections from other keys.  If a HUP
+    signal is received, ownership of the daemon is reset.
+
+ o  Playback of multiple digital samples simultaneously is 
+    supported.  The daemon uses a raw sample format which 
+    is easily generated by the SOX utility from many other 
+    data formats.
+
+ o  The mixed audio data may be output from the daemon as a
+    "monitor" stream.
+
+ o  Recording from the current input of the sound device is
+    supported.  Full duplex operation (simultaneous recording
+    and playback) is supported.
+
+ o  Client connections may cache samples for playback by an 
+    assigned identification number.  For example, a window
+    manager may cache samples in the server for playback on
+    various events, and play them back without replaying the
+    full audio stream for the sample.  Samples may be looped
+    until the server receives a "stop sample" message. 
+
+Currently, the only platform supported is Linux.  It is intended
+that this program support multiple platforms.  I have limited
+access to other Unix platforms, so any help in porting the
+Enlightened Sound Daemon to other platforms is appreciated.  
+The amp program, by Tomislav Uzelac may be a good reference 
+for porting the audio interface to other platforms.
+
+This is to be considered an alpha release, as functionality
+remains to be implemented.
+
+- -- ebm
++=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=+
+|  __                         a.k.a. Eric B. Mitchell |
+|  |_) .  _  _|      _|  _     ericmit@ix.netcom.com  |
+|  | \ ( (_ (_| (_| (_| (/_   www.netcom.com/~ericmit |
+| How's My Programming?   Call:  1 - 800 - DEV - NULL |
++=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=+
+
+
+
+- -- 
+This article has been digitally signed by the moderator, using PGP.
+http://www.iki.fi/mjr/cola-public-key.asc has PGP key for validating signature.
+Send submissions for comp.os.linux.announce to: linux-announce@news.ornl.gov
+PLEASE remember a short description of the software and the LOCATION.
+This group is archived at http://www.iki.fi/mjr/linux/cola.html
+
+-----BEGIN PGP SIGNATURE-----
+Version: 2.6.3ia
+Charset: latin1
+
+iQCVAgUBNUg1h1rUI/eHXJZ5AQHjSwP/aGb9U1fIgnUA6qMaD6x/JeTM2IJVRLDa
+YxXoZ9EbENIKCbV9lV0PcGogW0+eA2zAZq3tQFu9P9B+eFX6jcVD2FhDekvFI5ZS
+j44u74PbNU45LIuw2xxiaBAgfZcnZ9XZ3uy6Z9Yu3Xd+xkZ5k9nxafP1+tkPztmA
+y5okM7m4rEs=
+=Y1B3
+-----END PGP SIGNATURE-----
+------- End of forwarded message -------
+
diff --git a/Hints/scene-graph b/Hints/scene-graph
new file mode 100644
index 000000000..522c7681d
--- /dev/null
+++ b/Hints/scene-graph
@@ -0,0 +1,85 @@
+From owner-fgfs-devel@flightgear.org  Fri Mar 12 12:57:31 1999
+X-VM-v5-Data: ([nil nil nil nil t nil nil nil nil]
+	["1824" "Fri" "12" "March" "1999" "12:55:14" "-0600" "Stephen J Baker" "sjbaker@hti.com" "" "53" "[FGFS-Devel] Scene graph API." "^From:" nil nil "3" nil nil nil nil nil]
+	nil)
+Received: from mailhub.woodsoup.org (IDENT:root@anduin.physics.iastate.edu [129.186.82.1])
+	by meserv.me.umn.edu (8.9.1a/8.9.1) with ESMTP id MAA10391
+	for ; Fri, 12 Mar 1999 12:57:30 -0600 (CST)
+Received: from majordom by mailhub.woodsoup.org with local (Exim 1.92 #1)
+	for fgfs-devel-outgoing@flightgear.org
+	id 10LX6P-0003CG-00; Fri, 12 Mar 1999 12:56:09 -0600
+Received: from sunmgr.hti.com ([130.210.206.69] helo=issun6.hti.com)
+	by mailhub.woodsoup.org with esmtp (Exim 1.92 #1)
+	for fgfs-devel@flightgear.org
+	id 10LX6O-0003C8-00; Fri, 12 Mar 1999 12:56:08 -0600
+Received: from issun5.hti.com ([130.210.202.3]) by issun6.hti.com
+          (Netscape Messaging Server 3.6)  with ESMTP id AAAEEB
+          for ; Fri, 12 Mar 1999 12:55:26 -0600
+Received: from samantha.bgm.link.com ([130.210.65.19]) by issun5.hti.com
+          (Netscape Messaging Server 3.6)  with SMTP id AAA6D20
+          for ; Fri, 12 Mar 1999 12:55:25 -0600
+X-Sender: steve@samantha.bgm.link.com
+Message-ID: 
+MIME-Version: 1.0
+Content-Type: TEXT/PLAIN; charset=US-ASCII
+Precedence: bulk
+Reply-To: fgfs-devel@flightgear.org
+From: "Stephen J Baker" 
+Sender: owner-fgfs-devel@flightgear.org
+To: Flight Gear Mailing List 
+Subject: [FGFS-Devel] Scene graph API.
+Date: Fri, 12 Mar 1999 12:55:14 -0600 (CST)
+
+
+I have just posted an early (pre-alpha - whatever) version of my
+new Scene Graph API and simple matrix/vector math library onto my
+web site:
+
+   http://www.woodsoup.org/~sbaker/ssg
+
+...and...
+
+   http://www.woodsoup.org/~sbaker/sg
+
+...these are the libraries that I'm using in my Tux-the-Penguin
+game - so they *work* pretty well - but may not be as complete
+or well-structured as they should be. There are also no example
+programs (apart from the game itself) and the only file loader
+is for an obscure ASCII format that nobody is likely to want
+as a standard. I hope to fix that somewhat over then next few
+weeks - but I'm on vacation next week.
+
+I think these libraries could be applicable to FGFS in several
+areas:
+
+1) 3D instrument panels.
+
+2) BUildings and other hand-created features like airfields,
+   detailed city areas and so forth.
+
+3) Other aircraft.
+
+There are some issues about how this would all integrate into
+Curts terrain rendering scheme - but I think it's do-able.
+
+Anyway, it would be nice if people would read the manuals
+and email me some comments, criticisms, suggestions, etc.
+Like I said though - these are really early cuts so don't
+go out and write 100,000 lines of code that depend on
+them - OK?
+
+Since I'm going to be out in the wilds of Arkansas for the
+next week (Do they have email out there? I *think* they
+have phones), don't expect a quick answer to any questions.
+
+Steve Baker                (817)619-2657 (Vox/Vox-Mail)
+Raytheon Systems Inc.      (817)619-2466 (Fax)
+Work: sjbaker@hti.com      http://www.hti.com
+Home: sjbaker1@airmail.net http://web2.airmail.net/sjbaker1
+
+
+--
+Please visit the FGFS web page:  http://www.flightgear.org
+For help on using this list (especially unsubscribing), send a message to
+"fgfs-devel-request@flightgear.org" with a single line of text: "help".
+
diff --git a/Hints/stl-gcc-redhat b/Hints/stl-gcc-redhat
new file mode 100644
index 000000000..fba450c70
--- /dev/null
+++ b/Hints/stl-gcc-redhat
@@ -0,0 +1,153 @@
+From: Bernie Bright 
+Sender: owner-fgfs-devel@flightgear.org
+To: fgfs-devel@flightgear.org
+Subject: Re: [FGFS-Devel] Another problem compiling Flightgear 0.55
+Date: Mon, 02 Nov 1998 14:31:05 +1100
+
+Arno Dabekaussen wrote:
+> 
+> Hi Curt,
+> 
+> Thanks for answerring my former post, but unfortunately the compilation
+> blew up again.
+> Here is the relevant information.
+> 
+> With kind regards,
+> 
+> Arno Dabekaussen
+> 
+> Making all in Time
+> make[2]: Entering directory
+> `/home/arno/applications/FlightGear-0.55/Simulator/Time'
+> c++ -DHAVE_CONFIG_H -I. -I../../././Simulator/Time -I../../Include
+> -DHAVE_DAYLIGHT -DHAVE_TIMEZONE -I../.. -I../../Lib -I../../Simulator
+> -I/usr/local/include -I/usr/X11R6/include -g -O2 -c event.cxx
+> In file included from /usr/include/g++/std/bastring.h:571,
+>                  from /usr/include/g++/std/string.h:6,
+>                  from /usr/include/g++/string:5,
+>                  from event.hxx:42,
+>                  from event.cxx:48:
+> /usr/include/g++/std/sinst.h:60: ambiguous template instantiation for
+> `operator !=(const char *, const
+> basic_string > &)' requested
+
+[snip]
+
+This is a known problem with the string class in g++ 2.7.x and is not
+limited to FG. I've attached an unofficial patch to that fixes the
+problem.  Note, you'll need root access to apply the patch.
+
+Cheers
+Bernie.>From khan@xraylith.wisc.edu Wed Mar 05 02:21:24 1997
+Path: news.mel.aone.net.au!news.mel.connect.com.au!munnari.OZ.AU!news.ecn.uoknor.edu!feed1.news.erols.com!newsfeeds.sol.net!uwm.edu!newsspool.doit.wisc.edu!news.doit.wisc.edu!khan
+From: khan@xraylith.wisc.edu (Mumit Khan)
+Newsgroups: gnu.g++.help
+Subject: Re: Compiling with strings & vectors
+Date: 4 Mar 1997 16:21:24 GMT
+Organization: Center for X-ray Lithography, UW-Madison
+Lines: 100
+Message-ID: <5fhi64$lsa@news.doit.wisc.edu>
+References: <5ffoh9$v2a$1@quartz.inquo.net>
+NNTP-Posting-Host: modi.xraylith.wisc.edu
+
+In article <5ffoh9$v2a$1@quartz.inquo.net>,
+Travis Jensen  wrote:
+>I am trying to use a 'string' in a program compiled with 2.7.2.2
+>and libg++ 2.7.2.  If I just 
+>
+>  #include  
+>
+>and use it, I have no problems.  However, if I 
+>  
+>  #include 
+   ^^^^^^^^^^^^^^^^^^^
+
+should be 
+   #include 
+
+>  #include 
+>
+>Is there something special I have to do to use strings and vectors
+>together?
+>
+
+I've posted an unofficial patch to libstdc++ headers (no re-compilation
+necessary, so it's easy!) something like 19 times so far. Here is a copy
+of an old posting:
+
+=====================================================================
+
+If you're using GNU STL that comes with libg++-2.7.1, must apply the 
+following patch (no recompilation necessary):
+    
+    % cd /usr/local/lib/g++-include/std
+    % patch -s -p0 < /tmp/libg++-2.7.1-patch
+
+==== LIBG++ patch
+
+*** bastring.h.org	Sun Dec  3 10:51:44 1995
+--- bastring.h	Sun Dec  3 10:51:43 1995
+***************
+*** 523,529 ****
+  }
+  
+  // Kludge this until g++ supports the new template overloading semantics.
+! #if !defined(FUNCTION_H)
+  template 
+  inline bool
+  operator!= (const basic_string & lhs,
+--- 523,529 ----
+  }
+  
+  // Kludge this until g++ supports the new template overloading semantics.
+! #if !defined(FUNCTION_H) && !defined(OS_STL_FUNCTION_H)
+  template 
+  inline bool
+  operator!= (const basic_string & lhs,
+*** cinst.h.org	Sun Dec  3 10:51:48 1995
+--- cinst.h	Sun Dec  3 10:51:47 1995
+***************
+*** 84,92 ****
+--- 84,94 ----
+  __DO2(operator==,__B,__CCR,__CCR)
+  __DO2(operator==,__B,__CCR,__F)
+  __DO2(operator==,__B,__F,__CCR)
++ #if !defined(FUNCTION_H) && !defined(OS_STL_FUNCTION_H)
+  __DO2(operator!=,__B,__CCR,__CCR)
+  __DO2(operator!=,__B,__CCR,__F)
+  __DO2(operator!=,__B,__F,__CCR)
++ #endif
+  __DO1(abs,__F,__CCR)
+  __DO1(arg,__F,__CCR)
+  __DO2(polar,__C,__F,__F)
+*** sinst.h.org	Thu Feb 29 11:20:52 1996
+--- sinst.h	Thu Feb 29 11:21:22 1996
+***************
+*** 57,67 ****
+--- 57,71 ----
+  //  __DOPR (op, bool, wchar_t, __W)
+  
+  __DOB (==)
++ #if !defined(FUNCTION_H) && !defined(OS_STL_FUNCTION_H)
+  __DOB (!=)
++ #endif
+  __DOB (<)
++ #if !defined(FUNCTION_H) && !defined(OS_STL_FUNCTION_H)
+  __DOB (>)
+  __DOB (<=)
+  __DOB (>=)
++ #endif
+  
+  #undef __S
+  //#undef __W
+
+
+==== END LIBG++ patch
+
+Enjoy
+Mumit -- khan@xraylith.wisc.edu
+http://www.xraylith.wisc.edu/~khan/
+
+Cc: gnu.g++.help,
+    Travis Jensen  
+
diff --git a/Hints/strips-vs-fans b/Hints/strips-vs-fans
new file mode 100644
index 000000000..700de8058
--- /dev/null
+++ b/Hints/strips-vs-fans
@@ -0,0 +1,251 @@
+From fatcity!root@news.cts.com  Sun Apr 12 22:32:55 1998
+X-VM-v5-Data: ([nil nil nil nil nil nil nil nil nil]
+	["2122" "Sun" "12" "April" "1998" "19:50:31" "-0800" "Steve Baker" "sbaker@link.com" nil "47" "Re: Strips vs Fans ..." "^From:" nil nil "4" nil nil nil nil nil]
+	nil)
+Received: from mh2.cts.com (root@mh2.cts.com [205.163.24.68])
+	by meserv.me.umn.edu (8.8.8/8.8.8) with ESMTP id WAA20847
+	for ; Sun, 12 Apr 1998 22:32:52 -0500 (CDT)
+Received: from king.cts.com (root@king.cts.com [198.68.168.21]) by mh2.cts.com (8.8.7/8.8.5) with ESMTP id UAA22193; Sun, 12 Apr 1998 20:31:45 -0700 (PDT)
+Received: from donews.cts.com (root@donews.cts.com [192.188.72.21])
+	by king.cts.com (8.8.7/8.8.7) with SMTP id UAA00319;
+	Sun, 12 Apr 1998 20:31:43 -0700 (PDT)
+Received: from fatcity by donews.cts.com with uucp
+	(Smail3.1.29.1 #5) id m0yOZX9-00000Wa; Sun, 12 Apr 98 20:03 PDT
+Received: by fatcity.com (10-Feb-1998/v1.0f-b64/bab) via UUCP id 0001C21E; Sun, 12 Apr 1998 19:50:31 -0800
+Message-ID: 
+X-Comment: OpenGL Game Developers Mailing List
+X-Sender: Steve Baker 
+Reply-To: OPENGL-GAMEDEV-L@fatcity.com
+Errors-To: ML-ERRORS@fatcity.com
+Organization: Fat City Network Services, San Diego, California
+X-ListServer: v1.0f, build 64; ListGuru (c) 1996-1998 Bruce A. Bergman
+Precedence: bulk
+Mime-Version: 1.0
+Content-Type: TEXT/PLAIN; charset=US-ASCII
+Content-Transfer-Encoding: 7bit
+From: Steve Baker 
+Sender: root@fatcity.com
+To: Multiple recipients of list OPENGL-GAMEDEV-L 
+Subject: Re: Strips vs Fans ...
+Date: Sun, 12 Apr 1998 19:50:31 -0800
+
+On Sat, 11 Apr 1998, Edward M Povazan wrote:
+
+> I've been following threads here about auto strip generation, and am
+> starting to wonder, why not do fans. I did a small paper test ... a regular
+> triangle grid.
+>   case : transforms per case : percentage less than seperate triangles
+>   seperate triangles : 144 : 0
+>   fans : 77 : 53%
+>   strips : 56 : 39%
+> 
+> OK so strips win here. But on a general mesh (especially one optimized for
+> rt3d) the strip runs are not as long. In fact, there are cases when fans
+> produce less transforms than strips (this is the case in my landscape
+> engine).
+ 
+The other thing that leads me to get more excited about fans than
+strips is that they tend to be more compact - spatially that is -
+becuase they are all sharing that one vertex.
+
+This is useful for pre-OpenGL culling since it greatly increases the
+probablility that a fan will cleanly come out wither entirely inside
+or entirely outside the view frustum. If (like me) you are using a
+bounding sphere test to accept or reject entire strip/fan primitives
+then it's easy to visualise how fans fit better into a neat sphere
+than those long wandering strips.
+
+I'm still struggling to convert an old terrain system which was based
+around IRISGL primitives (alas, no fans) - and the wins for fans
+seem pretty significant.
+
+Steve Baker                (817)619-8776 (Vox/Vox-Mail)
+Raytheon Systems Inc.      (817)619-4028 (Fax)
+Work: SBaker@link.com      http://www.hti.com
+Home: SJBaker1@airmail.net http://web2.airmail.net/sjbaker1
+
+-- 
+Author: Steve Baker
+  INET: sbaker@link.com
+
+Fat City Network Services    -- (619) 538-5051  FAX: (619) 538-5051
+San Diego, California        -- Public Internet access / Mailing Lists
+--------------------------------------------------------------------
+To REMOVE yourself from this mailing list, send an E-Mail message
+to: ListGuru@fatcity.com (note EXACT spelling of 'ListGuru') and in
+the message BODY, include a line containing: UNSUB OPENGL-GAMEDEV-L
+(or the name of mailing list you want to be removed from).  You may
+also send the HELP command for other information (like subscribing).
+
+From sbaker@link.com  Sun Aug 16 00:55:44 1998
+X-VM-v5-Data: ([nil nil nil t t nil nil nil nil]
+	["1920" "Sun" "16" "August" "1998" "00:52:12" "-0500" "Steve Baker" "sbaker@link.com" "" "41" "Re: strips vs. fans" "^From:" nil nil "8" nil nil nil nil nil]
+	nil)
+Received: from lfkw10.bgm.link.com (bgm.link.com [130.210.2.10])
+	by meserv.me.umn.edu (8.9.1a/8.9.1) with ESMTP id AAA14434
+	for ; Sun, 16 Aug 1998 00:55:43 -0500 (CDT)
+Received: from lechter.bgm.link.com (lechter.bgm.link.com [130.210.63.22])
+          by lfkw10.bgm.link.com (8.8.6/RSC-RTI-1.0) with SMTP
+	  id AAA05219 for ; Sun, 16 Aug 1998 00:55:12 -0500 (CDT)
+X-Sender: steve@lechter.bgm.link.com
+Reply-To: Steve Baker 
+In-Reply-To: <199808152138.QAA27557@kenai.me.umn.edu>
+Message-ID: 
+MIME-Version: 1.0
+Content-Type: TEXT/PLAIN; charset=US-ASCII
+From: Steve Baker 
+To: "Curtis L. Olson" 
+Subject: Re: strips vs. fans
+Date: Sun, 16 Aug 1998 00:52:12 -0500 (CDT)
+
+On Sat, 15 Aug 1998, Curtis L. Olson wrote:
+
+> At one point did you suggest that I might have comperable performance
+> with fans vs. tri-strips?
+ 
+Yes. We went down the path of changing our terrain tools to use
+fans - the performance was essentially unchanged.
+
+In the end, it depends on the average number of vertices per triangle.
+For very long tristrips, or for very large fans, the average tends
+towards 1 vertex per triangle. In this respect, there is no performance
+difference between strips and fans. However, there are two reasons
+to prefer strips and one reason to prefer fans:
+
+1) Strips are allegedly implemented in hardware for Voodoo-2, and
+   when Mesa supports that, there could be some savings to be had
+   in triangle setup times. I have not heard that the same is true
+   for tri-fans - but it's possible.
+
+2) Strips can potentially contain more triangles than fans because
+   they are not limited to having all their triangles share that
+   one start vertex. If you can actually make your strips longer
+   for practical data then strips should win. However, it's quite
+   hard to get an average strip strip length more than four or
+   five when your terrain has features like lakes, rivers, forest,
+   etc embedded in it.
+
+3) Fans have one theoretical advantage - since all the triangles
+   share that first vertex, fans tend to be spatially compact.
+   This means that crude bounding sphere culling will be more
+   effective at reducing the number of triangles sent to OpenGL
+   than it might be with tri-strips.
+
+My practical experience so far seems to suggest that these
+various effects are either so tiny as to make no difference - or
+somehow cancel out. However, it's work-in-progress.
+
+Steve Baker                (817)619-2657 (Vox/Vox-Mail)
+Raytheon Systems Inc.      (817)619-4028 (Fax)
+Work: SBaker@link.com      http://www.hti.com
+Home: SJBaker1@airmail.net http://web2.airmail.net/sjbaker1
+
+From sbaker@link.com  Tue Aug 18 08:57:29 1998
+X-VM-v5-Data: ([nil nil nil nil nil nil nil nil nil]
+	["4108" "Tue" "18" "August" "1998" "08:56:05" "-0500" "Steve Baker" "sbaker@link.com" nil "87" "Re: strips vs. fans" "^From:" nil nil "8" nil nil nil nil nil]
+	nil)
+Received: from lfkw10.bgm.link.com (bgm.link.com [130.210.2.10])
+	by meserv.me.umn.edu (8.9.1a/8.9.1) with ESMTP id IAA10259
+	for ; Tue, 18 Aug 1998 08:57:27 -0500 (CDT)
+Received: from samantha.bgm.link.com (samantha.bgm.link.com [130.210.65.19])
+          by lfkw10.bgm.link.com (8.8.6/RSC-RTI-1.0) with SMTP
+	  id IAA11753 for ; Tue, 18 Aug 1998 08:56:48 -0500 (CDT)
+X-Sender: steve@samantha.bgm.link.com
+Reply-To: Steve Baker 
+In-Reply-To: <199808172109.QAA25296@kenai.me.umn.edu>
+Message-ID: 
+MIME-Version: 1.0
+Content-Type: TEXT/PLAIN; charset=US-ASCII
+From: Steve Baker 
+To: "Curtis L. Olson" 
+Subject: Re: strips vs. fans
+Date: Tue, 18 Aug 1998 08:56:05 -0500 (CDT)
+
+On Mon, 17 Aug 1998, Curtis L. Olson wrote:
+
+> So do just use a "greedy" algorithm to build fans, or do you do
+> something more sophisticated?
+ 
+Well, we have to consider the larger issues.
+
+* From the point of view of OpenGL, the more triangles in the strip/fan
+  the better.
+* From the point of view of FOV culling, the more compact the strip/fan
+  the better.
+* From the point of view of intersection testing, the shorter the strip/fan
+  the better.
+
+We use a variety of stripping algorithms depending on the cicumstance.
+Sometimes we just do the 'greedy' algorithm, sometimes we impose a limit
+on the maximum strip length which tends to cut down on the number of
+single triangles (which are especially costly on SGI hardware for some
+reason). Sometimes we use an algorithm that has an estimate of the
+relative costs of transforming strips of length 1, 2, 3, 4, ... which
+tries many different ways to strip/fan until it finds one with a cost
+per-triangle that is less than some user-specified limit - and the
+ultimate algorithm simply does a totally exhaustive search for the cheapest
+overall set of strips.
+
+The last few algorithms can take days to run on even relatively simple
+objects - and we use those only for the simplest of objects when that object
+is re-used a gazillion times in the database. For example, we did a
+model of Yellowstone national park where the customer needed the highest
+possible density of single, individual trees. We built a set of tree
+cluster models and ran the tri-stripper at maximum optimisation on them
+all to get down the cost of transforming all those thousands of trees to
+the absolute minimum.
+
+However, when we have the whole of North America to tstrip, we can't
+afford the CPU hours to do anything much more than the very basic
+limited-length-greedy algorithm.
+
+Limiting the maximum strip length helps the FOV culling so much that
+we pretty much always limit the length to a dozen of so triangles.
+That's principally due to SGI hardware which gains performance as the
+strip length increases - up to about 10 triangles - beyond which it
+doesn't really help any.
+
+It's MUCH better (on SGI ONYX hardware) to generate two strips of 5
+triangles each than it is to generate one strip of 9 and one single
+triangle.
+
+For us, there are yet other considerations. We don't currently drive
+OpenGL directly - we use the Performer scene graph API as a layer on
+top. Performer can optimise the case where all the triangles in the
+strip share the same surface normal and/or colour. In that case, it
+generates just one glNormal and glColor command for each strip. These
+are called 'Flat-Tri-strips'. For man-made objects, we can often win
+by having shorter strips that are flat rather than longer strips that
+are non-flat because the cost of transforming the normals is not
+negligable.
+
+Some of the SGI machines also optimise for the case when there is only
+a single, infinite light source by only doing illumination per-normal
+rather than per-vertex - this also makes flat strips worth having.
+
+Some of these optimisations are actually pessimisations on some machines,
+so you have to optimise the database for the hardware.
+
+As you can see, this is another incredibly complicated issue if you
+want to get absolutely *ALL* the performance you can.
+
+It's unreasonable to expect FGFS to do this with the limited effort
+available. We have two or three full-time staff thinking about
+database tools - and we have been working with OpenGL for five
+years now.
+
+> > 1) Strips are allegedly implemented in hardware for Voodoo-2, and
+> >    when Mesa supports that, there could be some savings to be had in
+> >    triangle setup times. I have not heard that the same is true for
+> >    tri-fans - but it's possible.
+> 
+> I would think that if they did strips, they could easily do fans ...
+ 
+I just asked the question on the 3Dfx newsgroup - we'll get a definitive
+answer there.
+
+Steve Baker                (817)619-2657 (Vox/Vox-Mail)
+Raytheon Systems Inc.      (817)619-4028 (Fax)
+Work: SBaker@link.com      http://www.hti.com
+Home: SJBaker1@airmail.net http://web2.airmail.net/sjbaker1
+
diff --git a/Hints/texturing b/Hints/texturing
new file mode 100644
index 000000000..d4c53031a
--- /dev/null
+++ b/Hints/texturing
@@ -0,0 +1,1073 @@
+From sbaker@link.com  Mon Jan 12 09:03:37 1998
+X-VM-v5-Data: ([nil nil nil nil t nil nil nil nil]
+	["11420" "Mon" "12" "January" "1998" "11:03:54" "-0600" "Steve Baker" "sbaker@link.com" "" "318" "[FGFS] Da-da-da (fwd)" "^From:" nil nil "1" nil nil nil nil nil]
+	nil)
+X-VM-Message-Order:
+	(1 2 3 5 4 6 7 8 9 10 11 12 13 14 15
+	 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
+	 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
+	 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
+	 61 62 63)
+X-VM-Summary-Format: "%n %*%a %-17.17F %-3.3m %2d %4l/%-5c %I\"%s\"\n"
+X-VM-Labels: ("r")
+X-VM-VHeader: ("Resent-" "From:" "Sender:" "To:" "Apparently-To:" "Cc:" "Subject:" "Date:") nil
+X-VM-Bookmark: 4
+Received: from lfkw10.bgm.link.com (bgm.link.com [130.210.2.10])
+	by meserv.me.umn.edu (8.8.8/8.8.6) with ESMTP id JAA01094
+	for ; Mon, 12 Jan 1998 09:03:28 -0600 (CST)
+Received: from lechter.bgm.link.com (lechter.bgm.link.com [130.210.239.45])
+          by lfkw10.bgm.link.com (8.8.6/HTI-Hack-8.8.4) with SMTP
+	  id JAA14248 for ; Mon, 12 Jan 1998 09:02:52 -0600 (CST)
+X-Sender: steve@lechter.bgm.link.com
+Reply-To: Steve Baker 
+Message-ID: 
+MIME-Version: 1.0
+Content-Type: TEXT/PLAIN; charset=US-ASCII
+From: Steve Baker 
+To: curt@me.umn.edu
+Subject: [FGFS] Da-da-da (fwd)
+Date: Mon, 12 Jan 1998 11:03:54 -0600 (CST)
+
+
+
+> I went with the wife to see "Titanic" tonight.  It was all sold out,
+
+It was a 'girl' movie - my Wife loved it - my kid and I zzzzz'd out.
+
+> and the only other movie that hadn't started yet was "007" which Ruth
+> didn't want see. :-(
+
+Now *that* was a 'boy' movie. Easily the best Bond movie so far (although
+the chase scene with the Tank in Goldeneye is still up there).
+
+> So I just generated a section of scenery in "ultra-high" detail and am
+> getting about 0.2 frames a second.
+
+Pretty neat ... but what it needs is:
+
+  ####### ####### #     # ####### #     # ######  #######
+     #    #        #   #     #    #     # #     # #
+     #    #         # #      #    #     # #     # #
+     #    #####      #       #    #     # ######  #####
+     #    #         # #      #    #     # #   #   #
+     #    #        #   #     #    #     # #    #  #
+     #    ####### #     #    #     #####  #     # #######
+
+(which is v.easy to add - and comes for free on a 3Dfx - although it'll
+*KILL* your frame rate on software-only Mesa).
+
+Could you do a screen dump of a wire-frame rendering of that so people can
+see the tesselation? Just set xglPolygonMode(GL_FRONT_AND_BACK,GL_LINE).
+
+> Anyone know anything about view frustum culling?
+
+Yep.
+
+Two issues:
+
+1) Scene hierarchy generation (offline).
+
+2) Runtime culling.
+
+
+
+Hierarchy:
+==========
+
+There are lots of ways to do this. I usually build an heirerchical description
+of each terrain tile. I typically build a tree structure that's organized
+as follows:
+
+                              |  The World.
+                              | 
+           ___________________|___   
+          |   |   |   |   |   |   |
+          *   *   *   *   *   *   *  Terrain tiles currently loaded
+          |   |   |   |   |   |   |
+                              |     
+                              |
+                         _____|_____
+                        |   |   |   |
+                        *   *   *   *   Quarter-tiles
+                        |   |   |   |
+                            |
+                            |
+                       _____|_____ 
+                      |   |   |   |
+                      *   *   *   *   Sixteenth-tiles
+                      |   |   |   |
+
+...and so on down until the number of polygons in each 'object' gets 'small enough'.
+
+When you do this, don't try to split polygons when they cross a quarter or a
+sixteenth tile boundary - just dump each polygon into the nearest 'bucket' to
+it's centroid.
+
+Do your tri-stripping on the leaf nodes of this tree - so that each tristrip
+is contained entirely within one bucket.
+
+Eventually, you will need to include buildings, roads, rivers, etc. Since these
+need to be culled by level of detail, it is often useful to put them into a separate
+tree structure that parallels the terrain 'skin' structure.
+
+Finally, compute a bounding sphere around each leaf node, find the best fit
+sphere by finding the maximum and minimim x, y and z of the tristrips in that
+leaf node, taking the mid-point and then finding the vertex that is furthest
+from that center point and using it as the radius.
+
+Compute the bounding sphere for each level in the tree (everywhere where there is
+a '*' in my diagram).
+
+Runtime:
+========
+
+At runtime, you walk that tree every frame, testing the bounding sphere against
+the view frustum.
+
+* If the sphere lies entirely outside the view frustum then stop traversal
+  for that node. There is no need to test any of the nodes beneath this one
+  (we know that none of their leaf tristrips are visible).
+
+* If the sphere lies entirely inside the view frustum then traverse immediately
+  to all of the leaves below this node without doing any more sphere testing
+  on them - draw all of the tristrips that are there. (We know they are all visible)
+
+* If the sphere straddles the view frustum then check each daughter node in
+  turn by applying this algorithm on them recursively. If a leaf node straddles
+  the view frustrum then it's bad luck, you just draw all the tristrips it
+  contains and let OpenGL do the work.
+
+You might also want to put a 'transition range' onto each node and if it
+lies beyond that range cull it. You can also use this to conveniently
+switch levels of detail by having multiple versions of each object in
+the tree.
+
+Testing a sphere against the View Frustum:
+==========================================
+
+In most cases, we can describe the volume of space that you can see
+through the little glass window on the front of your CRT using a
+Frustum (frequently mis-spelled as Frustrum or Fustrum even in some
+text books).
+
+A frustum is a truncated pyramid - which typically bounded by six
+planes called:
+
+  NEAR, FAR, LEFT, RIGHT, TOP, BOTTOM
+
+There are applications that require additional clipping planes (eg for
+non-rectangular screens) - extending the work described in this
+to cater for that is not hard).
+
+In principal, all six planes can be constructed as general plane
+equations:
+
+    A x + B y + C z + D == 0
+
+However, for most applications, NEAR and FAR are parallel to the
+screen, LEFT, RIGHT,TOP and BOTTOM all meet at the eye and the eye lies
+along a vector that extends out from the center of the screen and is
+perpendicular to it. This simplifies the equations considerably for
+practical applications.
+
+Transforms.
+~~~~~~~~~~~
+
+It is easiest to perform culling in a coordinate system where the
+eyepoint is at the origin and the line from the eye through the center
+of the screen lies along one major axis with the edges of the screen
+parallel to the remaining two axes. This coordinate system is called
+'Eye Space'.
+
+Testing a Sphere against a Frustum.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The most important thing to bear in mind about culling is that the
+first trivial-reject test you apply is by far the most time-critical.
+This test is always applied to more nodes than any of the subsequent
+tests.
+
+So, do the cheapest test first.
+
+This is typically the NEAR plane test. Everything behind the viewers
+head gets chopped out - and it's an especially cheap test.
+
+
+   if ( obj_sphere.center.z < near_plane - obj_sphere.radius )
+     REJECT!!
+
+
+...next do the second cheapest test (assuming you know that your
+database could possibly extend beyond the far clip plane)...
+
+
+   if ( obj_sphere.center.z - obj_sphere.radius > far_plane )
+     REJECT!!
+
+
+...and *then* (for each of the other 4 planes) do...
+
+
+   if ( distance( obj.position, plane ) <= obj_sphere.radius )
+     REJECT!!
+
+
+(The algorithm for computing that 'distance()' function is described
+below).
+
+It's also useful to know that in many applications, you cull more
+objects from the left and right faces of the frustum than you do from
+the top and bottom - so test left, then right, then bottom then top.
+
+Also, with bounding sphere tests, you shouldn't forget to do
+total-accept as well as total-reject tests. Once you know that an
+object's sphere is TOTALLY on screen, you don't have to descend into
+the daughter objects to cull-test them...you *know* they are all
+on-screen.
+
+Another way to look at that it to remember which of the six possible
+plane tests didn't even touch the sphere - as you work your way down
+the object hierarchy, you can accumulate those flags and avoid even
+testing those planes that a parent sphere has already cleanly passed.
+If you do this then a vast percentage of your spheres will only need to
+be tested against one plane.  However, for the normal case of a simple
+frustum - when you examine the fully optimised
+distance-of-point-from-plane code (below), you may well conclude that
+this additional logic doesn't justify the paltry amount of additional
+math that it might save.
+
+Computing the Distance from Sphere Center to Clipping Plane.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A plane can be represented by the equation
+
+
+     Ax + By + Cz + D = 0 ;
+
+
+A,B,C is just the surface normal of the plane and D is the shortest
+distance from the origin to the plane.
+
+So, if you need to find the distance of a point from the plane, just
+imagine a new plane that goes through your test point and is parallel
+to the plane you want to test. The plane equation of that new plane
+would be:
+
+
+     A'x + B'y + C'z + D' = 0 ;
+
+
+Since the two planes are parallel, their surface normals are the same,
+so
+
+
+   A' == A B' == B C' == C D' == D + distance_between_the_two_planes
+
+
+...the only thing that's different is their D values - which differ by
+the distance of your test point from the original plane.
+
+So, for a point (x,y,z), the distance 'd' from the plane (A,B,C,D) is
+derived as:
+
+
+   d = D' - D
+     = -A'x - B'y - C'z - D
+     = -Ax - By - Cz - D
+     = -( [ABC]dot[xyz] + D )
+
+
+A dot-product of the point and the surface normal of the plane, plus
+the distance from the plane to the origin. Three multiplies, three
+additions and a negation.
+
+As an aside - if you consider the point (x,y,z) as a FOUR element
+homogeneous vector (x,y,z,w) then 'w' is 1.0 and you can compute the
+distance by simply taking the four element dot-product of (A,B,C,D)
+with (x,y,z,w). If you have fast 4x4 matrix math hardware in your
+machine then you can use it to compute the distance from a point to all
+four planes in a single operation!
+
+That's the general result for an arbitary plane - but culling to the
+view frustum is a very special case. If you are working in eye-relative
+coordinates (IMHO this is best), then since all TOP,BOTTOM,LEFT,RIGHT
+planes of the frustum meet at the eye - and since the eye is at the
+origin (by definition), then D is always zero for those planes and that
+saves you a subtract.
+
+If you are feeling even more in need of optimisation - then you can
+save one multiply per plane by realising that (for rectangular screens)
+one of the three components of the plane equation will always be zero.
+
+So, for the LEFT clip plane, the Y component of the normal of the plane
+is zero, so the distance to the left or right plane is just
+
+
+     d = -( Ax + Cz )
+
+
+...and to the top or bottom plane it's just:
+
+
+     d = -( By + Cz )
+
+
+Furthermore, we know that the A component for the LEFT plane is just
+the negation of the A component of the RIGHT plane, and the C component
+is the same for both LEFT and RIGHT (and similarly, the B component of
+the TOP plane, is the negation of the B component for the BOTTOM plane
+and the C component is the same for both TOP and BOTTOM). This means
+that you only need four multiplies and four additions to do the entire
+job. (Since you are only using this for culling, you don't need the
+minus sign - just reverse the conditional).
+
+The NEAR and FAR planes are typically parallel to the X/Y plane. That
+means that A and B are both zero and C is one (or minus-one) - but D is
+not zero, so the math boils down to an add and a negate:
+
+
+     d = -(z + D)
+
+
+Conclusions.
+~~~~~~~~~~~~
+
+Sphere-based culling can be extremely cost-effective. It's so cheap
+that even if you feel the need to use a bounding cubeoid (or even a yet
+more complex shape), it's still worth doing a sphere-based cull first
+just to get rid of the trivial accept and reject cases.
+
+
+Steve Baker                     817-619-8776 (Vox/Vox-Mail)
+Hughes Training Inc.            817-619-4028 (Fax)
+2200 Arlington Downs Road       SBaker@link.com (eMail)
+Arlington, Texas. TX 76005-6171 SJBaker1@airmail.net (Personal eMail)
+http://www.hti.com              http://web2.airmail.net/sjbaker1 (personal)
+
+** Beware of Geeks bearing GIF's. **
+
+
+From owner-flight-gear@me.umn.edu  Thu Jan 15 21:09:17 1998
+X-VM-v5-Data: ([nil nil nil nil nil nil nil nil nil]
+	["1752" "Thu" "15" "January" "1998" "22:08:56" "-0500" "Bob Kuehne" "rpk@sgi.com" nil "41" "Re: [FGFS] Status Update w/ Scenery" "^From:" nil nil "1" nil nil nil nil nil]
+	nil)
+Received: (from majordom@localhost)
+	by meserv.me.umn.edu (8.8.8/8.8.6) id VAA10212
+	for flight-gear-outgoing; Thu, 15 Jan 1998 21:09:17 -0600 (CST)
+X-Authentication-Warning: meserv.me.umn.edu: majordom set sender to owner-flight-gear@me.umn.edu using -f
+Received: from sgi.sgi.com (SGI.COM [192.48.153.1])
+	by meserv.me.umn.edu (8.8.8/8.8.6) with SMTP id VAA10205
+	for ; Thu, 15 Jan 1998 21:09:11 -0600 (CST)
+Received: from dataserv.detroit.sgi.com (relay.detroit.sgi.com [169.238.128.2]) by sgi.sgi.com (950413.SGI.8.6.12/970507) via ESMTP id TAA28641
+	for <@external-mail-relay.sgi.com:flight-gear@me.umn.edu>; Thu, 15 Jan 1998 19:09:07 -0800
+	env-from (rpk@sgi.com)
+Received: from applab3.detroit.sgi.com by dataserv.detroit.sgi.com via ESMTP (951211.SGI.8.6.12.PATCH1502/930416.SGI)
+	for <@dataserv.detroit.sgi.com:flight-gear@me.umn.edu> id WAA02541; Thu, 15 Jan 1998 22:09:00 -0500
+Received: from localhost (rpk@localhost) by applab3.detroit.sgi.com (950413.SGI.8.6.12/950213.SGI.AUTOCF) via SMTP id WAA04150 for ; Thu, 15 Jan 1998 22:08:56 -0500
+X-Sender: rpk@applab3.detroit.sgi.com
+In-Reply-To: <199801160204.UAA06347@kenai.me.umn.edu>
+Message-ID: 
+MIME-Version: 1.0
+Content-Type: TEXT/PLAIN; charset=US-ASCII
+Precedence: bulk
+Reply-To: flight-gear@me.umn.edu
+From: Bob Kuehne 
+Sender: owner-flight-gear@me.umn.edu
+To: flight-gear@me.umn.edu
+Subject: Re: [FGFS] Status Update w/ Scenery
+Date: Thu, 15 Jan 1998 22:08:56 -0500 (EST)
+
+On Thu, 15 Jan 1998, Curtis L. Olson wrote:
+
+> Eric Mitchell (from the MSFS world) sent me some really nice textures,
+> so I may just have to sit down and figure out how to texture a polygon
+> in OpenGL.  It looks like the hardest part will be deciding what image
+> format to use and figuring out how to read that into memory so OpenGL
+> can use it as a texture.
+
+1) load the texture (and mipmaps) via glTexImage2D. Ideally we'll want to
+use a bound texture (in 1.1, and in 1.0 as an extension) for efficency.
+
+2) enable texturing with glEnable( GL_TEXTURE_2D )
+
+3) Throw a 'glTexCoord2[*]' (your favorite variant of that call) next to
+each vertex you draw.
+
+> I have an example of how to do this with the JPEG format using
+> jpeglib.  IRIX RGB format seems like it might be the most
+> straightforward, but not the most space efficient.  I don't believe
+
+on disk - note that in memory the only type of image data that most OpenGL
+implementations can deal with is uncompressed.
+
+> it's pretty easy to convert amongst these formats, but not necessarily
+> as easy to read them into your program.
+> One of these day's I'm going to have to break down and buy an OpenGL
+> book ... I bet they tell you exactly how to do this stuff. :-)
+
+You, sir, are a candidate for the Red Book. :)
+
+Bob
+
+Bob Kuehne    |         There was coffee.           |    Applications
+rpk@sgi.com   |         Life would go on.           |     Consulting
+248/848-4465  |  William Gibson, The Winter Market  |  Silicon Graphics
+
+-------------------------------------
+Please visit the Flight Gear web page:
+http://www.menet.umn.edu/~curt/fgfs/
+For help on using this list (especially unsubscribing), send a message to
+"flight-gear-request@me.umn.edu" with a single line of text: "help".
+
+From owner-flight-gear@me.umn.edu  Fri Jan 16 01:41:59 1998
+X-VM-v5-Data: ([nil nil nil nil nil nil nil nil nil]
+	["1477" "Fri" "16" "January" "1998" "03:42:36" "-0600" "Steve Baker" "sbaker@link.com" nil "38" "Re: [FGFS] Status Update w/ Scenery" "^From:" nil nil "1" nil nil nil nil nil]
+	nil)
+Received: (from majordom@localhost)
+	by meserv.me.umn.edu (8.8.8/8.8.6) id BAA15817
+	for flight-gear-outgoing; Fri, 16 Jan 1998 01:41:59 -0600 (CST)
+X-Authentication-Warning: meserv.me.umn.edu: majordom set sender to owner-flight-gear@me.umn.edu using -f
+Received: from lfkw10.bgm.link.com (bgm.link.com [130.210.2.10])
+	by meserv.me.umn.edu (8.8.8/8.8.6) with ESMTP id BAA15813
+	for ; Fri, 16 Jan 1998 01:41:53 -0600 (CST)
+Received: from lechter.bgm.link.com (lechter.bgm.link.com [130.210.239.45])
+          by lfkw10.bgm.link.com (8.8.6/HTI-Hack-8.8.4) with SMTP
+	  id BAA10510 for ; Fri, 16 Jan 1998 01:41:21 -0600 (CST)
+X-Sender: steve@lechter.bgm.link.com
+In-Reply-To: 
+Message-ID: 
+MIME-Version: 1.0
+Content-Type: TEXT/PLAIN; charset=US-ASCII
+Precedence: bulk
+Reply-To: flight-gear@me.umn.edu
+From: Steve Baker 
+Sender: owner-flight-gear@me.umn.edu
+To: flight-gear@me.umn.edu
+Subject: Re: [FGFS] Status Update w/ Scenery
+Date: Fri, 16 Jan 1998 03:42:36 -0600 (CST)
+
+On Thu, 15 Jan 1998, Bob Kuehne wrote:
+
+> 1) load the texture (and mipmaps) via glTexImage2D. Ideally we'll want to
+> use a bound texture (in 1.1, and in 1.0 as an extension) for efficency.
+ 
+Whether to load or compute the MIPmaps is an interesting question.
+
+The nice thing about loading the MIPmaps from disk is that you can
+use off-line tools to compute fancy MIPmaps in some special cases -
+notably for translucent textures.
+
+Talk to me off-line for an in-depth discussion sometime.
+
+> > One of these day's I'm going to have to break down and buy an OpenGL
+> > book ... I bet they tell you exactly how to do this stuff. :-)
+> 
+> You, sir, are a candidate for the Red Book. :)
+
+No question. Purchase (in this order):
+
+   Red    (make sure your bookstore doesn't stick you with V1.0!!)
+   Green
+   Blue   (but only if you dislike reading man pages off the screen)
+
+Steve Baker                     817-619-8776 (Vox/Vox-Mail)
+Hughes Training Inc.            817-619-4028 (Fax)
+2200 Arlington Downs Road       SBaker@link.com (eMail)
+Arlington, Texas. TX 76005-6171 SJBaker1@airmail.net (Personal eMail)
+http://www.hti.com              http://web2.airmail.net/sjbaker1 (personal)
+
+** Beware of Geeks bearing GIF's. **
+
+
+-------------------------------------
+Please visit the Flight Gear web page:
+http://www.menet.umn.edu/~curt/fgfs/
+For help on using this list (especially unsubscribing), send a message to
+"flight-gear-request@me.umn.edu" with a single line of text: "help".
+
+From sbaker@link.com  Fri Jan 16 01:28:35 1998
+X-VM-v5-Data: ([nil nil nil nil nil nil nil nil nil]
+	["2966" "Fri" "16" "January" "1998" "03:29:18" "-0600" "Steve Baker" "sbaker@link.com" nil "74" "Re: [FGFS] Status Update w/ Scenery" "^From:" nil nil "1" nil nil nil nil nil]
+	nil)
+Received: from lfkw10.bgm.link.com (bgm.link.com [130.210.2.10])
+	by meserv.me.umn.edu (8.8.8/8.8.6) with ESMTP id BAA15513
+	for ; Fri, 16 Jan 1998 01:28:34 -0600 (CST)
+Received: from lechter.bgm.link.com (lechter.bgm.link.com [130.210.239.45])
+          by lfkw10.bgm.link.com (8.8.6/HTI-Hack-8.8.4) with SMTP
+	  id BAA02053 for ; Fri, 16 Jan 1998 01:28:02 -0600 (CST)
+X-Sender: steve@lechter.bgm.link.com
+Reply-To: Steve Baker 
+In-Reply-To: <199801160204.UAA06347@kenai.me.umn.edu>
+Message-ID: 
+MIME-Version: 1.0
+Content-Type: TEXT/PLAIN; charset=US-ASCII
+From: Steve Baker 
+To: "Curtis L. Olson" 
+Subject: Re: [FGFS] Status Update w/ Scenery
+Date: Fri, 16 Jan 1998 03:29:18 -0600 (CST)
+
+On Thu, 15 Jan 1998, Curtis L. Olson wrote:
+
+> 5.  This allows me to generate very nice images with the one exception
+>     which you can clearly see if you view the picture.  The shared vertices
+>     aren't currently using shared normals, so the shading doesn't
+>     transition smoothly across tile boundaries.
+ 
+We cheat and point all the vertices along the edges of squares
+straight upwards.
+
+The reason for this is simple - it allows us to build each square
+independantly of the others - which is an important issue when
+databases are build by a number of different people at different
+times.
+
+The result is remarkably reasonable - you still can't really tell
+where the terrain tile edges are.
+
+> Eric Mitchell (from the MSFS world) sent me some really nice textures,
+> so I may just have to sit down and figure out how to texture a polygon
+> in OpenGL.  It looks like the hardest part will be deciding what image
+> format to use and figuring out how to read that into memory so OpenGL
+> can use it as a texture.
+ 
+Consider using PNG as your image format - it's the future - it's very
+compact, the loader is freeware, it's not a "lossy" format.
+
+> I have an example of how to do this with the JPEG format using
+> jpeglib.
+
+JPEG is **NOT** a good choice - the data compression is "LOSSY" -
+when you compress an image and decompress it, what you end up with
+is different from what you started with. The compression scheme is
+designed to not be noticable to the human eye - but that doesn't
+hold up when the image is viewed in perspective. JPEG sucks.
+
+> IRIX RGB format seems like it might be the most
+> straightforward, but not the most space efficient.
+
+True - but for lossless compression (where compress+decompress == no-op)
+it's not far from optimal.
+
+> I don't believe GIF is a 24bit color format (only 8bit)
+
+That's true - there are also legal issues over it's copyright/patent.
+
+> BMP has "Bill" written all over it (enough said.) :-)
+
+Exactly.
+
+> But, it's pretty easy to convert amongst these formats,
+> but not necessarily as easy to read them into your program.
+
+PNG is easy bacuse there are is a standard (and really good)
+library available. It's also supported by both major web
+browsers. It's the official replacement for GIF on the web.
+
+> One of these day's I'm going to have to break down and buy an OpenGL
+> book ... I bet they tell you exactly how to do this stuff. :-)
+
+Yep - the example in the Red book is about all you need.
+
+I'm sure you could get what you need from one of the Mesa
+example programs though (in fact, aren't all the RedBook
+examples distributed with Mesa? - I forget).
+
+Steve Baker                     817-619-8776 (Vox/Vox-Mail)
+Hughes Training Inc.            817-619-4028 (Fax)
+2200 Arlington Downs Road       SBaker@link.com (eMail)
+Arlington, Texas. TX 76005-6171 SJBaker1@airmail.net (Personal eMail)
+http://www.hti.com              http://web2.airmail.net/sjbaker1 (personal)
+
+** Beware of Geeks bearing GIF's. **
+
+
+From owner-flight-gear@me.umn.edu  Thu Feb 19 12:34:42 1998
+X-VM-v5-Data: ([nil nil nil nil t nil nil nil nil]
+	["3263" "Thu" "19" "February" "1998" "12:35:18" "-0600" "Steve Baker" "sbaker@link.com" "" "85" "Re: [FGFS] New HUD Screen Shots" "^From:" nil nil "2" nil nil (number " " mark "  R  Steve Baker       Feb 19   85/3263  " thread-indent "\"Re: [FGFS] New HUD Screen Shots\"\n") nil nil]
+	nil)
+Received: (from majordom@localhost)
+	by meserv.me.umn.edu (8.8.8/8.8.8) id MAA15262
+	for flight-gear-outgoing; Thu, 19 Feb 1998 12:34:42 -0600 (CST)
+X-Authentication-Warning: meserv.me.umn.edu: majordom set sender to owner-flight-gear@me.umn.edu using -f
+Received: from lfkw10.bgm.link.com (bgm.link.com [130.210.2.10])
+	by meserv.me.umn.edu (8.8.8/8.8.8) with ESMTP id MAA15258
+	for ; Thu, 19 Feb 1998 12:34:35 -0600 (CST)
+Received: from lechter.bgm.link.com (lechter.bgm.link.com [130.210.239.45])
+          by lfkw10.bgm.link.com (8.8.6/HTI-Hack-8.8.4) with SMTP
+	  id MAA19280 for ; Thu, 19 Feb 1998 12:33:57 -0600 (CST)
+X-Sender: steve@lechter.bgm.link.com
+In-Reply-To: <199802191621.KAA09095@kenai.me.umn.edu>
+Message-ID: 
+MIME-Version: 1.0
+Content-Type: TEXT/PLAIN; charset=US-ASCII
+Precedence: bulk
+Reply-To: flight-gear@me.umn.edu
+From: Steve Baker 
+Sender: owner-flight-gear@me.umn.edu
+To: flight-gear@me.umn.edu
+Subject: Re: [FGFS] New HUD Screen Shots
+Date: Thu, 19 Feb 1998 12:35:18 -0600 (CST)
+
+On Thu, 19 Feb 1998, Curtis L. Olson wrote:
+
+> Here's where I'm at with textures.
+> 
+> 1.  I gleaned some "RGB" format texture loading code out of a GLUT
+>     demo.
+ 
+So you have the texture into OpenGL using glGenTextures/glBindTexture
+and you have a number for each texture? Does the routine generate
+the MIPmaps for you?
+
+> 2.  I have some reasonable terrain textures for starters that Eric
+>     Mitchell from the MSFS world contributed.
+ 
+Good start! (Could you post them to the Web site? I might be able
+to suggest a suitable scale factor for them)
+
+> So for anyone who's familiar with texturing, it would likely be a
+> simple matter to call the texture load routine and do all the
+> OpenGL-ese to setup the textures.
+ 
+As a starter (just to get something going), you could simply divide the
+latitude and longitude of each terrain vertex by some suitable constant
+and use that as the texture coordinate. Alternatively, you could let
+OpenGL do the work using glTexGenf.
+
+Something like (off the top of my head):
+
+  glEnable        ( GL_TEXTURE_2D ) ;
+  glBindTexture   ( GL_TEXTURE_2D, texture_number ) ;
+  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_LINEAR ) ;
+  glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR ) ;
+  glTexEnvi       ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ) ;
+  glHint          ( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST ) ;
+
+  {
+    Draw bunches of terrain
+    For each vertex, add a glTexCoord2f with your scaled lat/long
+    values
+  }
+
+  glDisable       ( GL_TEXTURE_2D ) ;
+
+> So, I guess I've been trying to make what I have be a bit more solid
+> before I charge forward again.
+ 
+I guess that's a good thing.
+
+Adding texturing is *SO* easy though that you might want to just
+slip it in when you have an odd hour and feel like getting a 'WOW!'
+response!
+
+    :-)
+
+> > Have you checked the link ordering?
+> > 
+> > I see a couple of posts a day from people who have either failed to
+> > link with M$ OGL *as well as* SGI's OpenGL (SGI's OpenGL relies
+> > on some functions from M$ OpenGL) - or who have linked them in the
+> > wrong order or something.
+> 
+> Interesting, I'm not linking in opengl32 or glu32 ...  The compiler
+> never complains about unresolved symbols, and at runtime, I get no
+> complaint about missing dll's.
+ 
+Hmmm - that's odd - I'm pretty sure you need them because SGI's
+OpenGL falls back to M$ opengl if it thinks that M$'s OpenGL has
+hardware accelleration. That suggests that it *must* link to it
+somehow.
+
+Steve Baker                     817-619-8776 (Vox/Vox-Mail)
+Raytheon Systems Inc.           817-619-4028 (Fax)
+2200 Arlington Downs Road       SBaker@link.com (eMail)
+Arlington, Texas. TX 76005-6171 SJBaker1@airmail.net (Personal eMail)
+http://www.hti.com        http://web2.airmail.net/sjbaker1 (personal)
+
+** Beware of Geeks bearing GIF's. **
+
+
+-------------------------------------
+Please visit the FGFS web page:  http://www.menet.umn.edu/~curt/fgfs/
+For help on using this list (especially unsubscribing), send a message to
+"flight-gear-request@me.umn.edu" with a single line of text: "help".
+
+From sbaker@link.com  Mon Apr 27 23:45:25 1998
+X-VM-v5-Data: ([nil nil nil nil t nil nil nil nil]
+	["2532" "Mon" "27" "April" "1998" "23:43:38" "-0500" "Steve Baker" "sbaker@link.com" "" "58" "Re: texture coordinates" "^From:" nil nil "4" nil nil nil nil nil]
+	nil)
+X-VM-Message-Order:
+	(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+	 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
+	 31 32)
+X-VM-Summary-Format: "%n %*%a %-17.17F %-3.3m %2d %4l/%-5c %I\"%s\"\n"
+X-VM-Labels: ("r")
+X-VM-VHeader: ("Resent-" "From:" "Sender:" "To:" "Apparently-To:" "Cc:" "Subject:" "Date:") nil
+X-VM-Bookmark: 32
+Received: from lfkw10.bgm.link.com (bgm.link.com [130.210.2.10])
+	by meserv.me.umn.edu (8.8.8/8.8.8) with ESMTP id XAA19155
+	for ; Mon, 27 Apr 1998 23:45:24 -0500 (CDT)
+Received: from lechter.bgm.link.com (lechter.bgm.link.com [130.210.239.45])
+          by lfkw10.bgm.link.com (8.8.6/HTI-Hack-8.8.4) with SMTP
+	  id XAA03828 for ; Mon, 27 Apr 1998 23:44:53 -0500 (CDT)
+X-Sender: steve@lechter.bgm.link.com
+Reply-To: Steve Baker 
+In-Reply-To: <199804272123.QAA19688@kenai.me.umn.edu>
+Message-ID: 
+MIME-Version: 1.0
+Content-Type: TEXT/PLAIN; charset=US-ASCII
+From: Steve Baker 
+To: "Curtis L. Olson" 
+Subject: Re: texture coordinates
+Date: Mon, 27 Apr 1998 23:43:38 -0500 (CDT)
+
+On Mon, 27 Apr 1998, Curtis L. Olson wrote:
+
+> I just thought I'd fire off a quick texture coordinate question while
+> things were fresh on my mind.  I was doing the quick hack of texture
+> coordinate = (lon, lat) * CONSTANT.  I'm using a value of 128.0 for
+> the constant, lat/lon are in degrees.  This is giving me a lot of
+> "swimming" of the textures, where each frame the texture gets aligned
+> differently.  I'm thinking that 128 * 180 = 23040 which isn't that big
+> of a number.
+> 
+> So then before "clicking the proverbial send button" I decided to
+> fmod() the result with something smaller like 10.0 and now everything
+> seems to work pretty well.
+> 
+> Does this all sound reasonable?
+
+Yes - regrettably, it does.
+
+Most OpenGL implementations (or any 3D API for that matter) have
+serious problems with texture precision when the numbers get
+large.
+
+As you must have realised, you really don't need all those large
+integer parts - all that really matters is the delta.
+
+I think the best thing to do is to use a different constant
+for lat and long (v.important near the poles), and to compute
+that "constant" for each terrain tile such as to get an integer
+number of map repeats across the tile - keeping the actual size
+of each texel reasonably close to what it was designed to be.
+That ensures that adjacent tiles will match up most of the time
+- and it will minimise the number of texture seams you get. The
+coordinates within each tile should be as small as possible -
+take the south-west corner of each tile as (0,0) in texture space.
+
+I don't know of any really solid ways to avoid *any* texture
+seams. It is after all a topological impossibility to tile
+a sphere with equal sized squares without getting seams - 
+and the alternative is to distort the textures very badly
+towards the poles - and that sucks even more than the
+seams IMHO.
+
+I had a plan once to tile the planet with a particular
+grid spacing for each major continent - with the texture
+seams appearing exactly at the Suez canal, Panama canal,
+Straits of Gibralta...etc.  I now believe that to be hard
+to implement, and it still causes far too much distortion
+in the larger continents.
+
+Even if I could have made *that* work - there would still
+be the problem of texturing the oceans.
+
+In the end - I think seams are inevitable. (sniffle, sob)
+
+Steve Baker                (817)619-8776 (Vox/Vox-Mail)
+Raytheon Systems Inc.      (817)619-4028 (Fax)
+Work: SBaker@link.com      http://www.hti.com
+Home: SJBaker1@airmail.net http://web2.airmail.net/sjbaker1
+
+From sbaker@link.com  Mon May  4 07:42:43 1998
+X-VM-v5-Data: ([nil nil nil nil t nil nil nil nil]
+	["3088" "Mon" "4" "May" "1998" "07:40:58" "-0500" "Steve Baker" "sbaker@link.com" "" "75" "Re: texture coordinates" "^From:" nil nil "5" nil nil nil nil nil]
+	nil)
+Received: from lfkw10.bgm.link.com (bgm.link.com [130.210.2.10])
+	by meserv.me.umn.edu (8.8.8/8.8.8) with ESMTP id HAA28780
+	for ; Mon, 4 May 1998 07:42:42 -0500 (CDT)
+Received: from sutcliffe.bgm.link.com (sutcliffe.bgm.link.com [130.210.236.18])
+          by lfkw10.bgm.link.com (8.8.6/HTI-Hack-8.8.4) with SMTP
+	  id HAA08974 for ; Mon, 4 May 1998 07:42:10 -0500 (CDT)
+X-Sender: steve@sutcliffe.bgm.link.com
+Reply-To: Steve Baker 
+In-Reply-To: <199805011935.OAA12780@kenai.me.umn.edu>
+Message-ID: 
+MIME-Version: 1.0
+Content-Type: TEXT/PLAIN; charset=US-ASCII
+From: Steve Baker 
+To: "Curtis L. Olson" 
+Subject: Re: texture coordinates
+Date: Mon, 4 May 1998 07:40:58 -0500 (CDT)
+
+On Fri, 1 May 1998, Curtis L. Olson wrote:
+
+> (At this point I'm working in cartesian coordinates with all the
+> terrain points.)
+> 
+> I know a central point for a tile (average of min/max for x, y, z).
+> If I normalize (x, y, z) this gives me a nice normal.  So, I have a
+> nice point and a normal which is enough to define a plane that roughly
+> approximates the tile data points.  
+> 
+> Now, I could take each individual terrain point and project it onto
+> this plane.  This conceptually could be my texture coordinate.  But, I
+> would first have to rotate and translate the whole pile of projected
+> points so that they are at or near (0,0,0) at which point I could drop
+> the z dimension and (x,y) would be my real texture coordinate.
+> 
+> I'm pretty confident that I could do the math, but do you think it
+> would be worth the hassle?  It would all happen in the preprocessing
+> stage so I guess speed wouldn't be an issue.
+ 
+The problem is that you would end up with a seam in the texture at the
+edge of every terrain tile. Since your tiles are not exact squares,
+and (from what you seems to be saying), your texture *is* a square,
+there are bound to be differences in texture coordinates at the
+edges of adjacent tiles. Imagine taking a lot of square post-it notes
+(the textures) and sticking them onto a globe. Towards the poles,
+they would overlap more and more - and that is what would happen
+to your textures.
+
+Using the original lat/long as the texture coordinate eliminates
+the ugly seams.
+
+   S = lon / k1 ;
+   T = lat / k2 ;
+
+(k1 & k2 are constants).
+
+This squishes the texture around so it wraps neatly onto the spherical
+surface.
+
+However, there are two problems with this:
+
+* The texture coordinates get very big and that causes texture
+  swimming, jitter, etc.
+
+* The texture will now get long and thin near the poles.
+
+The way I get around these two problems is firstly to say:
+
+   S = ( lon - tile_origin_lon ) / k1
+   T = ( lat - tile_origin_lat ) / k2
+
+Now the texture coordinates are small - but the texture
+seams come back unless k1 and k2 are exact submultiples of
+a terrain tile size (expressed in degrees latitude/longitude).
+
+So, I set k1/k2 to the exact submultiple of a terrain tile
+size that comes closest to the ideal scale that I want for
+my textures (expressed in meters per map repeat). Since the
+size of a degree of longitude changes over the surface of
+the earth, k1 is no longer a constant. Whenever k2 changes,
+you get a texture seam that runs east-west across the terrain.
+This is unavoidable - but a lot better than having seams at
+the edges of every terrain tile.
+
+Hence, k1 will equal k2 at the equator and gradually go to
+zero at the poles. It's easiest to take the longitudinal
+size of the terrain tile half way up the tile (rather than
+at the top or bottom edge) to avoid a divide by zero error
+at either the north or south pole.
+
+Steve Baker                (817)619-8776 (Vox/Vox-Mail)
+Raytheon Systems Inc.      (817)619-4028 (Fax)
+Work: SBaker@link.com      http://www.hti.com
+Home: SJBaker1@airmail.net http://web2.airmail.net/sjbaker1
+
+From owner-fgfs-devel@flightgear.org  Tue Sep 22 16:24:52 1998
+X-VM-v5-Data: ([nil nil nil nil nil nil nil nil nil]
+	["1870" "Tue" "22" "September" "1998" "16:23:23" "-0500" "Steve Baker" "sbaker@link.com" nil "43" "Re: [FGFS-Devel] vegetation / land use" "^From:" nil nil "9" nil nil nil nil nil]
+	nil)
+Received: from mailhub.woodsoup.org (IDENT:root@anduin.physics.iastate.edu [129.186.82.1])
+	by meserv.me.umn.edu (8.9.1a/8.9.1) with ESMTP id QAA05981
+	for ; Tue, 22 Sep 1998 16:24:52 -0500 (CDT)
+Received: from majordom by mailhub.woodsoup.org with local (Exim 1.92 #1)
+	for fgfs-devel-outgoing@flightgear.org
+	id 0zLZvM-0000ZG-00; Tue, 22 Sep 1998 16:24:40 -0500
+Received: from bgm.link.com ([130.210.2.10] helo=lfkw10.bgm.link.com)
+	by mailhub.woodsoup.org with esmtp (Exim 1.92 #1)
+	for fgfs-devel@flightgear.org
+	id 0zLZvK-0000ZA-00; Tue, 22 Sep 1998 16:24:38 -0500
+Received: from samantha.bgm.link.com (samantha.bgm.link.com [130.210.65.19])
+          by lfkw10.bgm.link.com (8.8.6/RSC-RTI-1.0) with SMTP
+	  id QAA23764 for ; Tue, 22 Sep 1998 16:24:08 -0500 (CDT)
+X-Sender: steve@samantha.bgm.link.com
+In-Reply-To: <3607FBD8.58FC@mars.ark.com>
+Message-ID: 
+MIME-Version: 1.0
+Content-Type: TEXT/PLAIN; charset=US-ASCII
+Precedence: bulk
+Reply-To: fgfs-devel@flightgear.org
+From: Steve Baker 
+Sender: owner-fgfs-devel@flightgear.org
+To: fgfs-devel@flightgear.org
+Subject: Re: [FGFS-Devel] vegetation / land use
+Date: Tue, 22 Sep 1998 16:23:23 -0500 (CDT)
+
+On Tue, 22 Sep 1998, Eric Mitchell wrote:
+
+> Sounds good. Can you tell me the (rough) dimensions of a single texture
+> square when it's rendered in FG? I'll need to know that to make the farm
+> fields look right.
+ 
+I think we should be prepared to vary the size of the texels on the ground
+to fit the style of the map. (The technical term for "the size of the
+texels on the ground" is the "lambda" of the texture - measured in
+meters-per-texel).
+
+Also, it's going to be hard to pick a single lambda that looks good at
+all altitudes. There isn't a good solution for that - with big SGI machines,
+you can use a feature called "detail texture" - but there don't seem to
+be any efforts to implement that on PC boxes yet.
+
+Maybe we'll make use of the upcoming multitexture hardware (if 3Dfx
+and nVidia solve their lawsuits...) to apply two or more textures
+at differing lambdas.
+
+I think the preson who paints the map should have some idea of what
+altitudes it's going to look good at - and hence should be able to
+specify the lambda to the terrain generator software on a per-map
+basis.
+
+Clearly, for field patterns, we need a fairly small lambda to make it
+possible to see nice sharp field edges with the odd road or boundary
+hedge/treeline running between them. This makes the texture fairly
+repetitious, but for field patterns that may not be too bad.
+
+For fuzzier 'natural' textures, you can use a larger lambda's resulting
+in less obvious repetition.
+
+Steve Baker                (817)619-2657 (Vox/Vox-Mail)
+Raytheon Systems Inc.      (817)619-4028 (Fax)
+Work: SBaker@link.com      http://www.hti.com
+Home: SJBaker1@airmail.net http://web2.airmail.net/sjbaker1
+
+
+Please visit the FGFS web page:  http://www.flightgear.org
+For help on using this list (especially unsubscribing), send a message to
+"fgfs-devel-request@flightgear.org" with a single line of text: "help".
+
+From owner-fgfs-devel@flightgear.org  Tue Sep 22 16:28:28 1998
+X-VM-v5-Data: ([nil nil nil nil nil nil nil nil nil]
+	["1472" "Tue" "22" "September" "1998" "16:26:37" "-0500" "Steve Baker" "sbaker@link.com" nil "34" "Re: [FGFS-Devel] vegetation / land use" "^From:" nil nil "9" nil nil nil nil nil]
+	nil)
+Received: from mailhub.woodsoup.org (IDENT:root@anduin.physics.iastate.edu [129.186.82.1])
+	by meserv.me.umn.edu (8.9.1a/8.9.1) with ESMTP id QAA06106
+	for ; Tue, 22 Sep 1998 16:28:27 -0500 (CDT)
+Received: from majordom by mailhub.woodsoup.org with local (Exim 1.92 #1)
+	for fgfs-devel-outgoing@flightgear.org
+	id 0zLZyX-0000aT-00; Tue, 22 Sep 1998 16:27:57 -0500
+Received: from bgm.link.com ([130.210.2.10] helo=lfkw10.bgm.link.com)
+	by mailhub.woodsoup.org with esmtp (Exim 1.92 #1)
+	for fgfs-devel@flightgear.org
+	id 0zLZyW-0000a5-00; Tue, 22 Sep 1998 16:27:56 -0500
+Received: from samantha.bgm.link.com (samantha.bgm.link.com [130.210.65.19])
+          by lfkw10.bgm.link.com (8.8.6/RSC-RTI-1.0) with SMTP
+	  id QAA23910 for ; Tue, 22 Sep 1998 16:27:21 -0500 (CDT)
+X-Sender: steve@samantha.bgm.link.com
+In-Reply-To: <13831.64964.272599.402309@kenai.me.umn.edu>
+Message-ID: 
+MIME-Version: 1.0
+Content-Type: TEXT/PLAIN; charset=US-ASCII
+Precedence: bulk
+Reply-To: fgfs-devel@flightgear.org
+From: Steve Baker 
+Sender: owner-fgfs-devel@flightgear.org
+To: fgfs-devel@flightgear.org
+Subject: Re: [FGFS-Devel] vegetation / land use
+Date: Tue, 22 Sep 1998 16:26:37 -0500 (CDT)
+
+On Tue, 22 Sep 1998, Curtis L. Olson wrote:
+
+> Eric Mitchell writes:
+> > Sounds good. Can you tell me the (rough) dimensions of a single texture
+> > square when it's rendered in FG? I'll need to know that to make the farm
+> > fields look right.
+> 
+> This is a tough one I haven't really ironed out yet.  We can easily
+> change this in the code to suit our needs.  3dfx imposes a 256x256
+> limitation on texture dimensions.  What amount of ground could we
+> reasonably cover with a texture of this resolution.  Obviously this is
+> trade off city here ... :-(
+ 
+Probably ought to paint the maps at better than 256x256 resolution - 3Dfx
+won't be the norm forever - and there is a definite trend to having much
+bigger maps - and more of them.
+
+All portable OpenGL code should use the "PROXY" texture trick to figure
+out if the texture is going to fit and automagically reduce the size
+(by dropping out the higher level MIPmaps) on less capable hardware.
+
+This will make the textures look fuzzier on 3Dfx hardware than on others,
+especially at low altitudes.
+
+
+Steve Baker                (817)619-2657 (Vox/Vox-Mail)
+Raytheon Systems Inc.      (817)619-4028 (Fax)
+Work: SBaker@link.com      http://www.hti.com
+Home: SJBaker1@airmail.net http://web2.airmail.net/sjbaker1
+
+
+Please visit the FGFS web page:  http://www.flightgear.org
+For help on using this list (especially unsubscribing), send a message to
+"fgfs-devel-request@flightgear.org" with a single line of text: "help".
+
+From mschaefe@MIT.EDU  Wed Sep 23 12:33:42 1998
+X-VM-v5-Data: ([nil nil nil nil nil nil nil nil nil]
+	["1083" "Wed" "23" "September" "1998" "13:30:37" "-0400" "mschaefe@MIT.EDU" "mschaefe@MIT.EDU" nil "34" "Re: [FGFS-Devel] vegitation / land use" "^From:" nil nil "9" nil nil nil nil nil]
+	nil)
+Received: from MIT.EDU (PACIFIC-CARRIER-ANNEX.MIT.EDU [18.69.0.28])
+	by meserv.me.umn.edu (8.9.1a/8.9.1) with SMTP id MAA22241
+	for ; Wed, 23 Sep 1998 12:33:42 -0500 (CDT)
+Received: from MIT.MIT.EDU by MIT.EDU with SMTP
+	id AA17918; Wed, 23 Sep 98 13:33:41 EDT
+Received: from LFM-IDAHO.MIT.EDU by MIT.MIT.EDU (5.61/4.7) id AA06057; Wed, 23 Sep 98 13:33:41 EDT
+Message-Id: <3.0.32.19980923133036.008fc440@po10.mit.edu>
+X-Sender: mschaefe@po10.mit.edu
+X-Mailer: Windows Eudora Pro Version 3.0 (32)
+Mime-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
+From: mschaefe@MIT.EDU
+To: "Curtis L. Olson" 
+Subject: Re: [FGFS-Devel] vegitation / land use
+Date: Wed, 23 Sep 1998 13:30:37 -0400
+
+	Curt,
+
+	I believe all of that data is contained on the 1:2mil CD, which I know to
+be in lat/long format.  It's FTP'able, or you can buy the CD for $20, with
+data from all the states (I'm not sure if AK and HI are included on 2mil).
+	
+	It doesn't, as far as I know, have building/smokestack/... data on the
+2mil CD.  It think that's much too detailed.
+
+Mark
+P.S. Check out
+ftp://mapping.usgs.gov/pub/ti/DLG/2mdlgguide/1994_Revision/2mdug95.txt
+for more info on what is contained on the CD.  The site has more
+information on how to decode the data as well.
+
+>Mark,
+>
+>Is there lake, road, river, city outline data available on line that
+>uses lat/lon coordinates?  The data sets I've seen have all been
+>with the funky projected coordinate system relative to some reference
+>point.
+>
+>What other things can you get out of this?  Is there smoke stack,
+>powerline, tall building data available in these too?
+>
+>Thanks,
+>
+>Curt.
+>-- 
+>Curtis Olson                        University of MN, ME Dept.
+>curt@me.umn.edu                     
+>http://www.menet.umn.edu/~curt      Try Linux!
+>
+
diff --git a/Hints/tile-gaps b/Hints/tile-gaps
new file mode 100644
index 000000000..e0d743350
--- /dev/null
+++ b/Hints/tile-gaps
@@ -0,0 +1,72 @@
+From sbaker@link.com  Tue May 26 07:55:03 1998
+X-VM-v5-Data: ([nil nil nil nil nil nil nil nil nil]
+	["1540" "Tue" "26" "May" "1998" "07:54:04" "-0500" "Steve Baker" "sbaker@link.com" nil "40" "Re: Question" "^From:" nil nil "5" nil nil nil nil nil]
+	nil)
+X-VM-Last-Modified: (13793 54640 649954)
+X-VM-IMAP-Retrieved: nil
+X-VM-POP-Retrieved: nil
+X-VM-Message-Order:
+	(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+	 16 17 18 19 20 21 22 23 24 25 26)
+X-VM-Summary-Format: "%n %*%a %-17.17F %-3.3m %2d %4l/%-5c %I\"%s\"\n"
+X-VM-Labels: ("r")
+X-VM-VHeader: ("Resent-" "From:" "Sender:" "To:" "Apparently-To:" "Cc:" "Subject:" "Date:") nil
+X-VM-Bookmark: 20
+Received: from lfkw10.bgm.link.com (bgm.link.com [130.210.2.10])
+	by meserv.me.umn.edu (8.8.8/8.8.8) with ESMTP id HAA28563
+	for ; Tue, 26 May 1998 07:55:02 -0500 (CDT)
+Received: from borgus.bgm.link.com (borgus.bgm.link.com [130.210.236.13])
+          by lfkw10.bgm.link.com (8.8.6/HTI-Hack-8.8.4) with SMTP
+	  id HAA00068 for ; Tue, 26 May 1998 07:54:55 -0500 (CDT)
+X-Sender: steve@borgus.bgm.link.com
+Reply-To: Steve Baker 
+In-Reply-To: <199805230429.XAA10965@kenai.me.umn.edu>
+Message-ID: 
+MIME-Version: 1.0
+Content-Type: TEXT/PLAIN; charset=US-ASCII
+From: Steve Baker 
+To: "Curtis L. Olson" 
+Subject: Re: Question
+Date: Tue, 26 May 1998 07:54:04 -0500 (CDT)
+
+On Fri, 22 May 1998, Curtis L. Olson wrote:
+
+> I'm running into floating point problems again where my scenery tiles
+> sometimes have a pixel gap between them.  I was wondering if you had
+> any ideas ...
+ 
+It's a problem that plagues us too.
+
+I can't say that I have a magic solution.
+
+One thing I have *considered* is to do everything in integers (for
+the terrain skin at least).
+
+This sounds counter-intuitive - but the source data for your
+terrain is certainly not accurate to better than a meter - and
+integers have the huge advantage that they don't suffer from
+roundoff error providing all you do is add and subtract them.
+
+However, I havn't had the nerve to try this yet - right now, we
+kludge the edges of each terrain tile to make it a teeny-tiny bit
+too big. The resulting overlap is very small - but enough to get
+rid of the cracks.
+
+> Anyways, what this forces me to do is for each tile I must
+> glTranslate() by center_of_tile_to_be_drawn - center_of_tile_I'm_in.
+> But, up until this point everything was done in double's so I was
+> hoping the final translate about which is on the order of 20,000 -
+> 30,000 meters would be ok.
+ 
+But that translate could be done in integer meters. 
+
+> Anyways, I just thought I'd see if you had any brilliant thoughts on
+> the subject.
+
+Nope - it's a continual problem for me too.
+
+Steve Baker                (817)619-8776 (Vox/Vox-Mail)
+Raytheon Systems Inc.      (817)619-4028 (Fax)
+Work: SBaker@link.com      http://www.hti.com
+Home: SJBaker1@airmail.net http://web2.airmail.net/sjbaker1
+
diff --git a/Hints/timezone b/Hints/timezone
new file mode 100644
index 000000000..f17fac9b0
--- /dev/null
+++ b/Hints/timezone
@@ -0,0 +1,67 @@
+>-----Original Message-----
+>From: Antoine Leca [mailto:Antoine.Leca@renault.fr] 
+>Sent: Thursday, April 01, 1999 4:51 AM
+>To: Lee Geoff
+>Cc: tz@elsie.nci.nih.gov
+>Subject: Re: storing timestamp data
+>
+>
+>Lee Geoff wrote:
+>> 
+>> I'm interested in storing date/time data in Ingres
+>> databases which are running on Unix servers. We are 
+>recording timed events
+>> on Unix servers as well as Windows 3.1 and NT PCs.  I have 
+>had problems with
+>> the apparent miss-handling of data when viewed before or after a DST
+>> transition.
+>
+>We had this kind of problems when setting up a Internet 
+>standard for exchanging
+>calendars, agendas and schedules (it ends up in RFC2245, if you mind).
+>
+>The net result was: either use UTC, or local time + offset from UTC.
+>Do not use local time without UTC offset, as no reliable method can be
+>set up to correctly retrieve the exact point of time 
+>afterwards (as you may
+>have experienced).
+>
+>Using UTC times is native on Unix and NT (AFAIK), so this is 
+>the basic choice
+>there.  The problem comes with Windows non-NT PCs, since they 
+>run local clocks.
+>IMHO, and to be consistent with the above, no data that are 
+>not tagged with
+>the (best approximation of) UTC offset should leave the PC.
+>
+>Traditional way of finding the best approximation are (in order):
+> - search for an (up to date) Olson's package to interpret the 
+>information,
+>  perhaps by searching $(DJDIR)/zoneinfo/localtime in addition to 
+>  $(TZDIR)/localtime
+> - if running on Windows 95/98, search the information in the registry
+> - setting a mechanism dedicated to it (but it will end with one more
+>  mechanism, which tends to upset users)
+> - ask the TZ environment variable
+> - search the information on related softwares that may be 
+>present on the PCs
+>  (examples are mailing systems, e.g. Notes, and IP 
+>connectivity packages)
+>
+>Do not use:
+> - tzset and timezone, as it defaults to PST8PDT or EST5EDT on 
+>most compilers,
+>  without being reliably accurate on most workstations by lack of TZ
+> - if your users are not Americans, do not rely on US-based 
+>rules; they are
+>  almost correct for Europeans (except that for example, this 
+>week, my UTC
+>  offset is wrong because my mail software is brocken on this 
+>respect...)
+>
+>
+>Hope it helps,
+>
+>Antoine
+>
+>
diff --git a/Hints/view-frustum-culling b/Hints/view-frustum-culling
new file mode 100644
index 000000000..3c7b90bc8
--- /dev/null
+++ b/Hints/view-frustum-culling
@@ -0,0 +1,986 @@
+From sbaker@link.com  Thu Jan 29 23:16:07 1998
+X-VM-v5-Data: ([nil nil nil nil t nil nil nil nil]
+	["5377" "Thu" "29" "January" "1998" "23:16:36" "-0600" "Steve Baker" "sbaker@link.com" "" "139" "Re: View frustum culling" "^From:" nil nil "1" nil nil nil nil nil]
+	nil)
+Received: from lfkw10.bgm.link.com (bgm.link.com [130.210.2.10])
+	by meserv.me.umn.edu (8.8.8/8.8.6) with ESMTP id XAA03024
+	for ; Thu, 29 Jan 1998 23:16:06 -0600 (CST)
+Received: from lechter.bgm.link.com (lechter.bgm.link.com [130.210.239.45])
+          by lfkw10.bgm.link.com (8.8.6/HTI-Hack-8.8.4) with SMTP
+	  id XAA18220 for ; Thu, 29 Jan 1998 23:15:35 -0600 (CST)
+X-Sender: steve@lechter.bgm.link.com
+Reply-To: Steve Baker 
+In-Reply-To: <199801292145.PAA04212@kenai.me.umn.edu>
+Message-ID: 
+MIME-Version: 1.0
+Content-Type: TEXT/PLAIN; charset=US-ASCII
+From: Steve Baker 
+To: "Curtis L. Olson" 
+Subject: Re: View frustum culling
+Date: Thu, 29 Jan 1998 23:16:36 -0600 (CST)
+
+On Thu, 29 Jan 1998, Curtis L. Olson wrote:
+
+> Questions ...
+> 
+> Let's say I know the following:
+> 
+> Eye pt. = (0, 0, 0)
+> "look at" vector
+> "view up" vector
+> field of view angle
+> Assume a "square" view volume cross section (i.e. the far clip plane
+> would be a square)
+ 
+(That is almost never the case since you want the image to fit the
+screen shape - but OK - for argument's sake, same HFOV as VFOV).
+
+> I can calcuation the near and far clip planes pretty easily with this
+> info.
+ 
+Assuming you know the near and far clip ranges - yes.
+
+> Now, to calculate the left and right planes I could rotate the look at
+> vector about the view up vector by -1/2 * fov and +1/2 * fov
+> respectively.  The view up vector already lies in both these planes,
+> so then I'd have two vectors in each plane and then I could calculate
+> the normals to get the equations of these planes
+ 
+Yes, that would work.
+
+> Then to calculate the top and bottom planes I could rotate the view up
+> vector by 90 degrees about the look at vector to get a vector in both
+> these planes, then I could rotate the look at vector about this new
+> vector by -1/2 * fov and +1/2 * fov to get the second vector in each
+> of these planes, and crunch the math just like I did for the left and
+> right planes.
+ 
+...or you could just rotate the left or right plane normal by 90 degrees
+about the lookat vector (but only for your hypothetical square FOV).
+
+> Does this sound reasonable, or am I missing some obvious tricks?
+ 
+It's *reasonable* if you want the view planes in the coordinate system
+of the world. However, I'd argue about that premise.
+
+I did the opposite - I keep the view frustum in the coordinate system
+of the eye and rotate the world into that coordinate system. This
+costs at most one extra transform (by the inverse of the eye-rel-world
+matrix) per frame (at the root of the database tree).
+
+The advantages are *huge* in the clipping code (which is where I
+assume you are going with this question) since the plane equations
+for the near and far planes (in eye coordinates) are trivial:
+
+    General Equation of a Plane:
+
+              Ax + By + Cz + D == 0
+
+    Far clip plane:
+
+              A == 0 ;
+              B == 0 ;
+              C == -1 ;
+              D == far_clip_range ;
+
+    Near clip plane:
+
+              A == 0 ;
+              B == 0 ;
+              C == 1 ;
+              D == -near_clip_range ;
+
+Also, since the left and right clip planes are now vertical, we
+know that B==0 and for the top and bottom planes, A==0.
+
+In addition, because of symmetry about the Z axis, the A of
+the left plane is equal to -A for the right, and the B of
+the top plane is equal to -B of the bottom.
+
+Furthermore, since D is just the distance of the closest
+point of the plane to the origin - and all four planes
+go through the eyepoint - and that *is* the origin - that
+means that the 'D' component of all four edge equations is
+always zero.
+
+Notice that since the frustum is in eye coordinates,
+there is no need to worry about lookat or viewup vectors
+since these are 0,0,1 and 0,1,0 respectively - and the
+eye point is always at 0,0,0 by definition.  This also
+means that you only need to calculate those plane equations
+once - rather than once per frame as with your scheme.
+
+When you come to ask the question: "Is this bounding sphere
+cleanly inside the frustum, cleanly outside the frustum or
+(annoyingly) straddling it?", you will want to insert the
+x,y,z of the center of the sphere (relative to the eye
+in the 'eye' coordinate system) into each of the
+six plane equations in turn to compute the distance from the
+sphere center to the plane - and compare that to the radius
+of the sphere. When you write out the math for this, using
+the full plane equations (as you would have to do with your
+scheme), you find that all those zeros and symmetry effects
+result in some pretty amazing optimisations.
+
+Additionally, this is the OpenGL way. You stuff your frustum
+matrix into the 'PROJECTION_MATRIX', put the inverse of
+your eyepoint transform into the MODELVIEW_MATRIX and proceed
+to push/multiply/pop the transforms of each of the models onto
+that same matrix. Notice that the frustum is never transformed
+into world space.
+
+I suggest you go back and re-read the last L-O-N-G email I
+sent about clipping, I explain my suggested method there
+in more detail.
+
+Note that I'm not saying that what you propose is wrong -
+just that IMHO (and *only* IMHO), my way is going to be
+a lot simpler and cheaper to implement. However, there may
+be other reasons to want to do it your way.
+
+The complexity of MANY 3D graphics problems often depends
+critically on your choice of coordinate system. For
+clipping, doing the math in the eye coordinate system
+results in a *tiny* amount of math per sphere tested.
+
+If you ever need to do lighting calculations, then
+carrying them out in a coordinate system with the
+light source at the origin makes life a gazillion
+times easier too. The same kinds of things will also
+crop up in collision detection as well.
+
+
+Steve Baker                     817-619-8776 (Vox/Vox-Mail)
+Raytheon Systems Inc.           817-619-4028 (Fax)
+2200 Arlington Downs Road       SBaker@link.com (eMail)
+Arlington, Texas. TX 76005-6171 SJBaker1@airmail.net (Personal eMail)
+http://www.hti.com        http://web2.airmail.net/sjbaker1 (personal)
+
+** Beware of Geeks bearing GIF's. **
+
+
+From sbaker@link.com  Fri Jan 30 14:08:05 1998
+X-VM-v5-Data: ([nil nil nil nil t nil nil nil nil]
+	["4594" "Fri" "30" "January" "1998" "14:08:27" "-0600" "Steve Baker" "sbaker@link.com" "" "120" "Re: View frustum culling" "^From:" nil nil "1" nil nil nil nil nil]
+	nil)
+Received: from lfkw10.bgm.link.com (bgm.link.com [130.210.2.10])
+	by meserv.me.umn.edu (8.8.8/8.8.6) with ESMTP id OAA21393
+	for ; Fri, 30 Jan 1998 14:08:03 -0600 (CST)
+Received: from lechter.bgm.link.com (lechter.bgm.link.com [130.210.239.45])
+          by lfkw10.bgm.link.com (8.8.6/HTI-Hack-8.8.4) with SMTP
+	  id OAA10811 for ; Fri, 30 Jan 1998 14:07:27 -0600 (CST)
+X-Sender: steve@lechter.bgm.link.com
+Reply-To: Steve Baker 
+In-Reply-To: <199801301948.NAA25718@kenai.me.umn.edu>
+Message-ID: 
+MIME-Version: 1.0
+Content-Type: TEXT/PLAIN; charset=US-ASCII
+From: Steve Baker 
+To: "Curtis L. Olson" 
+Subject: Re: View frustum culling
+Date: Fri, 30 Jan 1998 14:08:27 -0600 (CST)
+
+On Fri, 30 Jan 1998, Curtis L. Olson wrote:
+
+> Steve Baker writes:
+> > I did the opposite - I keep the view frustum in the coordinate
+> > system of the eye and rotate the world into that coordinate
+> > system. This costs at most one extra transform (by the inverse of
+> > the eye-rel-world matrix) per frame (at the root of the database
+> > tree).
+> >
+> > I suggest you go back and re-read the last L-O-N-G email I sent
+> > about clipping, I explain my suggested method there in more detail.
+> 
+> Yes I have that in front of me.  I guess it wasn't clear to me that
+> you were using this greatly simplifed view frustum specially placed in
+> eye coordinates.
+ 
+That's the key to doing this stuff *quickly*.
+
+> > The complexity of MANY 3D graphics problems often depends critically
+> > on your choice of coordinate system. For clipping, doing the math in
+> > the eye coordinate system results in a *tiny* amount of math per
+> > sphere tested.
+> 
+> Yes ... your description all makes sense and looks like it makes view
+> frustum culling very simple to implement.
+> 
+> Ok, so now I'm going to try to zero in a bit more on the source of my
+> confusion, which involves getting from my world to your eye
+> coordinates.
+ 
+Let's adopt a naming convention for matrices here:
+
+    A_rel_B
+
+      means the matrix that positions objects in A relative to
+      the object B.
+
+Some facts:
+
+    B_rel_A is just the inverse of A_rel_B.
+
+    A_rel_B * B_rel_C == A_rel_C
+
+Hence: (for a flat-earth world - just for the moment)
+
+    If the eyepoint is 10km east of the origin (eyepoint.x == 10,000)
+    then:
+
+    eye_rel_world is a matrix that translates by 10000m in the X
+    direction.
+
+    world_rel_eye is the inverse of eye_rel_world - which in this
+    case is just a matrix that translates by -10000m in X.
+
+Taking the inverse of a general matrix isn't nice - but for simple
+rotate/translate matrices it isn't too bad - and you only do it
+once per frame anyway.
+
+> Lets say that I have a bunch of scenery tiles that are properly
+> oriented, but translated to near (0, 0, 0) to avoid problems with
+> "float" precision.
+> 
+> I assume based on your previous message that you define your view
+> frustum once at the beginning of your program in eye coordinates to
+> simplify all this math.
+
+Yep - you *might* want to allow the user to change it sometimes - but
+basically, it's always the same number unless you resize the window,
+zoom the image, etc.
+
+> This moves the "hard" part to generating a transformation matrix that
+> maps world coordinates into eye coordinates.
+ 
+But world_rel_eye is just the inverse of eye_rel_world - and that's
+just the rotation/translation of the eyepoint relative to some
+arbitary point.
+
+> You say ...
+> 
+> > Additionally, this is the OpenGL way. You stuff your frustum matrix
+> > into the 'PROJECTION_MATRIX', put the inverse of your eyepoint
+> > transform into the MODELVIEW_MATRIX and proceed to push/multiply/pop
+> > the transforms of each of the models onto that same matrix. Notice
+> > that the frustum is never transformed into world space.
+> 
+> Ok, so does this mean that every iteration I have to generate the
+> world -> eye transformation matrix by hand ... i.e. calculate the
+> first translation matrix, calculate the rotation matrix, calculate the
+> second translation matrix, calculate the shear matrix, calculate the
+> scaling matrix, and then combine all these together, then invert it
+> and stuff it on the MODELVIEW stack?
+
+Yes - except that the eye_rel_world isn't usually scaled or sheared or
+anything. Just heading/pitch/roll/x/y/z.
+
+> Or is there a way to get OpenGL to do this work for me?
+
+No - not really - there is no glInvertMatrix (AFAIK) - and in any
+case, on machines with geometry accelleration doing a glGetMatrix
+is *death* to performance.
+
+>  If not, can I at least use OpenGL's rotates,
+> and transformations to avoid spending two weeks debugging picky math
+> routines?
+ 
+No - don't debug new math routines either - let me find some out on the
+web for you.  I'm sure I know of a good set. I'll email you from home
+tonight - I'm a bit busy right now.
+
+Flight Gear will definitely need a good, robust set of math routines -
+better to have a solid library than to try to kludge something in OpenGL.
+
+Steve Baker                     817-619-8776 (Vox/Vox-Mail)
+Raytheon Systems Inc.           817-619-4028 (Fax)
+2200 Arlington Downs Road       SBaker@link.com (eMail)
+Arlington, Texas. TX 76005-6171 SJBaker1@airmail.net (Personal eMail)
+http://www.hti.com        http://web2.airmail.net/sjbaker1 (personal)
+
+** Beware of Geeks bearing GIF's. **
+
+
+From sbaker@link.com  Fri Jan 30 22:51:59 1998
+X-VM-v5-Data: ([nil nil nil nil nil nil nil nil nil]
+	["4301" "Fri" "30" "January" "1998" "22:52:31" "-0600" "Steve Baker" "sbaker@link.com" nil "103" "Re: View frustum culling" "^From:" nil nil "1" nil nil nil nil nil]
+	nil)
+Received: from lfkw10.bgm.link.com (bgm.link.com [130.210.2.10])
+	by meserv.me.umn.edu (8.8.8/8.8.6) with ESMTP id WAA03743
+	for ; Fri, 30 Jan 1998 22:51:58 -0600 (CST)
+Received: from lechter.bgm.link.com (lechter.bgm.link.com [130.210.239.45])
+          by lfkw10.bgm.link.com (8.8.6/HTI-Hack-8.8.4) with SMTP
+	  id WAA08997 for ; Fri, 30 Jan 1998 22:51:26 -0600 (CST)
+X-Sender: steve@lechter.bgm.link.com
+Reply-To: Steve Baker 
+In-Reply-To: <199801302035.OAA26234@kenai.me.umn.edu>
+Message-ID: 
+MIME-Version: 1.0
+Content-Type: TEXT/PLAIN; charset=US-ASCII
+From: Steve Baker 
+To: "Curtis L. Olson" 
+Subject: Re: View frustum culling
+Date: Fri, 30 Jan 1998 22:52:31 -0600 (CST)
+
+On Fri, 30 Jan 1998, Curtis L. Olson wrote:
+
+> Steve Baker writes:
+> > But world_rel_eye is just the inverse of eye_rel_world - and that's
+> > just the rotation/translation of the eyepoint relative to some
+> > arbitary point.
+> 
+> Ok, from what you are saying, if I think about it, I've probably
+> already got a suitable matrix or something close to it laying around
+> someplace.  I have a matrix that does the proper rotations to align
+> world coordinates with the local "up" for the aircraft.  I'd probably
+> just need to pre-multiply the proper translation matrix with that
+> rotate matrix, then invert it, and stuff it onto the MODELVIEW stack.
+ 
+You *must* be doing the right thing at the start of the frame - or
+how else would the graphics be coming out right? (Oh - unless you
+are using that weird OpenGL 'lookat' function or something).
+
+> > No - don't debug new math routines either - let me find some out on
+> > the web for you.  I'm sure I know of a good set. I'll email you from
+> > home tonight - I'm a bit busy right now.
+> >
+> > Flight Gear will definitely need a good, robust set of math routines
+> > - better to have a solid library than to try to kludge something in
+> > OpenGL.
+> 
+> You may scream when you hear this, or not, I'm not sure ... but I've
+> been using the matrix and vector routines from SRGP and SPHIGS.
+ 
+I don't know these - but it's hard to imagine how anyone could screw
+up the implementation of a matrix math library - so they are probably OK.
+
+I have accumulated by own matrix/quaternion library that I've used
+for the last 10 years - every new project starts with it - and adds to
+it, so now I don't even have to think about how to drive it. That's
+a very liberating thing.
+
+Another good source for a matrix lib is inside the Mesa sources. These
+are particularly interesting because the latest Beta release has
+super-optimised machine code for Intel CPU's under Linux as a conditional
+compiled option.  You'd need to copy and change the names of the routines
+though to avoid the names clashing with the real Mesa routines.
+
+One *IMPORTANT* thing is that when you invert the eye_rel_world matrix
+to get world_rel_eye, don't use a general purpose matrix invert routine
+since those are *REALLY* inefficient bits of code for matrices that
+are guaranteed to be pure rotate/translate. Instead, just do this:
+
+  /*
+    This definition of a matrix is
+    easier to deal with than a float[16] -
+    but you can safely pass this kind
+    of matrix directly to OpenGL routines
+    like glMultMatrix and glLoadMatrix.
+  */
+
+  typedef float fgMat [ 4 ][ 4 ] ;
+   
+  /*
+    Transpose/Negate is a poor man's invert.
+    It can *only* be used when matrix is a
+    simple rotate-translate - but it's a
+    gazillion times faster than a full-blown
+    invert.
+  */
+   
+  void fgTransposeNegateMat( fgMat dst, fgMat src )
+  {
+    /* Transpose the 3x3 rotation sub-matrix */
+
+    dst[0][0] = src[0][0] ; dst[0][1] = src[1][0] ; dst[0][2] = src[2][0] ;
+    dst[1][0] = src[0][1] ; dst[1][1] = src[1][1] ; dst[1][2] = src[2][1] ;
+    dst[2][0] = src[0][2] ; dst[2][1] = src[1][2] ; dst[2][2] = src[2][2] ;
+
+    /* Negate the translate part */
+
+    dst[3][0] = -src[3][0] ; dst[3][1] = -src[3][1] ; dst[3][2] = -src[3][2] ;
+
+    /* Populate the rest */
+
+    dst[0][3] = dst[1][3] = dst[2][3] = 0.0f ; dst[3][3] = 1.0f ;
+  }
+
+> Debugging the low level routines, though, is sometimes the easy part,
+> debugging the usage of them is where it can often get hairy ... :-)
+ 
+I agree - matrices are truly horrible to get your head around. Have
+you looked into Quaternions yet?  They are v.interesting for the
+flight dynamics people because they don't suffer from 'gymbal lock'
+like H,P,R angles and are easier to renormalize than matrices.
+
+You don't want to use Quaternions for the main graphics code - but
+it's easy to form a Matrix from a Quaternion - and Quaternions are
+a much better way to represent rotation than the usual three angles.
+
+Steve Baker                     817-619-8776 (Vox/Vox-Mail)
+Raytheon Systems Inc.           817-619-4028 (Fax)
+2200 Arlington Downs Road       SBaker@link.com (eMail)
+Arlington, Texas. TX 76005-6171 SJBaker1@airmail.net (Personal eMail)
+http://www.hti.com        http://web2.airmail.net/sjbaker1 (personal)
+
+** Beware of Geeks bearing GIF's. **
+
+
+From owner-flight-gear@me.umn.edu  Tue May 19 07:45:59 1998
+X-VM-v5-Data: ([nil nil nil nil nil nil nil nil nil]
+	["4413" "Tue" "19" "May" "1998" "07:44:47" "-0500" "Steve Baker" "sbaker@link.com" nil "116" "Re: [FGFS] View Frustum Culling" "^From:" nil nil "5" nil nil nil nil nil]
+	nil)
+Received: (from majordom@localhost)
+	by meserv.me.umn.edu (8.8.8/8.8.8) id HAA04944
+	for flight-gear-outgoing; Tue, 19 May 1998 07:45:59 -0500 (CDT)
+X-Authentication-Warning: meserv.me.umn.edu: majordom set sender to owner-flight-gear@me.umn.edu using -f
+Received: from lfkw10.bgm.link.com (bgm.link.com [130.210.2.10])
+	by meserv.me.umn.edu (8.8.8/8.8.8) with ESMTP id HAA04940
+	for ; Tue, 19 May 1998 07:45:55 -0500 (CDT)
+Received: from borgus.bgm.link.com (borgus.bgm.link.com [130.210.236.13])
+          by lfkw10.bgm.link.com (8.8.6/HTI-Hack-8.8.4) with SMTP
+	  id HAA29586 for ; Tue, 19 May 1998 07:45:23 -0500 (CDT)
+X-Sender: steve@borgus.bgm.link.com
+In-Reply-To: <199805182119.QAA04388@kenai.me.umn.edu>
+Message-ID: 
+MIME-Version: 1.0
+Content-Type: TEXT/PLAIN; charset=US-ASCII
+Precedence: bulk
+Reply-To: flight-gear@me.umn.edu
+From: Steve Baker 
+Sender: owner-flight-gear@me.umn.edu
+To: flight-gear@me.umn.edu
+Subject: Re: [FGFS] View Frustum Culling
+Date: Tue, 19 May 1998 07:44:47 -0500 (CDT)
+
+On Mon, 18 May 1998, Curtis L. Olson wrote:
+
+> Steve Baker writes:
+> > Are you only planning to cull at the tile level?  You probably ought
+> > to cull at the triangle strip level (at least on machines without
+> > geometry hardware).
+> 
+> You are always trying to make things more complicated ... :-)
+ 
+It's my experience that things are perfectly capable of getting
+more complicated without any help from me :-)
+
+> > You can check a bounding sphere against the view frustum in about 4
+> > multiplies and four additions - and you only need to do that for
+> > spheres inside tiles that straddle the frustum. Each test that
+> > excludes a tstrip will save a bunch of vertex transforms - so you
+> > should get another big win in doing that.
+> 
+> Ok, a couple of questions.  Do you recommend pre-calculating and
+> storing the bounding sphere info for each tri-strip in the data file,
+> or should I calculate it at load time?
+
+Well, since you only have one CPU to use for both rendering and
+realtime database paging, you'll want to minimise the amount of
+calculations when loading. The bounding sphere calculation
+that most people do is very simple - you probably would want to do it
+offline eventually - but you can probably do it on loading the database
+for now just so you can get the culling stuff finished. So long as you
+don't do it every frame you'll be OK in the short term.
+
+The basic bounding sphere algorithm that most people (including me)
+use is v.simple. Just find the maximum and minimum x, y and z values
+in the data set, position the center of the sphere halfway between
+the minimum and maximum in each axis - then go through the points
+to find the one thats furthest from that center point - that distance
+is the radius. (You can compare the square of the ranges to get the
+longest range - so you only need to do one sqrt per sphere when you
+need to compute the actual radius).
+
+There has been some discussion of 'better' algorithms that (presumable)
+produce tighter spheres than the simple method described above. On
+my 'to do' list here at work is to evaluate these various algorithms to
+see which actually produces the tightest spheres.
+
+   tighter spheres == better culling == lower polygon counts.
+
+I'm pretty sceptical about these algorithms being *significantly*
+better than the simple one - but even a few percent improvement
+is worth having if I can do it offline and steal the code from
+someone who can do 'math'.
+
+This one looks interesting:
+
+   http://vision.ucsd.edu/~dwhite/ball.html
+
+...although being iterative, I wouldn't want to do it in my
+database loader code.
+
+Same applies to this one:
+
+   http://cm.bell-labs.com/who/clarkson/center.html
+
+Both have source code - which is just as well since I can't understand
+the math behind either of them!
+
+If your culling math starts to take too much time then you'll want to
+do a hierarchical cull. If I were you though I'd probably just
+do this:
+
+  for each terrain tile
+  {
+    if ( outside the frustum )
+      continue ;
+
+    if ( inside the frustum )
+      draw all the tristrips
+    else /* straddling the frustum */
+    {
+      for each tristrip
+        if ( inside or straddling the frustum )
+          draw the tristrip
+    }
+  }
+
+(Of course 'draw the tristrip' might actually mean 'add the tristrip to
+the appropriate bucket so we can draw it later')
+
+>  To impliment this sort of
+> scheme I suppose I would need to keep each tri-strip in it's own
+> display list.
+
+Yep - but you need to do that so that you can....
+
+> ...sort the objects into buckets by material properties.
+
+Definitely. Switching material properties (especially texture map)
+is very costly on most hardware OpenGL's. Sorting is an absolute
+must once you start you use more than one kind of texture on the
+terrain skin.
+
+>  I suppose this would entail defining material properties in the data
+> file and otherwise sprucing up the data file format (and internal data
+> structures) a bit.
+
+Eventually.
+
+
+Steve Baker                (817)619-8776 (Vox/Vox-Mail)
+Raytheon Systems Inc.      (817)619-4028 (Fax)
+Work: SBaker@link.com      http://www.hti.com
+Home: SJBaker1@airmail.net http://web2.airmail.net/sjbaker1
+
+-------------------------------------
+Please visit the FGFS web page:  http://www.menet.umn.edu/~curt/fgfs/
+For help on using this list (especially unsubscribing), send a message to
+"flight-gear-request@me.umn.edu" with a single line of text: "help".
+
+From sbaker@link.com  Mon May 18 07:39:58 1998
+X-VM-v5-Data: ([nil nil nil nil nil nil nil nil nil]
+	["10518" "Mon" "18" "May" "1998" "07:39:06" "-0500" "Steve Baker" "sbaker@link.com" nil "295" "Re: view frustum culling" "^From:" nil nil "5" nil nil nil nil nil]
+	nil)
+Received: from lfkw10.bgm.link.com (bgm.link.com [130.210.2.10])
+	by meserv.me.umn.edu (8.8.8/8.8.8) with ESMTP id HAA01318
+	for ; Mon, 18 May 1998 07:39:57 -0500 (CDT)
+Received: from sutcliffe.bgm.link.com (sutcliffe.bgm.link.com [130.210.236.18])
+          by lfkw10.bgm.link.com (8.8.6/HTI-Hack-8.8.4) with SMTP
+	  id HAA03232 for ; Mon, 18 May 1998 07:39:26 -0500 (CDT)
+X-Sender: steve@sutcliffe.bgm.link.com
+Reply-To: Steve Baker 
+In-Reply-To: <199805152113.QAA12303@kenai.me.umn.edu>
+Message-ID: 
+MIME-Version: 1.0
+Content-Type: TEXT/PLAIN; charset=US-ASCII
+From: Steve Baker 
+To: "Curtis L. Olson" 
+Subject: Re: view frustum culling
+Date: Mon, 18 May 1998 07:39:06 -0500 (CDT)
+
+On Fri, 15 May 1998, Curtis L. Olson wrote:
+
+> I was just planning to work out the math myself, but it's not coming
+> out nearly as simple as what you had.  The near/far clipping plane is
+> trivial, but I was working through the sides and started to see a few
+> sqrt()'s and such start to creep in, and I don't remember seeing this
+> with your pseudo-code.
+ 
+Certainly shouldn't need sqrt's.
+
+How about this:
+
+You said:
+
+> Anyone know anything about view frustum culling?
+
+Yep.
+
+Two issues:
+
+1) Scene hierarchy generation (offline).
+
+2) Runtime culling.
+
+Hierarchy:
+==========
+
+There are lots of ways to do this. I usually build an heirerchical description
+of each terrain tile. I typically build a tree structure that's organized
+as follows:
+
+                              |  The World.
+                              | 
+           ___________________|___   
+          |   |   |   |   |   |   |
+          *   *   *   *   *   *   *  Terrain tiles currently loaded
+          |   |   |   |   |   |   |
+                              |     
+                              |
+                         _____|_____
+                        |   |   |   |
+                        *   *   *   *   Quarter-tiles
+                        |   |   |   |
+                            |
+                            |
+                       _____|_____ 
+                      |   |   |   |
+                      *   *   *   *   Sixteenth-tiles
+                      |   |   |   |
+
+...and so on down until the number of polygons in each 'object' gets 'small enough'.
+
+When you do this, don't try to split polygons when they cross a quarter or a
+sixteenth tile boundary - just dump each polygon into the nearest 'bucket' to
+it's centroid.
+
+Do your tri-stripping on the leaf nodes of this tree - so that each tristrip
+is contained entirely within one bucket.
+
+Eventually, you will need to include buildings, roads, rivers, etc. Since these
+need to be culled by level of detail, it is often useful to put them into a separate
+tree structure that parallels the terrain 'skin' structure.
+
+Finally, compute a bounding sphere around each leaf node, find the best fit
+sphere by finding the maximum and minimim x, y and z of the tristrips in that
+leaf node, taking the mid-point and then finding the vertex that is furthest
+from that center point and using it as the radius.
+
+Compute the bounding sphere for each level in the tree (everywhere where there is
+a '*' in my diagram).
+
+Runtime:
+========
+
+At runtime, you walk that tree every frame, testing the bounding sphere against
+the view frustum.
+
+* If the sphere lies entirely outside the view frustum then stop traversal
+  for that node. There is no need to test any of the nodes beneath this one
+  (we know that none of their leaf tristrips are visible).
+
+* If the sphere lies entirely inside the view frustum then traverse immediately
+  to all of the leaves below this node without doing any more sphere testing
+  on them - draw all of the tristrips that are there. (We know they are all visible)
+
+* If the sphere straddles the view frustum then check each daughter node in
+  turn by applying this algorithm on them recursively. If a leaf node straddles
+  the view frustrum then it's bad luck, you just draw all the tristrips it
+  contains and let OpenGL do the work.
+
+You might also want to put a 'transition range' onto each node and if it
+lies beyond that range cull it. You can also use this to conveniently
+switch levels of detail by having multiple versions of each object in
+the tree.
+
+Testing a sphere against the View Frustum:
+==========================================
+
+In most cases, we can describe the volume of space that you can see
+through the little glass window on the front of your CRT using a
+Frustum (frequently mis-spelled as Frustrum or Fustrum even in some
+text books).
+
+A frustum is a truncated pyramid - which typically bounded by six
+planes called:
+
+  NEAR, FAR, LEFT, RIGHT, TOP, BOTTOM
+
+There are applications that require additional clipping planes (eg for
+non-rectangular screens) - extending the work described in this
+to cater for that is not hard).
+
+In principal, all six planes can be constructed as general plane
+equations:
+
+    A x + B y + C z + D == 0
+
+However, for most applications, NEAR and FAR are parallel to the
+screen, LEFT, RIGHT,TOP and BOTTOM all meet at the eye and the eye lies
+along a vector that extends out from the center of the screen and is
+perpendicular to it. This simplifies the equations considerably for
+practical applications.
+
+Transforms.
+~~~~~~~~~~~
+
+It is easiest to perform culling in a coordinate system where the
+eyepoint is at the origin and the line from the eye through the center
+of the screen lies along one major axis with the edges of the screen
+parallel to the remaining two axes. This coordinate system is called
+'Eye Space'.
+
+Testing a Sphere against a Frustum.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The most important thing to bear in mind about culling is that the
+first trivial-reject test you apply is by far the most time-critical.
+This test is always applied to more nodes than any of the subsequent
+tests.
+
+So, do the cheapest test first.
+
+This is typically the NEAR plane test. Everything behind the viewers
+head gets chopped out - and it's an especially cheap test.
+
+
+   if ( obj_sphere.center.z < near_plane - obj_sphere.radius )
+     REJECT!!
+
+
+...next do the second cheapest test (assuming you know that your
+database could possibly extend beyond the far clip plane)...
+
+
+   if ( obj_sphere.center.z - obj_sphere.radius > far_plane )
+     REJECT!!
+
+
+...and *then* (for each of the other 4 planes) do...
+
+
+   if ( distance( obj.position, plane ) <= obj_sphere.radius )
+     REJECT!!
+
+
+(The algorithm for computing that 'distance()' function is described
+below).
+
+It's also useful to know that in many applications, you cull more
+objects from the left and right faces of the frustum than you do from
+the top and bottom - so test left, then right, then bottom then top.
+
+Also, with bounding sphere tests, you shouldn't forget to do
+total-accept as well as total-reject tests. Once you know that an
+object's sphere is TOTALLY on screen, you don't have to descend into
+the daughter objects to cull-test them...you *know* they are all
+on-screen.
+
+Another way to look at that it to remember which of the six possible
+plane tests didn't even touch the sphere - as you work your way down
+the object hierarchy, you can accumulate those flags and avoid even
+testing those planes that a parent sphere has already cleanly passed.
+If you do this then a vast percentage of your spheres will only need to
+be tested against one plane.  However, for the normal case of a simple
+frustum - when you examine the fully optimised
+distance-of-point-from-plane code (below), you may well conclude that
+this additional logic doesn't justify the paltry amount of additional
+math that it might save.
+
+Computing the Distance from Sphere Center to Clipping Plane.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A plane can be represented by the equation
+
+
+     Ax + By + Cz + D = 0 ;
+
+
+A,B,C is just the surface normal of the plane and D is the shortest
+distance from the origin to the plane.
+
+So, if you need to find the distance of a point from the plane, just
+imagine a new plane that goes through your test point and is parallel
+to the plane you want to test. The plane equation of that new plane
+would be:
+
+
+     A'x + B'y + C'z + D' = 0 ;
+
+
+Since the two planes are parallel, their surface normals are the same,
+so
+
+
+   A' == A B' == B C' == C D' == D + distance_between_the_two_planes
+
+
+...the only thing that's different is their D values - which differ by
+the distance of your test point from the original plane.
+
+So, for a point (x,y,z), the distance 'd' from the plane (A,B,C,D) is
+derived as:
+
+
+   d = D' - D
+     = -A'x - B'y - C'z - D
+     = -Ax - By - Cz - D
+     = -( [ABC]dot[xyz] + D )
+
+
+A dot-product of the point and the surface normal of the plane, plus
+the distance from the plane to the origin. Three multiplies, three
+additions and a negation.
+
+As an aside - if you consider the point (x,y,z) as a FOUR element
+homogeneous vector (x,y,z,w) then 'w' is 1.0 and you can compute the
+distance by simply taking the four element dot-product of (A,B,C,D)
+with (x,y,z,w). If you have fast 4x4 matrix math hardware in your
+machine then you can use it to compute the distance from a point to all
+four planes in a single operation!
+
+That's the general result for an arbitary plane - but culling to the
+view frustum is a very special case. If you are working in eye-relative
+coordinates (IMHO this is best), then since all TOP,BOTTOM,LEFT,RIGHT
+planes of the frustum meet at the eye - and since the eye is at the
+origin (by definition), then D is always zero for those planes and that
+saves you a subtract.
+
+If you are feeling even more in need of optimisation - then you can
+save one multiply per plane by realising that (for rectangular screens)
+one of the three components of the plane equation will always be zero.
+
+So, for the LEFT clip plane, the Y component of the normal of the plane
+is zero, so the distance to the left or right plane is just
+
+
+     d = -( Ax + Cz )
+
+
+...and to the top or bottom plane it's just:
+
+
+     d = -( By + Cz )
+
+
+Furthermore, we know that the A component for the LEFT plane is just
+the negation of the A component of the RIGHT plane, and the C component
+is the same for both LEFT and RIGHT (and similarly, the B component of
+the TOP plane, is the negation of the B component for the BOTTOM plane
+and the C component is the same for both TOP and BOTTOM). This means
+that you only need four multiplies and four additions to do the entire
+job. (Since you are only using this for culling, you don't need the
+minus sign - just reverse the conditional).
+
+The NEAR and FAR planes are typically parallel to the X/Y plane. That
+means that A and B are both zero and C is one (or minus-one) - but D is
+not zero, so the math boils down to an add and a negate:
+
+
+     d = -(z + D)
+
+
+Conclusions.
+~~~~~~~~~~~~
+
+Sphere-based culling can be extremely cost-effective. It's so cheap
+that even if you feel the need to use a bounding cubeoid (or even a yet
+more complex shape), it's still worth doing a sphere-based cull first
+just to get rid of the trivial accept and reject cases.
+
+
+Steve Baker                (817)619-8776 (Vox/Vox-Mail)
+Raytheon Systems Inc.      (817)619-4028 (Fax)
+Work: SBaker@link.com      http://www.hti.com
+Home: SJBaker1@airmail.net http://web2.airmail.net/sjbaker1
+
+From owner-flight-gear@me.umn.edu  Tue May 26 08:43:36 1998
+X-VM-v5-Data: ([nil nil nil nil nil nil nil nil nil]
+	["2090" "Tue" "26" "May" "1998" "08:42:09" "-0500" "Steve Baker" "sbaker@link.com" nil "69" "Re: [FGFS] View frustum culling" "^From:" nil nil "5" nil nil nil nil nil]
+	nil)
+Received: (from majordom@localhost)
+	by meserv.me.umn.edu (8.8.8/8.8.8) id IAA29744
+	for flight-gear-outgoing; Tue, 26 May 1998 08:43:36 -0500 (CDT)
+X-Authentication-Warning: meserv.me.umn.edu: majordom set sender to owner-flight-gear@me.umn.edu using -f
+Received: from lfkw10.bgm.link.com (bgm.link.com [130.210.2.10])
+	by meserv.me.umn.edu (8.8.8/8.8.8) with ESMTP id IAA29740
+	for ; Tue, 26 May 1998 08:43:31 -0500 (CDT)
+Received: from borgus.bgm.link.com (borgus.bgm.link.com [130.210.236.13])
+          by lfkw10.bgm.link.com (8.8.6/HTI-Hack-8.8.4) with SMTP
+	  id IAA02170 for ; Tue, 26 May 1998 08:43:01 -0500 (CDT)
+X-Sender: steve@borgus.bgm.link.com
+In-Reply-To: <199805240245.VAA00603@kenai.me.umn.edu>
+Message-ID: 
+MIME-Version: 1.0
+Content-Type: TEXT/PLAIN; charset=US-ASCII
+Precedence: bulk
+Reply-To: flight-gear@me.umn.edu
+From: Steve Baker 
+Sender: owner-flight-gear@me.umn.edu
+To: flight-gear@me.umn.edu
+Subject: Re: [FGFS] View frustum culling
+Date: Tue, 26 May 1998 08:42:09 -0500 (CDT)
+
+On Sat, 23 May 1998, Curtis L. Olson wrote:
+
+> Gene Buckle writes:
+> > If you want to email me a cygnus/mesa binary, I'd be happy to give
+> > you new speed figures.
+> 
+> Gene,
+> 
+> The new binaries expect a modified scenery format.  My impression for
+> now based on culled vs. drawn percentages is that there was a much
+> bigger jump between no culling and tile culling, than between tile
+> culling and fragment culling.
+ 
+That's to be expected...
+
+(The eye is in the center of the diagram - looking up:
+
+No Culling - draw this much:
+
+   ________\_____________/________
+  |       | \     |     / |       |
+  |       |  \    |    /  |       |
+  |_______|___\___|___/___|_______|
+  |       |    \  |  /    |       |
+  |       |     \ | /     |       |
+  |_______|______\|/______|_______|
+  |       |       |       |       |
+  |       |       |       |       |
+  |_______|_______|_______|_______|
+  |       |       |       |       |
+  |       |       |       |       |
+  |_______|_______|_______|_______|
+
+
+Tile culling - draw this much:
+
+          _\_____________/_
+          | \     |     / |
+          |  \    |    /  |
+          |___\___|___/___|
+          |    \  |  /    |
+          |     \ | /     |
+          |______\|/______|
+
+
+Tile *and* tstrip culling - draw maybe this much:
+
+           \_____________/_
+          |_\     |     /_|
+           |_\    |    / |
+            |_\___|___/__|
+              |\  |  /_|
+              |_\ | /_|
+                |\|/|
+
+Clearly most of the savings were in the tile culling, but providing the
+culling itself is done reasonably efficiently, the tstrip culling is
+still worth-while.
+
+
+Steve Baker                (817)619-8776 (Vox/Vox-Mail)
+Raytheon Systems Inc.      (817)619-4028 (Fax)
+Work: SBaker@link.com      http://www.hti.com
+Home: SJBaker1@airmail.net http://web2.airmail.net/sjbaker1
+
+-------------------------------------
+Please visit the FGFS web page:  http://www.menet.umn.edu/~curt/fgfs/
+For help on using this list (especially unsubscribing), send a message to
+"flight-gear-request@me.umn.edu" with a single line of text: "help".
+
diff --git a/Hints/view-projection b/Hints/view-projection
new file mode 100644
index 000000000..15cc6b09e
--- /dev/null
+++ b/Hints/view-projection
@@ -0,0 +1,86 @@
+From fatcity!root@news.cts.com  Mon Apr 20 10:54:32 1998
+X-VM-v5-Data: ([nil nil nil nil nil nil nil nil nil]
+	["2073" "Mon" "20" "April" "1998" "07:50:34" "-0800" "Steve Baker" "sbaker@link.com" nil "54" "Re: How To Q: Off-screen object culling." "^From:" nil nil "4" nil nil nil nil nil]
+	nil)
+Received: from mh2.cts.com (root@mh2.cts.com [205.163.24.68])
+	by meserv.me.umn.edu (8.8.8/8.8.8) with ESMTP id KAA05163
+	for ; Mon, 20 Apr 1998 10:54:29 -0500 (CDT)
+Received: from king.cts.com (root@king.cts.com [198.68.168.21]) by mh2.cts.com (8.8.7/8.8.5) with ESMTP id IAA15636; Mon, 20 Apr 1998 08:51:20 -0700 (PDT)
+Received: from donews.cts.com (root@donews.cts.com [192.188.72.21])
+	by king.cts.com (8.8.7/8.8.7) with SMTP id IAA29983;
+	Mon, 20 Apr 1998 08:51:19 -0700 (PDT)
+Received: from fatcity by donews.cts.com with uucp
+	(Smail3.1.29.1 #5) id m0yRI5D-00000Xa; Mon, 20 Apr 98 08:02 PDT
+Received: by fatcity.com (10-Feb-1998/v1.0f-b64/bab) via UUCP id 0001F042; Mon, 20 Apr 1998 07:50:34 -0800
+Message-ID: 
+X-Comment: OpenGL Game Developers Mailing List
+X-Sender: Steve Baker 
+Reply-To: OPENGL-GAMEDEV-L@fatcity.com
+Errors-To: ML-ERRORS@fatcity.com
+Organization: Fat City Network Services, San Diego, California
+X-ListServer: v1.0f, build 64; ListGuru (c) 1996-1998 Bruce A. Bergman
+Precedence: bulk
+Mime-Version: 1.0
+Content-Type: TEXT/PLAIN; charset=US-ASCII
+Content-Transfer-Encoding: 7bit
+From: Steve Baker 
+Sender: root@fatcity.com
+To: Multiple recipients of list OPENGL-GAMEDEV-L 
+Subject: Re: How To Q: Off-screen object culling.
+Date: Mon, 20 Apr 1998 07:50:34 -0800
+
+On Sat, 18 Apr 1998, Jason Maskell wrote:
+
+> This is probably an FAQ, but I'm to the point now where I need to be
+> able to tell when one of my objects is offscreen and not even send it
+> down the pipe. This would be pretty simple if I was using glFrustum,
+> but I'm not at the moment. I could switch, but I haven't quite got my
+> head around how to get the same results as I get using glPerspective..
+> If someone can point me to some code that does some simple pre-culling,
+> I would be most grateful..  >
+
+Well, if you can do it with glFrustum then you can do it with
+gluPerspective. Note that gluPerspective simply calls glFrustum.
+
+It's like this:
+
+void APIENTRY gluPerspective( GLdouble fovy, GLdouble aspect,
+                              GLdouble zNear, GLdouble zFar )
+{
+   GLdouble xmin, xmax, ymin, ymax;
+
+   ymax = zNear * tan( fovy * M_PI / 360.0 );
+   ymin = -ymax;
+
+   xmin = ymin * aspect;
+   xmax = ymax * aspect;
+
+   glFrustum( xmin, xmax, ymin, ymax, zNear, zFar );
+}
+
+[This is actually the source code for gluPerspective from the Mesa
+library - but since it only involves regular OpenGL API, it should
+work on any OpenGL implementation]
+
+> BTW, I've bought the red book finally...
+
+Always a good move. I have yet to hear anyone who regretted it.
+
+Steve Baker                (817)619-8776 (Vox/Vox-Mail)
+Raytheon Systems Inc.      (817)619-4028 (Fax)
+Work: SBaker@link.com      http://www.hti.com
+Home: SJBaker1@airmail.net http://web2.airmail.net/sjbaker1
+
+-- 
+Author: Steve Baker
+  INET: sbaker@link.com
+
+Fat City Network Services    -- (619) 538-5051  FAX: (619) 538-5051
+San Diego, California        -- Public Internet access / Mailing Lists
+--------------------------------------------------------------------
+To REMOVE yourself from this mailing list, send an E-Mail message
+to: ListGuru@fatcity.com (note EXACT spelling of 'ListGuru') and in
+the message BODY, include a line containing: UNSUB OPENGL-GAMEDEV-L
+(or the name of mailing list you want to be removed from).  You may
+also send the HELP command for other information (like subscribing).
+
diff --git a/Hints/win32-time-funcs b/Hints/win32-time-funcs
new file mode 100644
index 000000000..7a9448309
--- /dev/null
+++ b/Hints/win32-time-funcs
@@ -0,0 +1,112 @@
+From nhv@laserplot.com  Mon Mar 16 14:16:34 1998
+X-VM-v5-Data: ([nil nil nil nil t nil nil nil nil]
+	["1740" "Mon" "16" "March" "1998" "15:11:22" "-0500" "Norman Vine" "nhv@laserplot.com" "<01BD50EE.348AEBC0.nhv@laserplot.com>" "84" "RE: Today's patches" "^From:" nil nil "3" nil nil nil nil nil]
+	nil)
+Received: from mail-out-0.tiac.net (mail-out-0.tiac.net [199.0.65.247])
+	by meserv.me.umn.edu (8.8.8/8.8.8) with ESMTP id OAA21951
+	for ; Mon, 16 Mar 1998 14:16:33 -0600 (CST)
+Received: from mail-out-2.tiac.net (mail-out-2.tiac.net [199.0.65.13])
+	by mail-out-0.tiac.net (8.8.8/8.8.8) with ESMTP id PAA20462
+	for ; Mon, 16 Mar 1998 15:16:26 -0500 (EST)
+	(envelope-from nhv@laserplot.com)
+Received: from nhv (p1.gw1.mashp.MA.tiac.com [206.119.240.34])
+	by mail-out-2.tiac.net (8.8.7/8.8.7) with SMTP id PAA26460
+	for ; Mon, 16 Mar 1998 15:17:02 -0500 (EST)
+	(envelope-from nhv@laserplot.com)
+Received: by localhost with Microsoft MAPI; Mon, 16 Mar 1998 15:14:25 -0500
+Message-ID: <01BD50EE.348AEBC0.nhv@laserplot.com>
+Reply-To: "nhv@laserplot.com" 
+X-Mailer: Microsoft Internet E-mail/MAPI - 8.0.0.4211
+MIME-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
+Content-Transfer-Encoding: 7bit
+From: Norman Vine 
+To: "'Curtis L. Olson'" 
+Subject: RE: Today's patches
+Date: Mon, 16 Mar 1998 15:11:22 -0500
+
+On Monday, March 16, 1998 2:31 PM, Curtis L. Olson [SMTP:curt@me.umn.edu] wrote:
+> Norm,
+> 
+> I got both your patches.  Thanks!  The first one looks good, I'll
+> forward that over to the HUD guys.
+> 
+> For the second one, could you try a little bit different fix?  It
+> seemed to work for me anyways.  Somewhere in fg_time.c you'll see the
+> following four lines:
+> 
+> #ifdef WIN32
+>     int daylight;
+>     long int timezone;
+> #endif /* WIN32 */
+> 
+> Could you just try moving them to the top of the file (outside of any
+> functions) so they have a "global" scope?  I put 'em right before
+> fgTimeInit().
+
+Seems to work :-)
+
+> 
+> I just did a quick test of this and I didn't see the sun jumping
+> around.  I really wish I knew how to get the real daylight savings
+> time info out of a win32 machine ...
+
+following time related stuff from CygWin headers
+
+
+
+typedef struct _TIME_ZONE_INFORMATION { 
+  LONG       Bias; 
+  WCHAR      StandardName[ 32 ]; 
+  SYSTEMTIME StandardDate; 
+  LONG       StandardBias; 
+  WCHAR      DaylightName[ 32 ]; 
+  SYSTEMTIME DaylightDate; 
+  LONG       DaylightBias; 
+} TIME_ZONE_INFORMATION, *LPTIME_ZONE_INFORMATION; 
+
+typedef struct _SYSTEMTIME {  
+  WORD wYear; 
+  WORD wMonth; 
+  WORD wDayOfWeek; 
+  WORD wDay; 
+  WORD wHour; 
+  WORD wMinute; 
+  WORD wSecond; 
+  WORD wMilliseconds; 
+} SYSTEMTIME, *LPSYSTEMTIME; 
+
+!!!!!!!!!!!!!!!!!!!!!!
+
+
+
+DWORD
+STDCALL
+GetTimeZoneInformation(
+		       LPTIME_ZONE_INFORMATION lpTimeZoneInformation
+		       );
+
+VOID
+STDCALL
+GetSystemTime(
+	      LPSYSTEMTIME lpSystemTime
+	      );
+
+VOID
+STDCALL
+GetLocalTime(
+	     LPSYSTEMTIME lpSystemTime
+	     );
+
+
+DWORD
+STDCALL
+GetTickCount(
+	     VOID
+	     ); 
+
+See Ya
+
+Norman
+
+
diff --git a/Include/auto_ptr.hxx b/Include/auto_ptr.hxx
index d209b80ac..0f7864768 100644
--- a/Include/auto_ptr.hxx
+++ b/Include/auto_ptr.hxx
@@ -89,6 +89,9 @@ public:
 #endif /* _AUTO_PTR_HXX */
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:41  curt
+// Initial revision
+//
 // Revision 1.2  1998/09/10 19:07:03  curt
 // /Simulator/Objects/fragment.hxx
 //   Nested fgFACE inside fgFRAGMENT since its not used anywhere else.
diff --git a/Include/cmdargs.h b/Include/cmdargs.h
index d42ec52e1..21c6c27f6 100644
--- a/Include/cmdargs.h
+++ b/Include/cmdargs.h
@@ -42,6 +42,9 @@ extern const int   DefaultViewMode;
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:41  curt
+// Initial revision
+//
 // Revision 1.2  1998/02/16 16:17:36  curt
 // Minor tweaks.
 //
diff --git a/Include/compiler.h b/Include/compiler.h
index 3359c0563..dd9b87b87 100644
--- a/Include/compiler.h
+++ b/Include/compiler.h
@@ -301,6 +301,9 @@ inline const_mem_fun_ref_t<_Ret,_Tp> mem_fun_ref(_Ret (_Tp::*__f)() const)
 #endif // _COMPILER_H
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:40  curt
+// Initial revision
+//
 // Revision 1.9  1999/03/02 00:36:31  curt
 // Tweaks for native SGI compilers.
 //
diff --git a/Include/fg_callback.hxx b/Include/fg_callback.hxx
index 05edd0126..def7fb277 100644
--- a/Include/fg_callback.hxx
+++ b/Include/fg_callback.hxx
@@ -170,6 +170,9 @@ fgMethodCallback::call0v( void** )
 #endif // _FG_CALLBACK_HXX
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:41  curt
+// Initial revision
+//
 // Revision 1.2  1998/09/15 02:09:04  curt
 // Include/fg_callback.hxx
 //   Moved code inline to stop g++ 2.7 from complaining.
diff --git a/Include/fg_constants.h b/Include/fg_constants.h
index 70b932946..f15b4e185 100644
--- a/Include/fg_constants.h
+++ b/Include/fg_constants.h
@@ -173,6 +173,9 @@
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:40  curt
+// Initial revision
+//
 // Revision 1.13  1999/04/05 02:12:59  curt
 // Define maximum nodes for a tile here.
 //
diff --git a/Include/fg_memory.h b/Include/fg_memory.h
index 830dcba26..4ff20fb0b 100644
--- a/Include/fg_memory.h
+++ b/Include/fg_memory.h
@@ -59,6 +59,9 @@
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:40  curt
+// Initial revision
+//
 // Revision 1.2  1998/12/09 18:47:39  curt
 // Use C++ style comments.
 //
diff --git a/Include/fg_typedefs.h b/Include/fg_typedefs.h
index ab398a379..52e9368cc 100644
--- a/Include/fg_typedefs.h
+++ b/Include/fg_typedefs.h
@@ -2,6 +2,9 @@
 //  Alterations: Copyright C. Hotchkiss 1996
 //
 // $Log$
+// Revision 1.1  1999/04/05 21:32:40  curt
+// Initial revision
+//
 // Revision 1.2  1998/05/13 18:23:46  curt
 // fg_typedefs.h: updated version by Charlie Hotchkiss
 // general.h: moved fg_root info to fgOPTIONS structure.
diff --git a/Include/fg_zlib.h b/Include/fg_zlib.h
index 728094735..8fe7848c5 100644
--- a/Include/fg_zlib.h
+++ b/Include/fg_zlib.h
@@ -82,7 +82,10 @@
 
 
 /* $Log$
-/* Revision 1.1  1998/04/28 21:41:39  curt
-/* Initial revision of fg_zlib.h
+/* Revision 1.1  1999/04/05 21:32:41  curt
+/* Initial revision
 /*
+ * Revision 1.1  1998/04/28 21:41:39  curt
+ * Initial revision of fg_zlib.h
+ *
  */
diff --git a/Include/general.hxx b/Include/general.hxx
index da934e861..455e1e446 100644
--- a/Include/general.hxx
+++ b/Include/general.hxx
@@ -65,6 +65,9 @@ extern FGGeneral general;
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:40  curt
+// Initial revision
+//
 // Revision 1.1  1999/01/06 21:47:39  curt
 // renamed general.h to general.hxx
 // More portability enhancements to compiler.h
diff --git a/Lib/Audio/CHANGES b/Lib/Audio/CHANGES
deleted file mode 100644
index c36010719..000000000
--- a/Lib/Audio/CHANGES
+++ /dev/null
@@ -1,139 +0,0 @@
-
-/**********************************************\
-*                                              *
-*                W A R N I N G                 *
-*                                              *
-* This file is now kept in reverse chronolog-  *
-* ical order so recent changes are now at the  *
-* top.                                         *
-*                                              *
-\**********************************************/
-
-* 28th Sept 1889 -- Fixed a bug associated with exiting the
-                      program with sounds still playing.
-                    Fixed a bug associated with using the
-                      package in the absence of a sound card.
-                    Added a new member function "working"
-                      which is the opposite of "not_working",
-                      (as demanded by a bunch of rabid optimists)!
-                    Fixed a couple of typo's in the manual.
-
-* 23rd Sept 1998 -- The Good News: Finally got around to
-                         getting the pitch envelope working. (Hooray) 
-                    The Bad News: This costs quite a bit in
-                         performance - and it was a MAJOR rewrite
-                         of significant parts of the internals,
-                         so we may need some bug fixes.
-                    This version is 0.5
-
-* 7th  July 1998 -- Fixed some error checking in slSample.cxx and
-                    a missing declaration in sl.h
-
-* 6th  July 1998 -- Fixed an initialisation problem when
-                    slScheduler was not a static/global.
-
-                    Tom Knienieder's port to SGI/IRIX is now
-                    working, documentation updated to reflect that.
-
-* 16th June 1998 -- Added some slPortability.h fixes for
-                    FreeBSD and the Cygnus WIN32 compiler.
-                    Many thanks to Curt.
-
-* 14th June 1998 -- Tom Knienieder's port to OpenBSD is now
-                    working, documentation updated to reflect that.
-                    Tom's improved Makefiles included, also some
-                    example sound samples that were accidentally
-                    left out of the release are now present.
-                    A couple of typo's in the WIN32 section
-                    have been fixed. The top level Makefile
-                    now requires you to type 'make linux',
-                    'make win' or 'make openbsd'.
-
-* 13th June 1998 -- Tom Knienieder's port to WIN32 engine is now
-                    working, documentation updated to reflect that
-                    revised status. Some default constructor parameters
-                    have changed, slDSP no longer supports setRate/setBps/setStereo.
-                    You now have to delete the slDSP and recreate it with
-                    new parameters. This makes porting a little easier.
-                    'sound_test' renamed 'example'.
-
-* 7th  June 1998 -- Volume envelopes (and inverse volume envelopes)
-                    now work correctly. Pan envelopes won't work
-                    until stereo is implemented. Pitch and filter
-                    envelopes turn out to be a major pain to implement
-                    with the present slSceduler/slSamplePlayer interface,
-                    so some significant internal changes are to be
-                    expected.
-
-                    Changed the CHANGES file to be in reverse
-                    chronological order.
-
-                    This version is officially  SL v0.3 (beta)
- 
-*  3rd June 1998 -- Moved sample program and it's data files into
-                    'example', moved documents into 'doc' and sources
-                    into 'src'. Final library goes into 'lib'.
-
-                    The entire preempting mechanism was broken -
-                    now it's fixed.
- 
-                    Added a callback mechanism that allows
-                    applications to know when a sound
-                    loops, finishes playing, is pre-empted, etc.
-
-                    New mechanisms added to stop/pause/resume a
-                    playing sample.
- 
-                    All the documentation - and some of the code -
-                    for slEnvelopes has been added, they don't
-                    work yet - so don't bother with them for now.
-
-                    Made some code a little more bullet-proof.
-                    slSample's are now reference-counted so you
-                    can't accidentally delete one while it's
-                    playing without getting a FATAL error.
-
-* 2nd  June 1998 -- Fixed bug in initialisation that prevented SL
-                    from functioning correctly in the case were there
-                    is no sound card present.
-
-                    This version is officially  SL v0.2 (beta)
-
-* 1st  June 1998 -- Split library into two parts - libsm and
-                    libsl. libsm contains only the Mixer class
-                    since it is likely to be hard to port to
-                    a lot of non-OSS systems - and most programs
-                    won't need it anyway. Hence the documentation
-                    has blossomed into three files and all the
-                    'slMixer' references have turned into 'smMixer'.
-                    Also, I finally got a hold of the OSS documentation,
-                    which is a lot more complete - and straightened
-                    me out on a few points. slDSP has changed
-                    (internally) somewhat as a result and in particular,
-                    you can no longer mess with the sampling rate,
-                    stereo and bps settings after the slDSP or
-                    slScheduler has been created. This also allows the
-                    scheduler to enforce it's rule about only mono/8bps
-                    operations.
-
-                    I also added an 'autoMatch' function to the slSample
-                    class to automagically match incoming samples to the
-                    current slDSP/slScheduler. This makes using the library
-                    a lot less painful and error-prone.
- 
-                    This version is officially  SL v0.1 (beta)
- 
-                    We need a better name!
-
-* 30th May  1998 -- Almost total rewrite, library can now
-                    play multiple sounds without interruption,
-                    supports '.WAV' and '.AU' file formats as
-                    well as raw binary files. Able to copy with
-                    much shorter safetyMargin on sound buffers,
-                    and play without using the 'stop' call.
-                    All class and external symbols now begin
-                    with 'sl' or 'SL'. HTML documentation now
-                    available.
-
-* 27th May  1998 -- First hack
-
diff --git a/Lib/Audio/Makefile.am b/Lib/Audio/Makefile.am
deleted file mode 100644
index 835577f82..000000000
--- a/Lib/Audio/Makefile.am
+++ /dev/null
@@ -1 +0,0 @@
-SUBDIRS = src example
diff --git a/Lib/Audio/NOTICE b/Lib/Audio/NOTICE
deleted file mode 100644
index ba95093a2..000000000
--- a/Lib/Audio/NOTICE
+++ /dev/null
@@ -1,9 +0,0 @@
-NOTICE:  This Sound Library (SL) distribution contains source code that is
-placed into the public domain without copyright. These programs are freely
-distributable without licensing fees.  These programs are provided without
-guarantee or warrantee expressed or implied. 
-
-If you use SL in a commercial or shareware product, it would be nice if you
-gave credit where it is due.  If you make any modifications or improvements
-to SL, I would greatly appreciate a copy of the improved code.
-
diff --git a/Lib/Audio/README b/Lib/Audio/README
deleted file mode 100644
index 8bf6b4daa..000000000
--- a/Lib/Audio/README
+++ /dev/null
@@ -1,9 +0,0 @@
-
-Hi!
-
-  This is the fifth prototype of Steve's 'SL' sound library.
-
-  Check out 'CHANGES' and the new HTML documentation.
-
-Steve
-
diff --git a/Lib/Audio/README.freebsd b/Lib/Audio/README.freebsd
deleted file mode 100644
index 540c00e4f..000000000
--- a/Lib/Audio/README.freebsd
+++ /dev/null
@@ -1,13 +0,0 @@
-
-Building SL for Linux.
-~~~~~~~~~~~~~~~~~~~~~~
-
-   % make freebsd
-   % su root
-   % make install
-
-...that's all folks.
-
-Header  files   go into /usr/include/SL (analogous to /usr/include/GL for graphics)
-Library file(s) go into /usr/lib
-
diff --git a/Lib/Audio/README.linux b/Lib/Audio/README.linux
deleted file mode 100644
index 7df00e8f2..000000000
--- a/Lib/Audio/README.linux
+++ /dev/null
@@ -1,13 +0,0 @@
-
-Building SL for Linux.
-~~~~~~~~~~~~~~~~~~~~~~
-
-   % make linux
-   % su root
-   % make install
-
-...that's all folks.
-
-Header  files   go into /usr/include/SL (analogous to /usr/include/GL for graphics)
-Library file(s) go into /usr/lib
-
diff --git a/Lib/Audio/README.openbsd b/Lib/Audio/README.openbsd
deleted file mode 100644
index 9ef788f36..000000000
--- a/Lib/Audio/README.openbsd
+++ /dev/null
@@ -1,13 +0,0 @@
-
-Building SL for OpenBSD.
-~~~~~~~~~~~~~~~~~~~~~~~~
-
-   % make openbsd
-   % su root
-   % make install
-
-...that's all folks.
-
-Header  files   go into /usr/include/SL (analogous to /usr/include/GL for graphics)
-Library file(s) go into /usr/lib
-
diff --git a/Lib/Audio/README.sgi b/Lib/Audio/README.sgi
deleted file mode 100644
index c1c52e154..000000000
--- a/Lib/Audio/README.sgi
+++ /dev/null
@@ -1,27 +0,0 @@
-
-Building SL for SGI.
-~~~~~~~~~~~~~~~~~~~~~~
-
-There are two options, depending on whether you want to use GCC or
-the standard SGI C++ compiler.
-
-GNU G++:
-
-   % make sgigcc
-   % su root
-   % make install
-
-SGI C++:
-
-   % make sgi
-   % su root
-   % make install
-
-...that's all folks.
-
-Header  files   go into /usr/include/SL (analogous to /usr/include/GL for graphics)
-Library file(s) go into /usr/lib
-
-When you link, be sure to include to -laudio
-
-
diff --git a/Lib/Audio/README.unix b/Lib/Audio/README.unix
deleted file mode 100644
index 771e856d5..000000000
--- a/Lib/Audio/README.unix
+++ /dev/null
@@ -1,20 +0,0 @@
-Building SL for UNIX
-~~~~~~~~~~~~~~~~~~~~
-
-If your UNIX box is Linux or OpenBSD then
-check out README.linux or README.openbsd.
-
-If your UNIX box supports OSS (the Open
-Sound System) then in principal, you should
-only need to type:
-
-  % make oss
-  % su root
-  % make install
-
-...however, your milage may vary. If you succeed
-in getting a non-Linux, non-OpenBSD version to
-work, I'd like to hear about it.
-
-          Steve Baker  
-
diff --git a/Lib/Audio/README.win b/Lib/Audio/README.win
deleted file mode 100644
index a9d528227..000000000
--- a/Lib/Audio/README.win
+++ /dev/null
@@ -1,15 +0,0 @@
-
-Building SL for win32 (msvc)
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-   C:>nmake win32
-
-
-don't forget to set the environment !
-
-example:
-
-set include=c:\msdev\include;
-set lib=c:\msdev\lib
-
-path c:\msdev\bin;c:\bin;c:\winnt;......
diff --git a/Lib/Bucket/newbucket.cxx b/Lib/Bucket/newbucket.cxx
index 2fbb32ec5..b17103fb0 100644
--- a/Lib/Bucket/newbucket.cxx
+++ b/Lib/Bucket/newbucket.cxx
@@ -146,6 +146,9 @@ void fgBucketDiff( const FGBucket& b1, const FGBucket& b2, int *dx, int *dy ) {
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:34  curt
+// Initial revision
+//
 // Revision 1.4  1999/03/27 05:34:05  curt
 // Elimitated some const warnings from the compiler.
 //
diff --git a/Lib/Bucket/newbucket.hxx b/Lib/Bucket/newbucket.hxx
index 3ef337d4a..91a19342e 100644
--- a/Lib/Bucket/newbucket.hxx
+++ b/Lib/Bucket/newbucket.hxx
@@ -330,6 +330,9 @@ operator== ( const FGBucket& b1, const FGBucket& b2 )
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:34  curt
+// Initial revision
+//
 // Revision 1.8  1999/03/27 05:34:06  curt
 // Elimitated some const warnings from the compiler.
 //
diff --git a/Lib/CVSROOT/checkoutlist b/Lib/CVSROOT/checkoutlist
deleted file mode 100644
index b04b3501f..000000000
--- a/Lib/CVSROOT/checkoutlist
+++ /dev/null
@@ -1,13 +0,0 @@
-# The "checkoutlist" file is used to support additional version controlled
-# administrative files in $CVSROOT/CVSROOT, such as template files.
-#
-# The first entry on a line is a filename which will be checked out from
-# the corresponding RCS file in the $CVSROOT/CVSROOT directory.
-# The remainder of the line is an error message to use if the file cannot
-# be checked out.
-#
-# File format:
-#
-#	[]
-#
-# comment lines begin with '#'
diff --git a/Lib/CVSROOT/commitinfo b/Lib/CVSROOT/commitinfo
deleted file mode 100644
index b19e7b7a6..000000000
--- a/Lib/CVSROOT/commitinfo
+++ /dev/null
@@ -1,15 +0,0 @@
-# The "commitinfo" file is used to control pre-commit checks.
-# The filter on the right is invoked with the repository and a list 
-# of files to check.  A non-zero exit of the filter program will 
-# cause the commit to be aborted.
-#
-# The first entry on a line is a regular expression which is tested
-# against the directory that the change is being committed to, relative
-# to the $CVSROOT.  For the first match that is found, then the remainder
-# of the line is the name of the filter to run.
-#
-# If the repository name does not match any of the regular expressions in this
-# file, the "DEFAULT" line is used, if it is specified.
-#
-# If the name "ALL" appears as a regular expression it is always used
-# in addition to the first matching regex or "DEFAULT".
diff --git a/Lib/CVSROOT/cvswrappers b/Lib/CVSROOT/cvswrappers
deleted file mode 100644
index 5047bf1c5..000000000
--- a/Lib/CVSROOT/cvswrappers
+++ /dev/null
@@ -1,22 +0,0 @@
-# This file describes wrappers and other binary files to CVS.
-#
-# Wrappers are the concept where directories of files are to be
-# treated as a single file.  The intended use is to wrap up a wrapper
-# into a single tar such that the tar archive can be treated as a
-# single binary file in CVS.
-#
-# To solve the problem effectively, it was also necessary to be able to
-# prevent rcsmerge from merging these files.
-#
-# Format of wrapper file ($CVSROOT/CVSROOT/cvswrappers or .cvswrappers)
-#
-#  wildcard	[option value][option value]...
-#
-#  where option is one of
-#  -f		from cvs filter		value: path to filter
-#  -t		to cvs filter		value: path to filter
-#  -m		update methodology	value: MERGE or COPY
-#
-#  and value is a single-quote delimited value.
-#
-# For example:
diff --git a/Lib/CVSROOT/editinfo b/Lib/CVSROOT/editinfo
deleted file mode 100644
index d78886c15..000000000
--- a/Lib/CVSROOT/editinfo
+++ /dev/null
@@ -1,21 +0,0 @@
-# The "editinfo" file is used to allow verification of logging
-# information.  It works best when a template (as specified in the
-# rcsinfo file) is provided for the logging procedure.  Given a
-# template with locations for, a bug-id number, a list of people who
-# reviewed the code before it can be checked in, and an external
-# process to catalog the differences that were code reviewed, the
-# following test can be applied to the code:
-#
-#   Making sure that the entered bug-id number is correct.
-#   Validating that the code that was reviewed is indeed the code being
-#       checked in (using the bug-id number or a seperate review
-#       number to identify this particular code set.).
-#
-# If any of the above test failed, then the commit would be aborted.
-#
-# Actions such as mailing a copy of the report to each reviewer are
-# better handled by an entry in the loginfo file.
-#
-# One thing that should be noted is the the ALL keyword is not
-# supported.  There can be only one entry that matches a given
-# repository.
diff --git a/Lib/CVSROOT/loginfo b/Lib/CVSROOT/loginfo
deleted file mode 100644
index 226e93771..000000000
--- a/Lib/CVSROOT/loginfo
+++ /dev/null
@@ -1,19 +0,0 @@
-# The "loginfo" file is used to control where "cvs commit" log information is
-# sent.  The first entry on a line is a regular expression which is tested
-# against the directory that the change is being made to, relative to the
-# $CVSROOT.  For the first match that is found, the remainder of the line is a
-# filter program that should expect log information on its standard input
-#
-# If the repository name does not match any of the regular expressions in the
-# first field of this file, the "DEFAULT" line is used, if it is specified.
-#
-# If the name "ALL" appears as a regular expression it is always used
-# in addition to the first matching regex or "DEFAULT".
-#
-# The filter program may use one and only one "%s" modifier (ala printf).  If
-# such a "%s" is specified in the filter program, a brief title is included
-# (as one argument, enclosed in single quotes) showing the relative directory
-# name and listing the modified file names.
-#
-# For example:
-#DEFAULT		(echo ""; who am i; echo %s; date; cat) >> $CVSROOT/CVSROOT/commitlog
diff --git a/Lib/CVSROOT/modules b/Lib/CVSROOT/modules
deleted file mode 100644
index cb9e9efc9..000000000
--- a/Lib/CVSROOT/modules
+++ /dev/null
@@ -1,26 +0,0 @@
-# Three different line formats are valid:
-#	key	-a    aliases...
-#	key [options] directory
-#	key [options] directory files...
-#
-# Where "options" are composed of:
-#	-i prog		Run "prog" on "cvs commit" from top-level of module.
-#	-o prog		Run "prog" on "cvs checkout" of module.
-#	-e prog		Run "prog" on "cvs export" of module.
-#	-t prog		Run "prog" on "cvs rtag" of module.
-#	-u prog		Run "prog" on "cvs update" of module.
-#	-d dir		Place module in directory "dir" instead of module name.
-#	-l		Top-level directory only -- do not recurse.
-#
-# NOTE:  If you change any of the "Run" options above, you'll have to
-# release and re-checkout any working directories of these modules.
-#
-# And "directory" is a path to a directory relative to $CVSROOT.
-#
-# The "-a" option specifies an alias.  An alias is interpreted as if
-# everything on the right of the "-a" had been typed on the command line.
-#
-# You can encode a module within a module by using the special '&'
-# character to interpose another module into the current module.  This
-# can be useful for creating a module that consists of many directories
-# spread out over the entire source repository.
diff --git a/Lib/CVSROOT/notify b/Lib/CVSROOT/notify
deleted file mode 100644
index 34f0bc288..000000000
--- a/Lib/CVSROOT/notify
+++ /dev/null
@@ -1,12 +0,0 @@
-# The "notify" file controls where notifications from watches set by
-# "cvs watch add" or "cvs edit" are sent.  The first entry on a line is
-# a regular expression which is tested against the directory that the
-# change is being made to, relative to the $CVSROOT.  If it matches,
-# then the remainder of the line is a filter program that should contain
-# one occurrence of %s for the user to notify, and information on its
-# standard input.
-#
-# "ALL" or "DEFAULT" can be used in place of the regular expression.
-#
-# For example:
-#ALL mail %s -s "CVS notification"
diff --git a/Lib/CVSROOT/rcsinfo b/Lib/CVSROOT/rcsinfo
deleted file mode 100644
index 49e59f4d0..000000000
--- a/Lib/CVSROOT/rcsinfo
+++ /dev/null
@@ -1,13 +0,0 @@
-# The "rcsinfo" file is used to control templates with which the editor
-# is invoked on commit and import.
-#
-# The first entry on a line is a regular expression which is tested
-# against the directory that the change is being made to, relative to the
-# $CVSROOT.  For the first match that is found, then the remainder of the
-# line is the name of the file that contains the template.
-#
-# If the repository name does not match any of the regular expressions in this
-# file, the "DEFAULT" line is used, if it is specified.
-#
-# If the name "ALL" appears as a regular expression it is always used
-# in addition to the first matching regex or "DEFAULT".
diff --git a/Lib/CVSROOT/taginfo b/Lib/CVSROOT/taginfo
deleted file mode 100644
index 274a46dd5..000000000
--- a/Lib/CVSROOT/taginfo
+++ /dev/null
@@ -1,20 +0,0 @@
-# The "taginfo" file is used to control pre-tag checks.
-# The filter on the right is invoked with the following arguments:
-#
-# $1 -- tagname
-# $2 -- operation "add" for tag, "mov" for tag -F, and "del" for tag -d
-# $3 -- repository
-# $4->  file revision [file revision ...]
-#
-# A non-zero exit of the filter program will cause the tag to be aborted.
-#
-# The first entry on a line is a regular expression which is tested
-# against the directory that the change is being committed to, relative
-# to the $CVSROOT.  For the first match that is found, then the remainder
-# of the line is the name of the filter to run.
-#
-# If the repository name does not match any of the regular expressions in this
-# file, the "DEFAULT" line is used, if it is specified.
-#
-# If the name "ALL" appears as a regular expression it is always used
-# in addition to the first matching regex or "DEFAULT".
diff --git a/Lib/Debug/fg_debug.c b/Lib/Debug/fg_debug.c
index ca236a337..9224d9c25 100644
--- a/Lib/Debug/fg_debug.c
+++ b/Lib/Debug/fg_debug.c
@@ -282,9 +282,12 @@ int fgPrintf( fgDebugClass dbg_class, fgDebugPriority prio, char *fmt, ... ) {
 
 
 /* $Log$
-/* Revision 1.4  1998/06/01 17:49:44  curt
-/* Rewrote a slightly ambiguous code fragment (contributed by Charlie Hotchkiss)
+/* Revision 1.1  1999/04/05 21:32:33  curt
+/* Initial revision
 /*
+ * Revision 1.4  1998/06/01 17:49:44  curt
+ * Rewrote a slightly ambiguous code fragment (contributed by Charlie Hotchkiss)
+ *
  * Revision 1.3  1998/05/07 23:03:54  curt
  * Added an entry for AUTOPILOT.
  *
diff --git a/Lib/Debug/logstream.cxx b/Lib/Debug/logstream.cxx
index 182cafda1..6431f3461 100644
--- a/Lib/Debug/logstream.cxx
+++ b/Lib/Debug/logstream.cxx
@@ -63,6 +63,9 @@ logstream::setLogLevels( fgDebugClass c, fgDebugPriority p )
 }
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:33  curt
+// Initial revision
+//
 // Revision 1.2  1999/01/19 20:53:34  curt
 // Portability updates by Bernie Bright.
 //
diff --git a/Lib/Debug/logstream.hxx b/Lib/Debug/logstream.hxx
index f79f1b88a..63d7e2d17 100644
--- a/Lib/Debug/logstream.hxx
+++ b/Lib/Debug/logstream.hxx
@@ -212,6 +212,9 @@ fglog()
 #endif // _LOGSTREAM_H
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:33  curt
+// Initial revision
+//
 // Revision 1.4  1999/03/02 01:01:47  curt
 // Tweaks for compiling with native SGI compilers.
 //
diff --git a/Lib/Lib/Makefile.am b/Lib/Makefile.am
similarity index 100%
rename from Lib/Lib/Makefile.am
rename to Lib/Makefile.am
diff --git a/Lib/Math/fg_geodesy.cxx b/Lib/Math/fg_geodesy.cxx
index af10c1013..4dd73be77 100644
--- a/Lib/Math/fg_geodesy.cxx
+++ b/Lib/Math/fg_geodesy.cxx
@@ -164,6 +164,9 @@ void fgGeodToGeoc( double lat_geod, double alt, double *sl_radius,
 
 $Header$
 $Log$
+Revision 1.1  1999/04/05 21:32:33  curt
+Initial revision
+
 Revision 1.6  1999/03/02 01:01:49  curt
 Tweaks for compiling with native SGI compilers.
 
@@ -256,6 +259,9 @@ Initial Flight Gear revision.
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:33  curt
+// Initial revision
+//
 // Revision 1.6  1999/03/02 01:01:49  curt
 // Tweaks for compiling with native SGI compilers.
 //
diff --git a/Lib/Math/fg_geodesy.hxx b/Lib/Math/fg_geodesy.hxx
index f863d39d8..8b20a22c1 100644
--- a/Lib/Math/fg_geodesy.hxx
+++ b/Lib/Math/fg_geodesy.hxx
@@ -114,6 +114,9 @@ inline Point3D fgGeodToCart(const Point3D& geod) {
 
 $Header$
 $Log$
+Revision 1.1  1999/04/05 21:32:33  curt
+Initial revision
+
 Revision 1.4  1999/01/27 04:46:15  curt
 Portability tweaks by Bernie Bright.
 
@@ -193,6 +196,9 @@ Initial Flight Gear revision.
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:33  curt
+// Initial revision
+//
 // Revision 1.4  1999/01/27 04:46:15  curt
 // Portability tweaks by Bernie Bright.
 //
diff --git a/Lib/Math/fg_random.c b/Lib/Math/fg_random.c
index 31b24be7d..add3ac437 100644
--- a/Lib/Math/fg_random.c
+++ b/Lib/Math/fg_random.c
@@ -71,6 +71,9 @@ double fg_random(void) {
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:33  curt
+// Initial revision
+//
 // Revision 1.10  1998/11/07 19:07:03  curt
 // Enable release builds using the --without-logging option to the configure
 // script.  Also a couple log message cleanups, plus some C to C++ comment
diff --git a/Lib/Math/fg_random.h b/Lib/Math/fg_random.h
index 3ae53a053..e633ce46d 100644
--- a/Lib/Math/fg_random.h
+++ b/Lib/Math/fg_random.h
@@ -48,6 +48,9 @@ double fg_random(void);
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:33  curt
+// Initial revision
+//
 // Revision 1.4  1998/11/07 19:07:04  curt
 // Enable release builds using the --without-logging option to the configure
 // script.  Also a couple log message cleanups, plus some C to C++ comment
diff --git a/Lib/Math/geotest.c b/Lib/Math/geotest.c
new file mode 100644
index 000000000..cdaaec94d
--- /dev/null
+++ b/Lib/Math/geotest.c
@@ -0,0 +1,30 @@
+#include 
+#include 
+
+#include 
+
+void
+main( void )
+{
+    double Lon, Alt, sl_radius;
+    double geodetic_Lat;
+    double geocentric_Lat;
+
+    Lon          = -87.75 * DEG_TO_RAD;
+    geodetic_Lat =  41.83 * DEG_TO_RAD;
+    Alt          = 1.5; /* km */
+
+    printf("Geodetic position = (%.8f, %.8f, %.8f)\n", Lon, geodetic_Lat, Alt); 
+
+    fgGeodToGeoc( geodetic_Lat, Alt, &sl_radius, &geocentric_Lat );
+
+    printf("Geocentric position = (%.8f, %.8f, %.8f)\n", Lon, geocentric_Lat, 
+	   sl_radius + Alt); 
+    printf("new sl_radius = %.8f\n", sl_radius); 
+
+    fgGeocToGeod( geocentric_Lat, sl_radius + Alt, &geodetic_Lat,
+		     &Alt, &sl_radius );
+
+    printf("Geodetic position = (%.8f, %.8f, %.8f)\n", Lon, geodetic_Lat, Alt); 
+    printf("new sl_radius = %.8f\n", sl_radius); 
+}
diff --git a/Lib/Math/interpolater.cxx b/Lib/Math/interpolater.cxx
index 9aabeda2f..c0ebc3f27 100644
--- a/Lib/Math/interpolater.cxx
+++ b/Lib/Math/interpolater.cxx
@@ -103,6 +103,9 @@ fgINTERPTABLE::~fgINTERPTABLE( void ) {
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:33  curt
+// Initial revision
+//
 // Revision 1.7  1999/02/26 22:08:03  curt
 // Added initial support for native SGI compilers.
 //
diff --git a/Lib/Math/interpolater.hxx b/Lib/Math/interpolater.hxx
index 4260ba485..dd0adac5a 100644
--- a/Lib/Math/interpolater.hxx
+++ b/Lib/Math/interpolater.hxx
@@ -62,6 +62,9 @@ public:
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:33  curt
+// Initial revision
+//
 // Revision 1.6  1999/03/02 01:01:50  curt
 // Tweaks for compiling with native SGI compilers.
 //
diff --git a/Lib/Math/inttest.cxx b/Lib/Math/inttest.cxx
new file mode 100644
index 000000000..1fbc286c8
--- /dev/null
+++ b/Lib/Math/inttest.cxx
@@ -0,0 +1,23 @@
+#include 
+#include 
+
+#include "interpolater.hxx"
+
+main() {
+    fgINTERPTABLE test("test.table");
+
+    fgInitDebug();
+
+    printf("-1.0 = %.2f\n", test.interpolate(-1.0));
+    printf("0.0 = %.2f\n", test.interpolate(0.0));
+    printf("2.9 = %.2f\n", test.interpolate(2.9));
+    printf("3.0 = %.2f\n", test.interpolate(3.0));
+    printf("3.5 = %.2f\n", test.interpolate(3.5));
+    printf("4.0 = %.2f\n", test.interpolate(4.0));
+    printf("4.5 = %.2f\n", test.interpolate(4.5));
+    printf("5.2 = %.2f\n", test.interpolate(5.2));
+    printf("8.0 = %.2f\n", test.interpolate(8.0));
+    printf("8.5 = %.2f\n", test.interpolate(8.5));
+    printf("9.0 = %.2f\n", test.interpolate(9.0));
+    printf("10.0 = %.2f\n", test.interpolate(10.0));
+}
diff --git a/Lib/Math/leastsqs.cxx b/Lib/Math/leastsqs.cxx
index 28e2bd35a..20fc331bf 100644
--- a/Lib/Math/leastsqs.cxx
+++ b/Lib/Math/leastsqs.cxx
@@ -135,6 +135,9 @@ double least_squares_max_error(double *x, double *y, int n, double m, double b){
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:33  curt
+// Initial revision
+//
 // Revision 1.1  1999/03/13 17:34:45  curt
 // Moved to math subdirectory.
 //
diff --git a/Lib/Math/leastsqs.hxx b/Lib/Math/leastsqs.hxx
index d8b40c80e..5e1ae4615 100644
--- a/Lib/Math/leastsqs.hxx
+++ b/Lib/Math/leastsqs.hxx
@@ -73,6 +73,9 @@ double least_squares_max_error(double *x, double *y, int n, double m, double b);
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:33  curt
+// Initial revision
+//
 // Revision 1.1  1999/03/13 17:34:45  curt
 // Moved to math subdirectory.
 //
diff --git a/Lib/Math/point3d.hxx b/Lib/Math/point3d.hxx
index 975270779..d6fabc057 100644
--- a/Lib/Math/point3d.hxx
+++ b/Lib/Math/point3d.hxx
@@ -337,6 +337,9 @@ Point3D::distance3Dsquared(const Point3D& a ) const
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:33  curt
+// Initial revision
+//
 // Revision 1.10  1999/03/02 01:01:52  curt
 // Tweaks for compiling with native SGI compilers.
 //
diff --git a/Lib/Math/polar3d.cxx b/Lib/Math/polar3d.cxx
index 7958a83c2..45b25e215 100644
--- a/Lib/Math/polar3d.cxx
+++ b/Lib/Math/polar3d.cxx
@@ -61,6 +61,9 @@ double fgGeodAltFromCart(const Point3D& cp)
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:33  curt
+// Initial revision
+//
 // Revision 1.6  1999/01/27 04:46:19  curt
 // Portability tweaks by Bernie Bright.
 //
diff --git a/Lib/Math/polar3d.hxx b/Lib/Math/polar3d.hxx
index 4118f2d2c..7839a32e5 100644
--- a/Lib/Math/polar3d.hxx
+++ b/Lib/Math/polar3d.hxx
@@ -67,6 +67,9 @@ inline Point3D fgCartToPolar3d(const Point3D& cp) {
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:33  curt
+// Initial revision
+//
 // Revision 1.5  1999/01/27 04:46:20  curt
 // Portability tweaks by Bernie Bright.
 //
diff --git a/Lib/Math/vector.cxx b/Lib/Math/vector.cxx
index 22509cd60..c27f8c0b1 100644
--- a/Lib/Math/vector.cxx
+++ b/Lib/Math/vector.cxx
@@ -129,6 +129,9 @@ double fgPointLineSquared(MAT3vec p, MAT3vec p0, MAT3vec d) {
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:33  curt
+// Initial revision
+//
 // Revision 1.6  1999/03/25 19:02:28  curt
 // Minor optimization tweaks.
 //
diff --git a/Lib/Math/vector.hxx b/Lib/Math/vector.hxx
index 92e897c35..61a2ca5a6 100644
--- a/Lib/Math/vector.hxx
+++ b/Lib/Math/vector.hxx
@@ -63,6 +63,9 @@ double fgPointLineSquared(MAT3vec p, MAT3vec p0, MAT3vec d);
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:33  curt
+// Initial revision
+//
 // Revision 1.4  1998/10/16 23:36:39  curt
 // c++-ifying.
 //
diff --git a/Lib/Misc/fgstream.cxx b/Lib/Misc/fgstream.cxx
index b695315cb..e474937f2 100644
--- a/Lib/Misc/fgstream.cxx
+++ b/Lib/Misc/fgstream.cxx
@@ -140,6 +140,9 @@ skipcomment( istream& in )
 }
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:33  curt
+// Initial revision
+//
 // Revision 1.3  1998/11/06 14:05:12  curt
 // More portability improvements by Bernie Bright.
 //
diff --git a/Lib/Misc/fgstream.hxx b/Lib/Misc/fgstream.hxx
index e8b7c0bb3..10007b2d0 100644
--- a/Lib/Misc/fgstream.hxx
+++ b/Lib/Misc/fgstream.hxx
@@ -100,6 +100,9 @@ istream& skipcomment( istream& in );
 #endif /* _FGSTREAM_HXX */
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:33  curt
+// Initial revision
+//
 // Revision 1.9  1999/03/27 14:04:25  curt
 // Added is_open() so we can check if the open() succeeded.
 //
diff --git a/Lib/Misc/stopwatch.hxx b/Lib/Misc/stopwatch.hxx
index d3bcfade4..2b40bba15 100644
--- a/Lib/Misc/stopwatch.hxx
+++ b/Lib/Misc/stopwatch.hxx
@@ -25,6 +25,9 @@
  *
  ***************************************************************************
  * $Log$
+ * Revision 1.1  1999/04/05 21:32:33  curt
+ * Initial revision
+ *
  * Revision 1.3  1998/11/20 01:01:03  curt
  * FreeBSD support.
  *
diff --git a/Lib/Misc/strutils.cxx b/Lib/Misc/strutils.cxx
index 2f23d83f4..c9a348259 100644
--- a/Lib/Misc/strutils.cxx
+++ b/Lib/Misc/strutils.cxx
@@ -71,6 +71,9 @@ trim( const string& s, const string& trimmings )
 }
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:33  curt
+// Initial revision
+//
 // Revision 1.2  1998/10/18 01:17:15  curt
 // Point3D tweaks.
 //
diff --git a/Lib/Misc/strutils.hxx b/Lib/Misc/strutils.hxx
index b2c47a775..291df5d15 100644
--- a/Lib/Misc/strutils.hxx
+++ b/Lib/Misc/strutils.hxx
@@ -64,6 +64,9 @@ atoi( const string& str )
 #endif // STRUTILS_H
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:33  curt
+// Initial revision
+//
 // Revision 1.6  1999/03/02 01:01:56  curt
 // Tweaks for compiling with native SGI compilers.
 //
diff --git a/Lib/Misc/zfstream.cxx b/Lib/Misc/zfstream.cxx
index 38387cb89..9c4d213ca 100644
--- a/Lib/Misc/zfstream.cxx
+++ b/Lib/Misc/zfstream.cxx
@@ -309,6 +309,9 @@ gzifstream::close()
 #endif
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:33  curt
+// Initial revision
+//
 // Revision 1.3  1999/01/19 20:41:48  curt
 // Portability updates contributed by Bernie Bright.
 //
diff --git a/Lib/Misc/zfstream.hxx b/Lib/Misc/zfstream.hxx
index 714393456..1c081aab8 100644
--- a/Lib/Misc/zfstream.hxx
+++ b/Lib/Misc/zfstream.hxx
@@ -154,6 +154,9 @@ struct gzifstream_base
 #endif // _zfstream_hxx
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:33  curt
+// Initial revision
+//
 // Revision 1.9  1999/03/08 22:00:12  curt
 // Tweak for native SGI compilers.
 //
diff --git a/Lib/PUI/Makefile.am b/Lib/PUI/Makefile.am
deleted file mode 100644
index aa38a0cdb..000000000
--- a/Lib/PUI/Makefile.am
+++ /dev/null
@@ -1,24 +0,0 @@
-noinst_LIBRARIES = libPUI.a
-
-EXTRA_DIST = complex.cxx simple.cxx
-
-libPUI_a_SOURCES = \
-	pu.h puLocal.h \
-	pu.cxx \
-	puBox.cxx \
-	puButton.cxx \
-	puButtonBox.cxx \
-	puDialogBox.cxx \
-	puFrame.cxx \
-	puInput.cxx \
-	puInterface.cxx \
-	puMenuBar.cxx \
-	puObject.cxx \
-	puOneShot.cxx \
-	puPopup.cxx \
-	puPopupMenu.cxx \
-	puSlider.cxx \
-	puText.cxx
-
-INCLUDES += -I$(top_builddir)
-
diff --git a/Lib/PUI/complex.cxx b/Lib/PUI/complex.cxx
deleted file mode 100644
index 6c5d93a73..000000000
--- a/Lib/PUI/complex.cxx
+++ /dev/null
@@ -1,332 +0,0 @@
-#include 
-#include 
-#include 
-#include 
-#ifdef WIN32
-#include 
-#else
-#include 
-#endif
-#include 
-#include 
-#include "pu.h"
-
-/***********************************\
-*                                   *
-* These are the PUI widget pointers *
-*                                   *
-\***********************************/
-
-puMenuBar   *main_menu_bar ;
-puButton    *hide_menu_button ;
-puDialogBox *dialog_box ;
-puText      *dialog_box_message ;
-puOneShot   *dialog_box_ok_button ;
-puText      *timer_text ;
-puSlider    *rspeedSlider;
-
-
-/***********************************\
-*                                   *
-*  This is a generic tumbling cube  *
-*                                   *
-\***********************************/
-
-GLfloat light_diffuse [] = {0.0, 1.0, 0.0, 1.0} ;  /* Red diffuse light. */
-GLfloat light_position[] = {1.0, 1.0, 1.0, 0.0} ;  /* Infinite light location. */
-
-GLfloat cube_n[6][3] =  /* Normals */
-{
- {-1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 0.0, 0.0},
- { 0.0,-1.0, 0.0}, {0.0, 0.0, 1.0}, {0.0, 0.0,-1.0}
-} ;
-
-GLint cube_i[6][4] =  /* Vertex indices */
-{
-  {0, 1, 2, 3}, {3, 2, 6, 7}, {7, 6, 5, 4},
-  {4, 5, 1, 0}, {5, 6, 2, 1}, {7, 4, 0, 3}
-} ;
-
-GLfloat cube_v[8][3] =  /* Vertices */
-{
-  {-1.0,-1.0, 1.0}, {-1.0,-1.0,-1.0}, {-1.0, 1.0,-1.0}, {-1.0, 1.0, 1.0},
-  { 1.0,-1.0, 1.0}, { 1.0,-1.0,-1.0}, { 1.0, 1.0,-1.0}, { 1.0, 1.0, 1.0}
-} ;
-
-
-static int firsttime;
-
-void drawCube (void)
-{
-
-  if ( firsttime )
-  {
-    /*
-      Deliberately do this only once - it's a better test of
-      PUI's attempts to leave the OpenGL state undisturbed
-    */
-
-    firsttime = FALSE ;
-    glLightfv      ( GL_LIGHT0, GL_DIFFUSE , light_diffuse  ) ;
-    glLightfv      ( GL_LIGHT0, GL_POSITION, light_position ) ;
-    glEnable       ( GL_LIGHT0     ) ;
-    glEnable       ( GL_LIGHTING   ) ;
-    glEnable       ( GL_DEPTH_TEST ) ;
-    glMatrixMode   ( GL_PROJECTION ) ;
-    gluPerspective ( 40.0, 1.0, 1.0, 10.0 ) ;
-    glMatrixMode   ( GL_MODELVIEW ) ;
-    gluLookAt      ( 0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0 ) ;
-    glTranslatef   ( 0.0, 0.0, -1.0 ) ;
-    glRotatef      ( 60.0, 1.0, 0.0, 0.0 ) ;
-  }
-
-  glCullFace     ( GL_FRONT ) ;
-  glEnable       ( GL_CULL_FACE ) ;
-  //  glRotatef ( 1.0f, 0.0, 0.0, 1.0 ) ;  /* Tumble that cube! */
-
-  glBegin ( GL_QUADS ) ;
-
-  for ( int i = 0 ; i < 6 ; i++ )
-  {
-    glNormal3fv ( &cube_n[i][0] ) ;
-    glVertex3fv ( cube_v[cube_i[i][0]] ) ; glVertex3fv ( cube_v[cube_i[i][1]] ) ;
-    glVertex3fv ( cube_v[cube_i[i][2]] ) ; glVertex3fv ( cube_v[cube_i[i][3]] ) ;
-  }
-
-  glEnd () ;
-}
-
-/********************************\
-*                                *
-* End of cube renderer in OpenGL * 
-*                                *
-\********************************/
-
-
-/**************************************\
-*                                      *
-* These three functions capture mouse  *
-* and keystrokes (special and mundane) *
-* from GLUT and pass them on to PUI.   *
-*                                      *
-\**************************************/
-
-static void specialfn ( int key, int, int )
-{
-  puKeyboard ( key + PU_KEY_GLUT_SPECIAL_OFFSET, PU_DOWN ) ;
-  glutPostRedisplay () ;
-}
-
-static void keyfn ( unsigned char key, int, int )
-{
-  puKeyboard ( key, PU_DOWN ) ;
-  glutPostRedisplay () ;
-}
-
-static void motionfn ( int x, int y )
-{
-  puMouse ( x, y ) ;
-  glutPostRedisplay () ;
-}
-
-static void mousefn ( int button, int updown, int x, int y )
-{
-  puMouse ( button, updown, x, y ) ;
-  glutPostRedisplay () ;
-}
-
-/**************************************\
-*                                      *
-* This function redisplays the PUI and *
-* the tumbling cube, flips the double  *
-* buffer and then asks GLUT to post a  *
-* redisplay command - so we re-render  *
-* at maximum rate.                     *
-*                                      *
-\**************************************/
-
-static void displayfn (void)
-{
-  /* Clear the screen */
-
-  glClearColor ( 0.0, 0.0, 0.0, 1.0 ) ;
-  glClear      ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ;
-
-  /* Draw the tumbling cube */
-
-  float val ; rspeedSlider->getValue ( &val ) ;
-
-  glRotatef( 4*val, 15.0, 10.0 , 5.0 );
-
-  drawCube  () ;
-
-  /* Update the 'timer' */
-
-  time_t t = time ( NULL ) ;
-  timer_text -> setLabel ( ctime ( & t ) ) ;
-
-  /* Make PUI redraw */
-
-  puDisplay () ;
-  
-  /* Off we go again... */
-
-  glutSwapBuffers   () ;
-  glutPostRedisplay () ;
-}
-
-
-/***********************************\
-*                                   *
-* Here are the PUI widget callback  *
-* functions.                        *
-*                                   *
-\***********************************/
-
-void hide_menu_cb ( puObject *cb )
-{
-  if ( cb -> getValue () )
-  {
-    main_menu_bar -> reveal () ;
-    hide_menu_button->setLegend ( "Hide Menu" ) ;
-  }
-  else
-  {
-    main_menu_bar -> hide   () ;
-    hide_menu_button->setLegend ( "Show Menu" ) ;
-  }
-}
-
-
-void go_away_cb ( puObject * )
-{
-  /*
-    Delete the dialog box when its 'OK' button is pressed.
-
-    This seems to crash on MSVC compilers - probably because
-    I delete dialog_box - whose member function is calling
-    this function. Hence we return to something that is
-    in a distinctly 'iffy' state.
-  */
-
-  delete dialog_box ;
-  dialog_box = NULL ;
-}
-
-void mk_dialog ( char *txt )
-{
-  dialog_box = new puDialogBox ( 150, 50 ) ;
-  {
-    new puFrame ( 0, 0, 400, 100 ) ;
-    dialog_box_message   = new puText         ( 10, 70 ) ;
-    dialog_box_message   -> setLabel          ( txt ) ;
-    dialog_box_ok_button = new puOneShot      ( 180, 10, 240, 50 ) ;
-    dialog_box_ok_button -> setLegend         ( "OK" ) ;
-    dialog_box_ok_button -> makeReturnDefault ( TRUE ) ;
-    dialog_box_ok_button -> setCallback       ( go_away_cb ) ;
-  }
-  dialog_box -> close  () ;
-  dialog_box -> reveal () ;
-}
-
-void ni_cb ( puObject * )
-{
-  mk_dialog ( "Sorry, that function isn't implemented" ) ;
-}
-
-void about_cb ( puObject * )
-{
-  mk_dialog ( "This is the PUI 'complex' program" ) ;
-}
-
-void help_cb ( puObject * )
-{
-  mk_dialog ( "Sorry, no help is available for this demo" ) ;
-}
-
-void edit_cb ( puObject * )
-{
-}
-
-void exit_cb ( puObject * )
-{
-  fprintf ( stderr, "Exiting PUI demo program.\n" ) ;
-  exit ( 1 ) ;
-}
-
-/* Menu bar entries: */
-
-char      *file_submenu    [] = {  "Exit", "Close", "--------", "Print", "--------", "Save", "New", NULL } ;
-puCallback file_submenu_cb [] = { exit_cb, exit_cb,       NULL, ni_cb  ,       NULL,  ni_cb, ni_cb, NULL } ;
-
-char      *edit_submenu    [] = { "Edit text", NULL } ;
-puCallback edit_submenu_cb [] = {     edit_cb, NULL } ;
-
-char      *help_submenu    [] = { "About...",  "Help", NULL } ;
-puCallback help_submenu_cb [] = {   about_cb, help_cb, NULL } ;
-
-
-void sliderCB( puObject *sliderObj)
-{
-  glutPostRedisplay();
-}
-
-int main ( int argc, char **argv )
-{
-  firsttime = TRUE;
-
-#ifdef VOODOO
-  glutInitWindowPosition(   0,   0 ) ;
-#endif
-  glutInitWindowSize    ( 640, 480 ) ;
-  glutInit              ( &argc, argv ) ;
-  glutInitDisplayMode   ( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ) ;
-  glutCreateWindow      ( "Complex PUI Application"  ) ;
-  glutDisplayFunc       ( displayfn ) ;
-  glutKeyboardFunc      ( keyfn     ) ;
-  glutSpecialFunc       ( specialfn ) ;
-  glutMouseFunc         ( mousefn   ) ;
-  glutMotionFunc        ( motionfn  ) ;
-  glutPassiveMotionFunc ( motionfn  ) ;
-  glutIdleFunc          ( displayfn ) ;
-
-  puInit () ;
-
-#ifdef VOODOO
-  puShowCursor () ;
-#endif
-
-  puSetDefaultStyle        ( PUSTYLE_SMALL_SHADED ) ;
-  puSetDefaultColourScheme ( 0.8, 0.8, 0.8 ) ;
-
-  timer_text = new puText ( 300, 10 ) ;
-  timer_text -> setColour ( PUCOL_LABEL, 1.0, 1.0, 1.0 ) ;
-
-  /* Make a button to hide the menu bar */
-
-  hide_menu_button = new puButton     ( 10, 10, 150, 50 ) ;
-  hide_menu_button->setValue          (    TRUE      ) ;
-  hide_menu_button->setLegend         ( "Hide Menu"  ) ;
-  hide_menu_button->setCallback       ( hide_menu_cb ) ;
-  hide_menu_button->makeReturnDefault (    TRUE      ) ;
-
-  /* Make the menu bar */
-
-  main_menu_bar = new puMenuBar () ;
-  {
-    main_menu_bar -> add_submenu ( "File", file_submenu, file_submenu_cb ) ;
-    main_menu_bar -> add_submenu ( "Edit", edit_submenu, edit_submenu_cb ) ;
-    main_menu_bar -> add_submenu ( "Help", help_submenu, help_submenu_cb ) ;
-  }
-  main_menu_bar -> close () ; 
-
-  rspeedSlider = new puSlider (20,80,150,TRUE);
-  rspeedSlider->setDelta(0.1);
-  rspeedSlider->setCBMode( PUSLIDER_DELTA );
-  rspeedSlider->setCallback(sliderCB);
-
-  glutMainLoop () ;
-  return 0 ;
-}
-
-
diff --git a/Lib/PUI/pu.cxx b/Lib/PUI/pu.cxx
deleted file mode 100644
index 5e47cf054..000000000
--- a/Lib/PUI/pu.cxx
+++ /dev/null
@@ -1,332 +0,0 @@
-
-#include "puLocal.h"
-
-#ifdef PU_NOT_USING_GLUT
-#include 
-#include 
-#endif
-
-#define PU_STRING_X_FUDGE 6
-#define PU_STRING_Y_FUDGE 6
-
-int puRefresh = TRUE ;
-
-#ifdef PU_NOT_USING_GLUT
-
-static int puWindowWidth  = 400 ;
-static int puWindowHeight = 400 ;
-
-int puGetWindowHeight () { return puWindowHeight ; }
-int puGetWindowWidth  () { return puWindowWidth  ; }
-
-void puSetWindowSize ( int width, int height )
-{
-  puWindowWidth  = width  ;
-  puWindowHeight = height ;
-}
-
-static int fontBase = 0;
-static int fontSize[257];
-#else
-
-int puGetWindowHeight () { return glutGet ( (GLenum) GLUT_WINDOW_HEIGHT ) ; }
-int puGetWindowWidth  () { return glutGet ( (GLenum) GLUT_WINDOW_WIDTH  ) ; }
-
-void puSetWindowSize ( int width, int height )
-{
-  fprintf ( stderr, "PUI: puSetWindowSize shouldn't be used with GLUT.\n" ) ;
-}
-
-#endif
-
-puColour _puDefaultColourTable[] =
-{
-  { 0.5f, 0.5f, 0.5f, 1.0f }, /* PUCOL_FOREGROUND */
-  { 0.3f, 0.3f, 0.3f, 1.0f }, /* PUCOL_BACKGROUND */
-  { 0.7f, 0.7f, 0.7f, 1.0f }, /* PUCOL_HIGHLIGHT  */
-  { 0.0f, 0.0f, 0.0f, 1.0f }, /* PUCOL_LABEL      */
-  { 1.0f, 1.0f, 1.0f, 1.0f }, /* PUCOL_TEXT       */
-
-  { 0.0f, 0.0f, 0.0f, 0.0f }  /* ILLEGAL */
-} ;
- 
-
-puValue::~puValue () {}  
-
-static int _puCursor_enable = FALSE ;
-static int _puCursor_x      = 0 ;
-static int _puCursor_y      = 0 ;
-static float _puCursor_bgcolour [4] = { 1.0f, 1.0f, 1.0f, 1.0f } ; 
-static float _puCursor_fgcolour [4] = { 0.0f, 0.0f, 0.0f, 1.0f } ;  
-
-void   puHideCursor ( void ) { _puCursor_enable = FALSE ; }
-void   puShowCursor ( void ) { _puCursor_enable = TRUE  ; }
-int    puCursorIsHidden ( void ) { return ! _puCursor_enable ; }
-
-void puCursor ( int x, int y )
-{
-  _puCursor_x = x ;
-  _puCursor_y = y ;
-}
-
-int puGetStringDescender ( void *fnt )
-{
-  if ( fnt == NULL )
-    fnt = PUFONT_9_BY_15 ;
-
-  if ( fnt == PUFONT_8_BY_13        ) return 2 ;
-  if ( fnt == PUFONT_9_BY_15        ) return 3 ;
-  if ( fnt == PUFONT_TIMES_ROMAN_10 ) return 2 ;
-  if ( fnt == PUFONT_TIMES_ROMAN_24 ) return 5 ;
-  if ( fnt == PUFONT_HELVETICA_10   ) return 2 ;
-  if ( fnt == PUFONT_HELVETICA_12   ) return 3 ;
-  if ( fnt == PUFONT_HELVETICA_18   ) return 4 ;
-
-  return 0 ;
-}
-
-int puGetStringHeight ( void *fnt )
-{
-  /* Height *excluding* descender */
-  if ( fnt == NULL )
-    fnt = PUFONT_9_BY_15 ;
-
-  if ( fnt == PUFONT_8_BY_13        ) return  9 ;
-  if ( fnt == PUFONT_9_BY_15        ) return 10 ;
-  if ( fnt == PUFONT_TIMES_ROMAN_10 ) return  7 ;
-  if ( fnt == PUFONT_TIMES_ROMAN_24 ) return 17 ;
-  if ( fnt == PUFONT_HELVETICA_10   ) return  8 ;
-  if ( fnt == PUFONT_HELVETICA_12   ) return  9 ;
-  if ( fnt == PUFONT_HELVETICA_18   ) return 14 ;
-
-  return 0 ;
-}
-
-int puGetStringWidth ( void *fnt, char *str )
-{
-
-  if ( str == NULL )
-    return 0 ;
-
-  int res = 0 ;
-
-#ifdef PU_NOT_USING_GLUT
-  while ( *str != '\0' )
-  {
-    res += fontSize [ *str ] ;
-    str++ ;
-  }
-#else
-  if ( fnt == NULL )
-    fnt = PUFONT_9_BY_15 ;
-
-  while ( *str != '\0' )
-  {
-    res += glutBitmapWidth ( fnt, *str ) ;
-    str++ ;
-  }
-#endif
-
-  return res ;
-}
-
-
-void puDrawString ( void *fnt, char *str, int x, int y )
-{
-  if ( str == NULL )
-    return ;
-
-  glRasterPos2f((float)x, (float)y); 
-
-#ifdef PU_NOT_USING_GLUT
-  /*
-    Display a string: 
-       indicate start of glyph display lists 
-  */
-
-  glListBase (fontBase);
-
-  /* Now draw the characters in a string */
-
-  int len = strlen(str);
-  glCallLists(len, GL_UNSIGNED_BYTE, str); 
-  glListBase(0);
-#else
-  if ( fnt == NULL )
-    fnt = PUFONT_9_BY_15 ;
-
-  while ( *str != '\0' )
-  {
-    glutBitmapCharacter ( fnt, *str ) ;
-    str++ ;
-  }
-#endif
-}
-
-
-static void puDrawCursor ( int x, int y )
-{
-  glColor4fv ( _puCursor_bgcolour ) ;  
-
-  glBegin    ( GL_TRIANGLES ) ;
-  glVertex2i ( x, y ) ;
-  glVertex2i ( x + 13, y -  4 ) ;
-  glVertex2i ( x +  4, y - 13 ) ;
-
-  glVertex2i ( x +  8, y -  3 ) ;
-  glVertex2i ( x + 17, y - 12 ) ;
-  glVertex2i ( x + 12, y - 17 ) ;
-
-  glVertex2i ( x + 12, y - 17 ) ;
-  glVertex2i ( x +  3, y -  8 ) ;
-  glVertex2i ( x +  8, y -  3 ) ;
-  glEnd      () ;
-
-  glColor4fv ( _puCursor_fgcolour ) ;  
-
-  glBegin    ( GL_TRIANGLES ) ;
-  glVertex2i ( x+1, y-1 ) ;
-  glVertex2i ( x + 11, y -  4 ) ;
-  glVertex2i ( x +  4, y - 11 ) ;
-
-  glVertex2i ( x +  8, y -  5 ) ;
-  glVertex2i ( x + 15, y - 12 ) ;
-  glVertex2i ( x + 12, y - 15 ) ;
-
-  glVertex2i ( x + 12, y - 15 ) ;
-  glVertex2i ( x +  5, y -  8 ) ;
-  glVertex2i ( x +  8, y -  5 ) ;
-  glEnd      () ;
-}
-
-void  puInit ( void )
-{
-  static int firsttime = TRUE ;
-
-  if ( firsttime )
-  {
-    puInterface *base_interface = new puInterface ( 0, 0 ) ;
-    puPushInterface     ( base_interface ) ;
-    puPushLiveInterface ( base_interface ) ;
-    firsttime = FALSE ;
-#ifdef PU_NOT_USING_GLUT
-
-    /* Create bitmaps for the device context font's first 256 glyphs */
-
-    fontBase = glGenLists(256);
-    assert(fontBase);
-    HDC hdc = wglGetCurrentDC();
-
-    /* Make the system font the device context's selected font */
-
-    SelectObject (hdc, GetStockObject (SYSTEM_FONT)); 
-
-    int *tempSize = &fontSize[1];
-
-    if ( ! GetCharWidth32 ( hdc, 1, 255, tempSize ) &&
-         ! GetCharWidth   ( hdc, 1, 255, tempSize ) )
-    {
-      LPVOID lpMsgBuf ;
-
-      FormatMessage ( FORMAT_MESSAGE_ALLOCATE_BUFFER |
-	              FORMAT_MESSAGE_FROM_SYSTEM,
-	              NULL,
-	              GetLastError(),
-	              MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
-	              (LPTSTR) &lpMsgBuf,
-	              0, NULL ) ;
-
-      fprintf ( stderr, "PUI: Error: %s\n", (char *)lpMsgBuf ) ;
-      LocalFree ( lpMsgBuf ) ;
-    }
-
-    wglUseFontBitmaps ( hdc, 0, 256, fontBase ) ;
-#endif
-  }
-}
-
-static void puSetOpenGLState ( void )
-{
-  int w = puGetWindowWidth  () ;
-  int h = puGetWindowHeight () ;
-
-  glPushAttrib   ( GL_ENABLE_BIT | GL_VIEWPORT_BIT | GL_TRANSFORM_BIT ) ;
-  glDisable      ( GL_LIGHTING   ) ;
-  glDisable      ( GL_FOG        ) ;
-  glDisable      ( GL_TEXTURE_2D ) ;
-  glDisable      ( GL_DEPTH_TEST ) ;
-  glDisable      ( GL_CULL_FACE  ) ;
- 
-  glViewport     ( 0, 0, w, h ) ;
-  glMatrixMode   ( GL_PROJECTION ) ;
-  glPushMatrix   () ;
-  glLoadIdentity () ;
-  gluOrtho2D     ( 0, w, 0, h ) ;
-  glMatrixMode   ( GL_MODELVIEW ) ;
-  glPushMatrix   () ;
-  glLoadIdentity () ;
-}
-
-static void puRestoreOpenGLState ( void )
-{
-  glMatrixMode   ( GL_PROJECTION ) ;
-  glPopMatrix    () ;
-  glMatrixMode   ( GL_MODELVIEW ) ;
-  glPopMatrix    () ;
-  glPopAttrib    () ;
-}
-
-
-void  puDisplay ( void )
-{
-  puSetOpenGLState () ;
-  puGetUltimateLiveInterface () -> draw ( 0, 0 ) ;
-
-  int h = puGetWindowHeight () ;
-
-  if ( _puCursor_enable )
-    puDrawCursor ( _puCursor_x,
-                   h - _puCursor_y ) ;
-
-  puRestoreOpenGLState () ;
-}
-
-int puKeyboard ( int key, int updown )
-{
-  return puGetBaseLiveInterface () -> checkKey ( key, updown ) ;
-}
-
-
-static int last_buttons = 0 ;
-int puMouse ( int button, int updown, int x, int y )
-{
-  puCursor ( x, y ) ;
-
-  int h = puGetWindowHeight () ;
-
-  if ( updown == PU_DOWN )
-    last_buttons |=  ( 1 << button ) ;
-  else
-    last_buttons &= ~( 1 << button ) ;
-
-  return puGetBaseLiveInterface () -> checkHit ( button, updown, x,
-                                 h - y ) ;
-}
-
-int puMouse ( int x, int y )
-{
-  puCursor ( x, y ) ;
-
-  if ( last_buttons == 0 )
-    return FALSE ;
-
-  int button = (last_buttons & (1< checkHit ( button, PU_DRAG, x,
-                                 h - y ) ;
-}
-
diff --git a/Lib/PUI/pu.h b/Lib/PUI/pu.h
deleted file mode 100644
index 02f99adab..000000000
--- a/Lib/PUI/pu.h
+++ /dev/null
@@ -1,805 +0,0 @@
-#ifndef _PU_H_
-#define _PU_H_
-
-#ifdef HAVE_CONFIG_H
-#  include 
-#endif
-
-#ifdef HAVE_WINDOWS_H
-#  include 
-#endif
-
-#include 
-#include 
-#include 
-
-#ifdef PU_NOT_USING_GLUT
-#include 
-#include 
-#include 
-#else
-#include 
-#endif
-
-#ifndef TRUE
-#define TRUE  1
-#define FALSE 0
-#endif
-
-/*
-  Webster's Dictionary (for American English) permits
-  Color or Colour as acceptable spellings - but
-  The Oxford English Dictionary (for English) only
-  permits Colour.
-
-  Hence, the logical thing to do is to use 'colour',
-  which *ought* to be acceptable on both sides of
-  the atlantic.
-
-  However, as a concession to the illogical:
-*/
-
-#define setColorScheme          setColourScheme
-#define setColor                setColour
-#define getColor                getColour
-#define puColor                 puColour
-#define puSetColor              puSetColour
-#define puSetDefaultColorScheme puSetDefaultColourScheme
-#define puGetDefaultColorScheme puGetDefaultColourScheme
-
-
-typedef void *puFont ;
-
-#ifdef PU_NOT_USING_GLUT
-#define PU_LEFT_BUTTON		0
-#define PU_LEFT_BUTTON		0
-#define PU_MIDDLE_BUTTON	1
-#define PU_RIGHT_BUTTON		2
-#define PU_DOWN			0
-#define PU_UP		        1
-
-#define PUFONT_8_BY_13        ((void*)3)
-#define PUFONT_9_BY_15        ((void*)2)
-#define PUFONT_TIMES_ROMAN_10 ((void*)4)
-#define PUFONT_TIMES_ROMAN_24 ((void*)5)
-#define PUFONT_HELVETICA_10   ((void*)6)
-#define PUFONT_HELVETICA_12   ((void*)7)
-#define PUFONT_HELVETICA_18   ((void*)8)
-
-#else
-
-#define PUFONT_8_BY_13        GLUT_BITMAP_8_BY_13
-#define PUFONT_9_BY_15        GLUT_BITMAP_9_BY_15
-#define PUFONT_TIMES_ROMAN_10 GLUT_BITMAP_TIMES_ROMAN_10
-#define PUFONT_TIMES_ROMAN_24 GLUT_BITMAP_TIMES_ROMAN_24
-#define PUFONT_HELVETICA_10   GLUT_BITMAP_HELVETICA_10
-#define PUFONT_HELVETICA_12   GLUT_BITMAP_HELVETICA_12
-#define PUFONT_HELVETICA_18   GLUT_BITMAP_HELVETICA_18
-
-#define PU_LEFT_BUTTON      GLUT_LEFT_BUTTON
-#define PU_MIDDLE_BUTTON    GLUT_MIDDLE_BUTTON
-#define PU_RIGHT_BUTTON     GLUT_RIGHT_BUTTON
-#define PU_DOWN             GLUT_DOWN
-#define PU_UP               GLUT_UP
-#endif	// PU_NOT_USING_GLUT
-
-#define PU_UP_AND_DOWN   254
-#define PU_DRAG          255
-#define PU_CONTINUAL     PU_DRAG
-
-#define PU_KEY_GLUT_SPECIAL_OFFSET  256
-
-#ifdef PU_NOT_USING_GLUT
-#define PU_KEY_F1        (1		+ PU_KEY_GLUT_SPECIAL_OFFSET)
-#define PU_KEY_F2        (2		+ PU_KEY_GLUT_SPECIAL_OFFSET)
-#define PU_KEY_F3        (3		+ PU_KEY_GLUT_SPECIAL_OFFSET)
-#define PU_KEY_F4        (4	    + PU_KEY_GLUT_SPECIAL_OFFSET)
-#define PU_KEY_F5        (5		+ PU_KEY_GLUT_SPECIAL_OFFSET)
-#define PU_KEY_F6        (6		+ PU_KEY_GLUT_SPECIAL_OFFSET)
-#define PU_KEY_F7        (7		+ PU_KEY_GLUT_SPECIAL_OFFSET)
-#define PU_KEY_F8        (8		+ PU_KEY_GLUT_SPECIAL_OFFSET)
-#define PU_KEY_F9        (9		+ PU_KEY_GLUT_SPECIAL_OFFSET)
-#define PU_KEY_F10       (10		+ PU_KEY_GLUT_SPECIAL_OFFSET)
-#define PU_KEY_F11       (11		+ PU_KEY_GLUT_SPECIAL_OFFSET)
-#define PU_KEY_F12       (12		+ PU_KEY_GLUT_SPECIAL_OFFSET)
-#define PU_KEY_LEFT      (100		+ PU_KEY_GLUT_SPECIAL_OFFSET)
-#define PU_KEY_UP        (101		+ PU_KEY_GLUT_SPECIAL_OFFSET)
-#define PU_KEY_RIGHT     (102		+ PU_KEY_GLUT_SPECIAL_OFFSET)
-#define PU_KEY_DOWN      (103		+ PU_KEY_GLUT_SPECIAL_OFFSET)
-#define PU_KEY_PAGE_UP   (104		+ PU_KEY_GLUT_SPECIAL_OFFSET)
-#define PU_KEY_PAGE_DOWN (105		+ PU_KEY_GLUT_SPECIAL_OFFSET)
-#define PU_KEY_HOME      (106		+ PU_KEY_GLUT_SPECIAL_OFFSET)
-#define PU_KEY_END       (107		+ PU_KEY_GLUT_SPECIAL_OFFSET)
-#define PU_KEY_INSERT    (108		+ PU_KEY_GLUT_SPECIAL_OFFSET)
-
-#else
-#define PU_KEY_F1        (GLUT_KEY_F1        + PU_KEY_GLUT_SPECIAL_OFFSET)
-#define PU_KEY_F2        (GLUT_KEY_F2        + PU_KEY_GLUT_SPECIAL_OFFSET)
-#define PU_KEY_F3        (GLUT_KEY_F3        + PU_KEY_GLUT_SPECIAL_OFFSET)
-#define PU_KEY_F4        (GLUT_KEY_F4        + PU_KEY_GLUT_SPECIAL_OFFSET)
-#define PU_KEY_F5        (GLUT_KEY_F5        + PU_KEY_GLUT_SPECIAL_OFFSET)
-#define PU_KEY_F6        (GLUT_KEY_F6        + PU_KEY_GLUT_SPECIAL_OFFSET)
-#define PU_KEY_F7        (GLUT_KEY_F7        + PU_KEY_GLUT_SPECIAL_OFFSET)
-#define PU_KEY_F8        (GLUT_KEY_F8        + PU_KEY_GLUT_SPECIAL_OFFSET)
-#define PU_KEY_F9        (GLUT_KEY_F9        + PU_KEY_GLUT_SPECIAL_OFFSET)
-#define PU_KEY_F10       (GLUT_KEY_F10       + PU_KEY_GLUT_SPECIAL_OFFSET)
-#define PU_KEY_F11       (GLUT_KEY_F11       + PU_KEY_GLUT_SPECIAL_OFFSET)
-#define PU_KEY_F12       (GLUT_KEY_F12       + PU_KEY_GLUT_SPECIAL_OFFSET)
-#define PU_KEY_LEFT      (GLUT_KEY_LEFT      + PU_KEY_GLUT_SPECIAL_OFFSET)
-#define PU_KEY_UP        (GLUT_KEY_UP        + PU_KEY_GLUT_SPECIAL_OFFSET)
-#define PU_KEY_RIGHT     (GLUT_KEY_RIGHT     + PU_KEY_GLUT_SPECIAL_OFFSET)
-#define PU_KEY_DOWN      (GLUT_KEY_DOWN      + PU_KEY_GLUT_SPECIAL_OFFSET)
-#define PU_KEY_PAGE_UP   (GLUT_KEY_PAGE_UP   + PU_KEY_GLUT_SPECIAL_OFFSET)
-#define PU_KEY_PAGE_DOWN (GLUT_KEY_PAGE_DOWN + PU_KEY_GLUT_SPECIAL_OFFSET)
-#define PU_KEY_HOME      (GLUT_KEY_HOME      + PU_KEY_GLUT_SPECIAL_OFFSET)
-#define PU_KEY_END       (GLUT_KEY_END       + PU_KEY_GLUT_SPECIAL_OFFSET)
-#define PU_KEY_INSERT    (GLUT_KEY_INSERT    + PU_KEY_GLUT_SPECIAL_OFFSET)
-#endif	// PU_NOT_USING_GLUT
-
-#define PUPLACE_DEFAULT  PUPLACE_RIGHT
-#define PUPLACE_ABOVE    0
-#define PUPLACE_BELOW    1
-#define PUPLACE_LEFT     2
-#define PUPLACE_RIGHT    3
-
-#define PUCOL_FOREGROUND 0
-#define PUCOL_BACKGROUND 1
-#define PUCOL_HIGHLIGHT  2
-#define PUCOL_LABEL      3
-#define PUCOL_LEGEND     4
-#define PUCOL_MAX        5
-
-#define PUSLIDER_CLICK   0
-#define PUSLIDER_ALWAYS  1
-#define PUSLIDER_DELTA   2
-
-/* These styles may be negated to get 'highlighted' graphics */
-
-#define PUSTYLE_DEFAULT    PUSTYLE_SHADED
-#define PUSTYLE_NONE       0
-#define PUSTYLE_PLAIN      1
-#define PUSTYLE_BEVELLED   2
-#define PUSTYLE_BOXED      3
-#define PUSTYLE_DROPSHADOW 4
-#define PUSTYLE_SPECIAL_UNDERLINED 5
-#define PUSTYLE_SMALL_BEVELLED     6
-#define PUSTYLE_RADIO      7
-#define PUSTYLE_SHADED     8
-#define PUSTYLE_SMALL_SHADED   9
-#define PUSTYLE_MAX        10
-
-/* These are the gaps that we try to leave around text objects */
-
-#define PUSTR_TGAP   5
-#define PUSTR_BGAP   5
-#define PUSTR_LGAP   5
-#define PUSTR_RGAP   5
-#define PUSTR_MAX_HEIGHT  ( 25 + PUSTR_TGAP + PUSTR_BGAP )
-
-#define PU_RADIO_BUTTON_SIZE 16
-
-extern int puRefresh ;
-
-#define PUCLASS_VALUE            0x00000001
-#define PUCLASS_OBJECT           0x00000002
-#define PUCLASS_INTERFACE        0x00000004
-#define PUCLASS_FRAME            0x00000008
-#define PUCLASS_TEXT             0x00000010
-#define PUCLASS_BUTTON           0x00000020
-#define PUCLASS_ONESHOT          0x00000040
-#define PUCLASS_POPUP            0x00000080
-#define PUCLASS_POPUPMENU        0x00000100
-#define PUCLASS_MENUBAR          0x00000200
-#define PUCLASS_INPUT            0x00000400
-#define PUCLASS_BUTTONBOX        0x00000800
-#define PUCLASS_SLIDER           0x00001000
-#define PUCLASS_DIALOGBOX        0x00002000
-
-/* This function is not required for GLUT programs */
-void puSetWindowSize ( int width, int height ) ;
-
-int  puGetWindowHeight () ;
-int  puGetWindowWidth  () ;
-
-class puValue            ;
-class puObject           ;
-class puInterface        ;
-class puButtonBox        ;
-class puFrame            ;
-class puText             ;
-class puButton           ;
-class puOneShot          ;
-class puPopup            ;
-class puPopupMenu        ;
-class puMenuBar          ;
-class puInput            ;
-class puSlider           ;
-
-typedef float puColour [ 4 ] ;  /* RGBA */
-
-struct puBox
-{
-  int min [ 2 ] ;
-  int max [ 2 ] ;
-
-  void draw   ( int dx, int dy, int style, puColour colour[], int am_default ) ;
-  void extend ( puBox *bx ) ;
-
-  void empty   ( void ) { min[0]=min[1]=1000000 ; max[0]=max[1]=-1000000 ; }
-  int  isEmpty ( void ) { return min[0]>max[0] || min[1]>max[1] ; }
-} ;
-
-#define PUSTRING_MAX 80
-
-/* If you change - or add to these, be sure to change _puDefaultColourTable */
-
-extern puColour _puDefaultColourTable[] ;
-
-
-inline void puSetColour ( puColour dst, puColour src )
-{
-  dst[0] = src[0] ; dst[1] = src[1] ; dst[2] = src[2] ; dst[3] = src[3] ;
-}
-
-inline void puSetColour ( puColour c, float r, float g, float b, float a = 1.0f )
-{
-  c [ 0 ] = r ; c [ 1 ] = g ; c [ 2 ] = b ; c [ 3 ] = a ;
-}
-
-
-void  puInit           ( void ) ;
-void  puDisplay        ( void ) ;
-int   puMouse          ( int button, int updown, int x, int y ) ;
-int   puMouse          ( int x, int y ) ;
-int   puKeyboard       ( int key, int updown ) ;
-void  puHideCursor     ( void ) ;
-void  puShowCursor     ( void ) ;
-int   puCursorIsHidden ( void ) ;
-
-void puDrawString         ( puFont fnt, char *str, int x, int y ) ;
-int  puGetStringWidth     ( puFont fnt, char *str ) ;
-int  puGetStringHeight    ( puFont fnt = NULL ) ;
-int  puGetStringDescender ( puFont fnt = NULL ) ;
-
-class puValue
-{
-protected:
-  int   type    ;
-  int   integer ;
-  float floater ;
-  char  string  [ PUSTRING_MAX ] ;
-public:
-  puValue () { type = PUCLASS_VALUE ; clrValue () ; }
-
-  virtual ~puValue () ;
-
-  int  getType ( void ) { return type ; }
-  char *getTypeString ( void ) ;
-  void clrValue ( void ) { setValue ( "" ) ; }
-
-  void setValue ( puValue *pv )
-  {
-    integer = pv -> integer ;
-    floater = pv -> floater ;
-    strcpy ( string, pv -> string ) ;
-    puRefresh = TRUE ;
-  }
-
-  void setValue ( int   i ) { integer = i ; floater = (float) i ; sprintf ( string, "%d", i ) ; puRefresh = TRUE ; }
-  void setValue ( float f ) { integer = (int) f ; floater = f ; sprintf ( string, "%g", f ) ; puRefresh = TRUE ; }
-  void setValue ( char *s ) { 
-                              if ( s == NULL || s[0] == '\0' )
-                              {
-                                integer = 0 ;
-                                floater = 0.0f ;
-                                s = "" ;
-                              }
-                              else
-                              {
-                                integer = atoi(s) ;
-                                floater = (float)atof(s) ;
-
-                                if ( string != s ) strcpy ( string, s ) ;
-                              }
-                              puRefresh = TRUE ;
-                            }
-
-  void getValue ( int   *i ) { *i = integer ; }
-  void getValue ( float *f ) { *f = floater ; }
-  void getValue ( char **s ) { *s = string  ; }
-  void getValue ( char  *s ) { strcpy ( s, string ) ; }
-
-  int  getValue ( void ) { return integer ; }
-} ;
-
-typedef void (*puCallback)(class puObject *) ;
-
-void puSetDefaultStyle ( int  style ) ;
-int  puGetDefaultStyle ( void ) ;
-void puSetDefaultFonts ( puFont  legendFont, puFont  labelFont ) ;
-void puGetDefaultFonts ( puFont *legendFont, puFont *labelFont ) ;
-void puSetDefaultColourScheme ( float r, float g, float b, float a = 1.0 ) ;
-void puGetDefaultColourScheme ( float *r, float *g, float *b, float *a = NULL );
-
-class puObject : public puValue
-{
-protected:
-  puValue default_value ;
-
-  puBox bbox ;   /* Bounding box of entire Object */
-  puBox abox ;   /* Active (clickable) area */
-  puColour colour [ PUCOL_MAX ] ;
-  puInterface *parent ;
-
-  int active_mouse_edge ; /* is it PU_UP or PU_DOWN (or both) that activates this? */
-  int style       ;
-  int visible     ;
-  int active      ;
-  int highlighted ;
-  int am_default  ;
-
-  char *label  ; puFont  labelFont ; int labelPlace ;
-  char *legend ; puFont legendFont ;
-
-  void *user_data ;
-  puCallback cb ;
-
-  virtual void draw_label  ( int dx, int dy ) ;
-  virtual int  isHit ( int x, int y ) { return isVisible() && isActive() &&
-                                               x >= abox.min[0] &&
-                                               x <= abox.max[0] &&
-                                               y >= abox.min[1] &&
-                                               y <= abox.max[1] ; }
-  virtual void doHit ( int button, int updown, int x, int y ) ;
-
-public:
-   puObject ( int minx, int miny, int maxx, int maxy ) ;
-  ~puObject () ;
-
-  puObject *next ;
-  puObject *prev ;
- 
-  puBox *getBBox ( void ) { return & bbox ; }
-  puBox *getABox ( void ) { return & abox ; }
-
-  void setPosition ( int x, int y )
-  {
-    if ( abox.isEmpty() )
-    {
-      abox.max[0] = abox.min[0] = x ;
-      abox.max[1] = abox.min[1] = y ;
-    }
-    else
-    {
-      abox.max[0] += x - abox.min[0] ;
-      abox.max[1] += y - abox.min[1] ;
-      abox.min[0]  = x ;
-      abox.min[1]  = y ;
-    }
-    recalc_bbox() ; puRefresh = TRUE ;
-  }
-
-  void setSize ( int w, int h )
-  {
-    abox.max[0] = abox.min[0] + w ;
-    abox.max[1] = abox.min[1] + h ;
-    recalc_bbox() ; puRefresh = TRUE ;
-  }
-
-  void getPosition ( int *x, int *y )
-  {
-    if ( abox . isEmpty () )
-    {
-      if ( x ) *x = 0 ;
-      if ( y ) *y = 0 ;
-    }
-    else
-    {
-      if ( x ) *x = abox.min[0] ;
-      if ( y ) *y = abox.min[1] ;
-    }
-  }
-
-  void getSize ( int *w, int *h )
-  {
-    if ( abox . isEmpty () )
-    {
-      if ( w ) *w = 0 ;
-      if ( h ) *h = 0 ;
-    }
-    else
-    {
-      if ( w ) *w = abox.max[0] - abox.min[0] ;
-      if ( h ) *h = abox.max[1] - abox.min[1] ;
-    }
-  }
-
-  virtual void recalc_bbox ( void ) ;
-  virtual int  checkHit ( int button, int updown, int x, int y ) ;
-  virtual int  checkKey ( int key   , int updown ) ;
-  virtual void draw ( int dx, int dy ) = 0 ;
-
-  puInterface *getParent     ( void ) { return parent ; }
-  puObject    *getNextObject ( void ) { return next   ; }
-  puObject    *getPrevObject ( void ) { return prev   ; }
-
-  void       setCallback ( puCallback c ) { cb = c ;    }
-  puCallback getCallback ( void )               { return cb ; }
-  void       invokeCallback ( void ) { if ( cb ) (*cb)(this) ; }
-
-  void  makeReturnDefault ( int def ) { am_default = def ; }
-  int   isReturnDefault   ( void )          { return am_default ; }
-
-  void  setActiveDirn ( int e ) { active_mouse_edge = e ; }
-  int   getActiveDirn ( void ) { return active_mouse_edge ; }
-
-  void  setLegend ( char *l ) { legend = l ; recalc_bbox() ; puRefresh = TRUE ; }
-  char *getLegend ( void ) { return legend ; }
-
-  void  setLegendFont ( puFont f ) { legendFont = f ; recalc_bbox() ; puRefresh = TRUE ; }
-  puFont getLegendFont ( void ) { return legendFont ; }
-
-  void  setLabel ( char *l ) { label = l ; recalc_bbox() ; puRefresh = TRUE ; }
-  char *getLabel ( void ) { return label ; }
-
-  void  setLabelFont ( puFont f ) { labelFont = f ; recalc_bbox() ; puRefresh = TRUE ; }
-  puFont getLabelFont ( void ) { return labelFont ; }
-
-  void  setLabelPlace ( int lp ) { labelPlace = lp ; recalc_bbox() ; puRefresh = TRUE ; }
-  int   getLabelPlace ( void ) { return labelPlace ; }
-
-  void activate   ( void ) { if ( ! active  ) { active  = TRUE  ; puRefresh = TRUE ; } }
-  void greyOut    ( void ) { if (   active  ) { active  = FALSE ; puRefresh = TRUE ; } }
-  int  isActive   ( void ) { return active ; }
-
-  void highlight  ( void ) { if ( ! highlighted ) { highlighted = TRUE  ; puRefresh = TRUE ; } }
-  void lowlight   ( void ) { if (   highlighted ) { highlighted = FALSE ; puRefresh = TRUE ; } }
-  int isHighlighted( void ){ return highlighted ; }
-
-  void reveal     ( void ) { if ( ! visible ) { visible = TRUE  ; puRefresh = TRUE ; } }
-  void hide       ( void ) { if (   visible ) { visible = FALSE ; puRefresh = TRUE ; } }
-  int  isVisible  ( void ) { return visible ; }
-
-  void setStyle ( int which )
-  {
-    style = which ;
-    recalc_bbox () ;
-    puRefresh = TRUE ;
-  }
-
-  int  getStyle ( void ) { return style ; }
-
-  void setColourScheme ( float r, float g, float b, float a = 1.0f ) ;
-
-  void setColour ( int which, float r, float g, float b, float a = 1.0f )
-  {
-    puSetColour ( colour [ which ], r, g, b, a ) ;
-    puRefresh = TRUE ;
-  }
-
-  void getColour ( int which, float *r, float *g, float *b, float *a = NULL )
-  {
-    if ( r ) *r = colour[which][0] ;
-    if ( g ) *g = colour[which][1] ;
-    if ( b ) *b = colour[which][2] ;
-    if ( a ) *a = colour[which][3] ;
-  }
-
-  void  setUserData ( void *data ) { user_data = data ; }
-  void *getUserData ( void )             { return user_data ; }
-
-  void defaultValue ( void ) { setValue ( & default_value ) ; }
-
-  void setDefaultValue ( int    i ) { default_value . setValue ( i ) ; }
-  void setDefaultValue ( float  f ) { default_value . setValue ( f ) ; }
-  void setDefaultValue ( char  *s ) { default_value . setValue ( s ) ; }
-
-  void getDefaultValue ( int   *i ) { default_value . getValue ( i ) ; }
-  void getDefaultValue ( float *f ) { default_value . getValue ( f ) ; }
-  void getDefaultValue ( char **s ) { default_value . getValue ( s ) ; }
-  int  getDefaultValue ( void )    { return default_value . getValue () ; }
-} ;
-
-/*
-  The 'live' interface stack is used for clicking and rendering.
-*/
-
-void         puPushLiveInterface        ( puInterface *in ) ;
-void         puPopLiveInterface         ( void ) ;
-int          puNoLiveInterface          ( void ) ;
-puInterface *puGetBaseLiveInterface     ( void ) ;
-puInterface *puGetUltimateLiveInterface ( void ) ;
-
-/*
-  The regular interface stack is used for adding widgets
-*/
-
-void         puPushInterface        ( puInterface *in ) ;
-void         puPopInterface         ( void ) ;
-int          puNoInterface          ( void ) ;
-puInterface *puGetCurrInterface     ( void ) ;
-
-class puInterface : public puObject
-{
-protected:
-  int num_children ;
-  puObject *dlist ;
-
-  void doHit       ( int button, int updown, int x, int y ) ;
-
-public:
-
-  puInterface ( int x, int y ) : puObject ( x, y, x, y )
-  {
-    type |= PUCLASS_INTERFACE ;
-    dlist = NULL ;
-    num_children = 0 ;
-    puPushInterface ( this ) ;
-    puPushLiveInterface ( this ) ;
-  }
-
-  ~puInterface () ;
-
-  void recalc_bbox ( void ) ;
-  virtual void add    ( puObject *new_object ) ;
-  virtual void remove ( puObject *old_object ) ;
-
-  void draw        ( int dx, int dy ) ;
-  int  checkHit    ( int button, int updown, int x, int y ) ;
-  int  checkKey    ( int key   , int updown ) ;
-
-  puObject *getFirstChild ( void ) { return dlist ; }
-  int getNumChildren ( void ) { return num_children ; }
-
-  virtual void close ( void )
-  {
-    if ( puGetCurrInterface () != this )
-      fprintf ( stderr, "PUI: puInterface::close() is mismatched!\n" ) ;
-    else
-      puPopInterface () ;
-  }
-} ;
-
-class puFrame : public puObject
-{
-protected:
-  virtual int  isHit ( int /* x */, int /* y */ ) { return FALSE ; }
-public:
-  void draw ( int dx, int dy ) ;
-  puFrame ( int minx, int miny, int maxx, int maxy ) :
-             puObject ( minx, miny, maxx, maxy )
-  {
-    type |= PUCLASS_FRAME ;
-  }
-} ;
-
-
-class puText : public puObject
-{
-protected:
-  virtual int  isHit ( int /* x */, int /* y */ ) { return FALSE ; }
-public:
-  void draw ( int dx, int dy ) ;
-  puText ( int x, int y ) : puObject ( x, y, x, y )
-  {
-    type |= PUCLASS_TEXT ;
-  }
-} ;
-
-
-class puButton : public puObject
-{
-protected:
-public:
-  void doHit ( int button, int updown, int x, int y ) ;
-  void draw  ( int dx, int dy ) ;
-  puButton   ( int minx, int miny, char *l ) :
-                 puObject ( minx, miny,
-                            minx + puGetStringWidth  ( NULL, l ) + PUSTR_LGAP + PUSTR_RGAP,
-                            miny + puGetStringHeight () + puGetStringDescender () + PUSTR_TGAP + PUSTR_BGAP )
-  {
-    type |= PUCLASS_BUTTON ;
-    setLegend ( l ) ;
-  }
-
-  puButton   ( int minx, int miny, int maxx, int maxy ) :
-                 puObject ( minx, miny, maxx, maxy )
-  {
-    type |= PUCLASS_BUTTON ;
-  }
-} ;
-
-
-class puSlider : public puObject
-{
-protected:
-  int vert ;
-  float last_cb_value ;
-  float cb_delta ;
-  int   cb_mode ;
-  float slider_fraction ;
-public:
-  void doHit ( int button, int updown, int x, int y ) ;
-  void draw  ( int dx, int dy ) ;
-  puSlider ( int minx, int miny, int sz, int vertical = FALSE ) :
-     puObject ( minx, miny, vertical ?
-                             ( minx + puGetStringWidth ( NULL, "W" ) +
-                                      PUSTR_LGAP + PUSTR_RGAP ) :
-                             ( minx + sz ),
-                            vertical ?
-                             ( miny + sz ) :
-                             ( miny + puGetStringHeight () +
-                                      puGetStringDescender () +
-                                      PUSTR_TGAP + PUSTR_BGAP )
-                           )
-  {
-    type |= PUCLASS_SLIDER ;
-    slider_fraction = 0.1f ;
-    getValue ( & last_cb_value ) ;
-    vert = vertical ;
-    cb_delta = 0.1f ;
-    cb_mode = PUSLIDER_ALWAYS ;
-  }
-
-  void setCBMode ( int m ) { cb_mode = m ; }
-  float getCBMode ( void ) { return (float)cb_mode ; }
-
-  int  isVertical ( void ) { return vert ; }
-
-  void setDelta ( float f ) { cb_delta = (f<=0.0f) ? 0.1f : (f>=1.0f) ? 0.9f : f ; }
-  float getDelta ( void ) { return cb_delta ; }
-
-  void setSliderFraction ( float f ) { slider_fraction = (f<=0.0f) ? 0.1f : (f>=1.0f) ? 0.9f : f ; }
-  float getSliderFraction ( void ) { return slider_fraction ; }
-} ;
-
-
-
-class puOneShot : public puButton
-{
-protected:
-public:
-  void doHit ( int button, int updown, int x, int y ) ;
-
-  puOneShot ( int minx, int miny, char *l ) : puButton   ( minx, miny, l )
-  {
-    type |= PUCLASS_ONESHOT ;
-  }
-
-  puOneShot ( int minx, int miny, int maxx, int maxy ) :
-                 puButton ( minx, miny, maxx, maxy )
-  {
-    type |= PUCLASS_ONESHOT ;
-  }
-} ;
-
-
-
-class puPopup : public puInterface
-{
-protected:
-public:
-  puPopup ( int x, int y ) : puInterface ( x, y )
-  {
-    type |= PUCLASS_POPUP ;
-    hide () ;
-  }
-} ;
-
-class puPopupMenu : public puPopup
-{
-protected:
-public:
-  puPopupMenu ( int x, int y ) : puPopup ( x, y )
-  {
-    type |= PUCLASS_POPUPMENU ;
-  }
-
-  puObject *add_item ( char *str, puCallback cb ) ;
-  int  checkHit ( int button, int updown, int x, int y ) ;
-  int  checkKey ( int key   , int updown ) ;
-  void close ( void ) ;
-} ;
-
-class puMenuBar : public puInterface
-{
-protected:
-public:
-  puMenuBar ( int h = -1 ) :
-
-  puInterface ( 0, h < 0 ? puGetWindowHeight() -
-                      ( puGetStringHeight() + PUSTR_TGAP + PUSTR_BGAP ) : h )
-  {
-    type |= PUCLASS_MENUBAR ;
-  }
-
-  void add_submenu ( char *str, char *items[], puCallback cb[] ) ;
-  void close ( void ) ;
-} ;
-
-
-class puInput : public puObject
-{
-  int accepting ;
-  int cursor_position ;
-  int select_start_position ;
-  int select_end_position ;
-
-  void normalize_cursors ( void ) ;
-
-public:
-  void draw     ( int dx, int dy ) ;
-  void doHit    ( int button, int updown, int x, int y ) ;
-  int  checkKey ( int key, int updown ) ;
-
-  int  isAcceptingInput ( void ) { return accepting ; }
-  void rejectInput      ( void ) { accepting = FALSE ; }
-  void acceptInput      ( void ) { accepting = TRUE ;
-                             cursor_position = strlen ( string ) ;
-                             select_start_position = select_end_position = -1 ; }
-
-  int  getCursor ( void )        { return cursor_position ; }
-  void setCursor ( int c ) { cursor_position = c ; }
-
-  void setSelectRegion ( int s, int e )
-  {
-    select_start_position = s ;
-    select_end_position   = e ;
-  }
-
-  void getSelectRegion ( int *s, int *e )
-  {
-    if ( s ) *s = select_start_position ;
-    if ( e ) *e = select_end_position   ;
-  }
-
-  puInput ( int minx, int miny, int maxx, int maxy ) :
-             puObject ( minx, miny, maxx, maxy )
-  {
-    type |= PUCLASS_INPUT ;
-
-    accepting = FALSE ;
-
-    cursor_position       =  0 ;
-    select_start_position = -1 ;
-    select_end_position   = -1 ;
-
-    setColourScheme ( 0.8f, 0.7f, 0.7f ) ; /* Yeukky Pink */
-  }
-} ;
-
-
-class puButtonBox : public puObject
-{
-protected:
-  int one_only ;
-  int num_kids ;
-  char **button_labels ;
-
-public:
-
-  puButtonBox ( int minx, int miny, int maxx, int maxy, 
-                char **labels, int one_button ) ;
-
-  int isOneButton ( void ) { return one_only ; }
-
-  int checkKey ( int key   , int updown ) ;
-  int checkHit ( int button, int updown, int x, int y ) ;
-  void draw    ( int dx, int dy ) ;
-} ;
-
-
-
-class puDialogBox : public puPopup
-{
-protected:
-public:
-
-  puDialogBox ( int x, int y ) : puPopup ( x, y )
-  {
-    type |= PUCLASS_DIALOGBOX ;
-  }
-} ;
-
-#endif
-
diff --git a/Lib/PUI/puBox.cxx b/Lib/PUI/puBox.cxx
deleted file mode 100644
index d0d926285..000000000
--- a/Lib/PUI/puBox.cxx
+++ /dev/null
@@ -1,319 +0,0 @@
-
-#include "puLocal.h"
-
-#define PU_BEVEL              5
-#define PU_SMALL_BEVEL        2
-#define PU_DFLT_OFFSET        8
-#define PU_BOX_WIDTH          2
-#define PU_DROPSHADOW_OFFSET  5
-
-void puBox::extend ( puBox *bx )
-{
-  if ( bx -> isEmpty () ) return ;
-
-  if ( min[0]>bx->min[0] ) min[0] = bx->min[0] ;
-  if ( min[1]>bx->min[1] ) min[1] = bx->min[1] ;
-  if ( max[0]max[0] ) max[0] = bx->max[0] ;
-  if ( max[1]max[1] ) max[1] = bx->max[1] ;
-}
- 
-
- 
-void puBox::draw ( int dx, int dy, int style, puColour colour[], int am_default  )
-{
-  int hi, mid, lo ;
-
-  /* Colour assignments */
-
-  switch ( style )
-  {
-    case  PUSTYLE_NONE       :
-      return ;
-
-    case  PUSTYLE_PLAIN      :
-    case  PUSTYLE_DROPSHADOW :
-      mid = PUCOL_FOREGROUND ;
-      lo  = PUCOL_BACKGROUND ;
-      break ;
-
-    case  PUSTYLE_SMALL_SHADED :
-    case  PUSTYLE_SHADED     :
-    case  PUSTYLE_SMALL_BEVELLED :
-    case  PUSTYLE_BEVELLED   :
-    case  PUSTYLE_BOXED      :
-    case  PUSTYLE_SPECIAL_UNDERLINED :
-      mid = PUCOL_FOREGROUND ;
-      hi  = PUCOL_HIGHLIGHT  ;
-      lo  = PUCOL_BACKGROUND ;
-      break ;
-
-    case  PUSTYLE_RADIO      :
-    case -PUSTYLE_RADIO      :
-      hi  = PUCOL_HIGHLIGHT  ;
-      lo  = PUCOL_BACKGROUND ;
-      break ;
-
-    case -PUSTYLE_PLAIN      :
-    case -PUSTYLE_DROPSHADOW :
-      mid = PUCOL_HIGHLIGHT  ;
-      lo  = PUCOL_BACKGROUND ;
-      break ;
-
-    case -PUSTYLE_SMALL_BEVELLED :
-    case -PUSTYLE_BEVELLED   :
-    case -PUSTYLE_SMALL_SHADED :
-    case -PUSTYLE_SHADED     :
-    case -PUSTYLE_BOXED      :
-    case -PUSTYLE_SPECIAL_UNDERLINED :
-      mid = PUCOL_FOREGROUND ;
-      hi  = PUCOL_BACKGROUND ;
-      lo  = PUCOL_HIGHLIGHT  ;
-      break ;
-
-    default :
-      fprintf ( stderr, "PUI: Unrecognised 'style' %d\n", style ) ;
-      return ;
-  }
-
-  switch ( abs(style) )
-  {
-    case  PUSTYLE_PLAIN      :
-      glColor4fv ( colour [ mid ] ) ;
-      glRecti ( dx + min[0], dy + min[1],
-		dx + max[0], dy + max[1] ) ;
-      break ;
-
-    case  PUSTYLE_SMALL_BEVELLED   :
-    case  PUSTYLE_SMALL_SHADED     :
-      glColor4fv ( colour [ hi  ] ) ;
-      glBegin ( GL_QUAD_STRIP ) ;
-	glVertex2i ( dx + min[0] + PU_SMALL_BEVEL, dy + min[1] + PU_SMALL_BEVEL ) ;
-	glVertex2i ( dx + min[0], dy + min[1] ) ;
-	glVertex2i ( dx + min[0] + PU_SMALL_BEVEL, dy + max[1] - PU_SMALL_BEVEL ) ;
-	glVertex2i ( dx + min[0], dy + max[1] ) ;
-	glVertex2i ( dx + max[0] - PU_SMALL_BEVEL, dy + max[1] - PU_SMALL_BEVEL ) ;
-	glVertex2i ( dx + max[0], dy + max[1] ) ;
-      glEnd () ;
-	glColor4fv ( colour [ lo  ] ) ;
-      glBegin ( GL_QUAD_STRIP ) ;
-	glVertex2i ( dx + min[0], dy + min[1] ) ;
-	glVertex2i ( dx + min[0] + PU_SMALL_BEVEL, dy + min[1] + PU_SMALL_BEVEL ) ;
-	glVertex2i ( dx + max[0], dy + min[1] ) ;
-	glVertex2i ( dx + max[0] - PU_SMALL_BEVEL, dy + min[1] + PU_SMALL_BEVEL ) ;
-	glVertex2i ( dx + max[0], dy + max[1] ) ;
-	glVertex2i ( dx + max[0] - PU_SMALL_BEVEL, dy + max[1] - PU_SMALL_BEVEL ) ;
-      glEnd () ;
-
-      if ( abs(style) == PUSTYLE_SMALL_BEVELLED )
-      {
-        glColor4fv ( colour [ mid ] ) ;
-        glRecti ( dx + min[0] + PU_SMALL_BEVEL, dy + min[1] + PU_SMALL_BEVEL,
-		  dx + max[0] - PU_SMALL_BEVEL, dy + max[1] - PU_SMALL_BEVEL ) ;
-      }
-      else
-      {
-	glShadeModel(GL_SMOOTH);
-	glBegin(GL_POLYGON);
-	  glColor4fv( colour [ mid ] );
-	  glVertex2i( dx + min[0] + PU_SMALL_BEVEL , dy + min[1] + PU_SMALL_BEVEL );
-	  if(style==PUSTYLE_SMALL_SHADED)
-	    glColor4f( colour [mid][0] + (colour[lo][0] - colour[mid][0])/2.0f,
-		       colour [mid][1] + (colour[lo][1] - colour[mid][1])/2.0f,
-		       colour [mid][2] + (colour[lo][2] - colour[mid][2])/2.0f,
-		       colour [lo][3] );
-	  else
-	    glColor4f( colour [mid][0] + (colour[hi][0] - colour[mid][0])/2.0f,
-		       colour [mid][1] + (colour[hi][1] - colour[mid][1])/2.0f,
-		       colour [mid][2] + (colour[hi][2] - colour[mid][2])/2.0f,
-		       colour [hi][3] );
-	  glVertex2i( dx + min[0] + PU_SMALL_BEVEL , dy + max[1] - PU_SMALL_BEVEL );
-	  glColor4fv( colour [ mid ] );
-	  glVertex2i( dx + max[0] - PU_SMALL_BEVEL , dy + max[1] - PU_SMALL_BEVEL );
-	  if(style==-PUSTYLE_SMALL_SHADED)
-	    glColor4f( colour [mid][0] + (colour[lo][0] - colour[mid][0])/2.0f,
-		       colour [mid][1] + (colour[lo][1] - colour[mid][1])/2.0f,
-		       colour [mid][2] + (colour[lo][2] - colour[mid][2])/2.0f,
-		       colour [lo][3] );
-	  else
-	    glColor4f( colour [mid][0] + (colour[hi][0] - colour[mid][0])/2.0f,
-		       colour [mid][1] + (colour[hi][1] - colour[mid][1])/2.0f,
-		       colour [mid][2] + (colour[hi][2] - colour[mid][2])/2.0f,
-		       colour [hi][3] );
-	  glVertex2i( dx + max[0] - PU_SMALL_BEVEL , dy + min[1] + PU_SMALL_BEVEL );
-	glEnd();
-	glShadeModel(GL_FLAT);
-
-	if(style == -PUSTYLE_SMALL_SHADED)
-	{
-	  glColor4fv ( colour [ lo  ] ) ;
-	  glBegin ( GL_QUAD_STRIP ) ;
-	    glVertex2i ( dx + min[0] + PU_SMALL_BEVEL   , dy + min[1] + PU_SMALL_BEVEL   ) ;
-	    glVertex2i ( dx + min[0] + PU_SMALL_BEVEL/2 , dy + min[1] + PU_SMALL_BEVEL/2 ) ;
-	    glVertex2i ( dx + min[0] + PU_SMALL_BEVEL   , dy + max[1] - PU_SMALL_BEVEL   ) ;
-	    glVertex2i ( dx + min[0] + PU_SMALL_BEVEL/2 , dy + max[1] - PU_SMALL_BEVEL/2 ) ;
-	    glVertex2i ( dx + max[0] - PU_SMALL_BEVEL   , dy + max[1] - PU_SMALL_BEVEL   ) ;
-	    glVertex2i ( dx + max[0] - PU_SMALL_BEVEL/2 , dy + max[1] - PU_SMALL_BEVEL/2 ) ;
-	  glEnd () ;
-	  glColor4fv ( colour [ hi  ] ) ;
-	  glBegin ( GL_QUAD_STRIP ) ;
-	    glVertex2i ( dx + min[0] + PU_SMALL_BEVEL/2 , dy + min[1] + PU_SMALL_BEVEL/2 ) ;
-	    glVertex2i ( dx + min[0] + PU_SMALL_BEVEL   , dy + min[1] + PU_SMALL_BEVEL   ) ;
-	    glVertex2i ( dx + max[0] - PU_SMALL_BEVEL/2 , dy + min[1] + PU_SMALL_BEVEL/2 ) ;
-	    glVertex2i ( dx + max[0] - PU_SMALL_BEVEL   , dy + min[1] + PU_SMALL_BEVEL   ) ;
-	    glVertex2i ( dx + max[0] - PU_SMALL_BEVEL/2 , dy + max[1] - PU_SMALL_BEVEL/2 ) ;
-	    glVertex2i ( dx + max[0] - PU_SMALL_BEVEL   , dy + max[1] - PU_SMALL_BEVEL   ) ;
-	  glEnd () ;
-	}	
-      }
-      break ;
-
-    case  PUSTYLE_BEVELLED   :
-    case  PUSTYLE_SHADED     :
-      glColor4fv ( colour [ hi  ] ) ;
-      glBegin ( GL_QUAD_STRIP ) ;
-	glVertex2i ( dx + min[0] + PU_BEVEL, dy + min[1] + PU_BEVEL ) ;
-	glVertex2i ( dx + min[0], dy + min[1] ) ;
-	glVertex2i ( dx + min[0] + PU_BEVEL, dy + max[1] - PU_BEVEL ) ;
-	glVertex2i ( dx + min[0], dy + max[1] ) ;
-	glVertex2i ( dx + max[0] - PU_BEVEL, dy + max[1] - PU_BEVEL ) ;
-	glVertex2i ( dx + max[0], dy + max[1] ) ;
-      glEnd () ;
-	glColor4fv ( colour [ lo  ] ) ;
-      glBegin ( GL_QUAD_STRIP ) ;
-	glVertex2i ( dx + min[0], dy + min[1] ) ;
-	glVertex2i ( dx + min[0] + PU_BEVEL, dy + min[1] + PU_BEVEL ) ;
-	glVertex2i ( dx + max[0], dy + min[1] ) ;
-	glVertex2i ( dx + max[0] - PU_BEVEL, dy + min[1] + PU_BEVEL ) ;
-	glVertex2i ( dx + max[0], dy + max[1] ) ;
-	glVertex2i ( dx + max[0] - PU_BEVEL, dy + max[1] - PU_BEVEL ) ;
-      glEnd () ;
-
-      if ( abs(style) == PUSTYLE_BEVELLED )
-      {
-	glColor4fv ( colour [ mid ] ) ;
-	glRecti ( dx + min[0] + PU_BEVEL, dy + min[1] + PU_BEVEL,
-		  dx + max[0] - PU_BEVEL, dy + max[1] - PU_BEVEL ) ;
-      }
-      else
-      {
-	glShadeModel(GL_SMOOTH);
-	glBegin(GL_POLYGON);
-	  glColor4fv( colour [ mid ] );
-	  glVertex2i( dx + min[0] + PU_BEVEL , dy + min[1] + PU_BEVEL );
-	  if(style==PUSTYLE_SHADED)
-	    glColor4f( colour [mid][0] + (colour[lo][0] - colour[mid][0])/2.0f,
-		       colour [mid][1] + (colour[lo][1] - colour[mid][1])/2.0f,
-		       colour [mid][2] + (colour[lo][2] - colour[mid][2])/2.0f,
-		       colour [lo][3] );
-	  else
-	    glColor4f( colour [mid][0] + (colour[hi][0] - colour[mid][0])/2.0f,
-		       colour [mid][1] + (colour[hi][1] - colour[mid][1])/2.0f,
-		       colour [mid][2] + (colour[hi][2] - colour[mid][2])/2.0f,
-		       colour [hi][3] );
-	  glVertex2i( dx + min[0] + PU_BEVEL , dy + max[1] - PU_BEVEL );
-	  glColor4fv( colour [ mid ] );
-	  glVertex2i( dx + max[0] - PU_BEVEL , dy + max[1] - PU_BEVEL );
-	  if(style==-PUSTYLE_SHADED)
-	    glColor4f( colour [mid][0] + (colour[lo][0] - colour[mid][0])/2.0f,
-		       colour [mid][1] + (colour[lo][1] - colour[mid][1])/2.0f,
-		       colour [mid][2] + (colour[lo][2] - colour[mid][2])/2.0f,
-		       colour [lo][3] );
-	  else
-	    glColor4f( colour [mid][0] + (colour[hi][0] - colour[mid][0])/2.0f,
-		       colour [mid][1] + (colour[hi][1] - colour[mid][1])/2.0f,
-		       colour [mid][2] + (colour[hi][2] - colour[mid][2])/2.0f,
-		       colour [hi][3] );
-	  glVertex2i( dx + max[0] - PU_BEVEL , dy + min[1] + PU_BEVEL );
-	glEnd();
-	glShadeModel(GL_FLAT);
-
-	if(style == -PUSTYLE_SHADED)
-        {
-	  glColor4fv ( colour [ lo  ] ) ;
-	  glBegin ( GL_QUAD_STRIP ) ;
-	    glVertex2i ( dx + min[0] + PU_BEVEL   , dy + min[1] + PU_BEVEL   ) ;
-	    glVertex2i ( dx + min[0] + PU_BEVEL/2 , dy + min[1] + PU_BEVEL/2 ) ;
-	    glVertex2i ( dx + min[0] + PU_BEVEL   , dy + max[1] - PU_BEVEL   ) ;
-	    glVertex2i ( dx + min[0] + PU_BEVEL/2 , dy + max[1] - PU_BEVEL/2 ) ;
-	    glVertex2i ( dx + max[0] - PU_BEVEL   , dy + max[1] - PU_BEVEL   ) ;
-	    glVertex2i ( dx + max[0] - PU_BEVEL/2 , dy + max[1] - PU_BEVEL/2 ) ;
-	  glEnd () ;
-	  glColor4fv ( colour [ hi  ] ) ;
-	  glBegin ( GL_QUAD_STRIP ) ;
-	    glVertex2i ( dx + min[0] + PU_BEVEL/2 , dy + min[1] + PU_BEVEL/2 ) ;
-	    glVertex2i ( dx + min[0] + PU_BEVEL   , dy + min[1] + PU_BEVEL   ) ;
-	    glVertex2i ( dx + max[0] - PU_BEVEL/2 , dy + min[1] + PU_BEVEL/2 ) ;
-	    glVertex2i ( dx + max[0] - PU_BEVEL   , dy + min[1] + PU_BEVEL   ) ;
-	    glVertex2i ( dx + max[0] - PU_BEVEL/2 , dy + max[1] - PU_BEVEL/2 ) ;
-	    glVertex2i ( dx + max[0] - PU_BEVEL   , dy + max[1] - PU_BEVEL   ) ;
-	  glEnd () ;
-	}	
-      }	
-      break ;
-
-    case  PUSTYLE_BOXED      :
-      glColor4fv ( colour [ hi  ] ) ;
-      glRecti ( dx + min[0], dy + min[1],
-		dx + max[0], dy + max[1] ) ;
-      glColor4fv ( colour [ mid ] ) ;
-      glRecti ( dx + min[0]+PU_BOX_WIDTH, dy + min[1]+PU_BOX_WIDTH,
-		dx + max[0]-PU_BOX_WIDTH, dy + max[1]-PU_BOX_WIDTH ) ;
-      break ;
-
-    case  PUSTYLE_RADIO      :
-      glColor4fv ( colour [ lo  ] ) ;
-      glBegin ( GL_LINE_LOOP ) ;
-        glVertex2i ( dx + min[0] + PU_RADIO_BUTTON_SIZE/2, dy + min[1]                          ) ;
-        glVertex2i ( dx + min[0] + PU_RADIO_BUTTON_SIZE  , dy + min[1] + PU_RADIO_BUTTON_SIZE/2 ) ;
-        glVertex2i ( dx + min[0] + PU_RADIO_BUTTON_SIZE/2, dy + min[1] + PU_RADIO_BUTTON_SIZE   ) ;
-        glVertex2i ( dx + min[0]                         , dy + min[1] + PU_RADIO_BUTTON_SIZE/2 ) ;
-      glEnd () ;
-
-      if ( style < 0 )
-      {
-	glColor4fv ( colour [ hi  ] ) ;
-	glBegin ( GL_QUADS ) ;
-	  glVertex2i ( dx + min[0] + PU_RADIO_BUTTON_SIZE/2, dy + min[1] + 2                      ) ;
-	  glVertex2i ( dx + min[0] + PU_RADIO_BUTTON_SIZE-2, dy + min[1] + PU_RADIO_BUTTON_SIZE/2 ) ;
-	  glVertex2i ( dx + min[0] + PU_RADIO_BUTTON_SIZE/2, dy + min[1] + PU_RADIO_BUTTON_SIZE-2 ) ;
-	  glVertex2i ( dx + min[0] + 2                     , dy + min[1] + PU_RADIO_BUTTON_SIZE/2 ) ;
-	glEnd () ;
-      }
-      break ;
-
-    case  PUSTYLE_SPECIAL_UNDERLINED :
-      glColor4fv ( colour [ hi  ] ) ;
-      glRecti ( dx + min[0], dy + min[1],
-		dx + max[0], dy + min[1]+2 ) ;
-      glColor4fv ( colour [ mid ] ) ;
-      glRecti ( dx + min[0], dy + min[1]+1,
-		dx + max[0], dy + max[1] ) ;
-      break ;
-
-    case  PUSTYLE_DROPSHADOW :
-      glColor4fv ( colour [ lo  ] ) ;
-      glRecti ( dx + min[0] + PU_DROPSHADOW_OFFSET, dy + min[1] - PU_DROPSHADOW_OFFSET,
-		dx + max[0] + PU_DROPSHADOW_OFFSET, dy + max[1] - PU_DROPSHADOW_OFFSET ) ;
-      glColor4fv ( colour [ mid ] ) ;
-      glRecti ( dx + min[0], dy + min[1],
-		dx + max[0], dy + max[1] ) ;
-      break ;
-  }
-
-  if ( am_default )
-  {
-    glColor4fv ( colour [ PUCOL_BACKGROUND ] ) ;
-    glLineStipple ( 1, 0xF0F0 ) ;
-    glEnable ( GL_LINE_STIPPLE ) ;
-    glBegin ( GL_LINE_LOOP ) ;
-      glVertex2i ( dx + min[0] + PU_DFLT_OFFSET, dy + min[1] + PU_DFLT_OFFSET ) ;
-      glVertex2i ( dx + min[0] + PU_DFLT_OFFSET, dy + max[1] - PU_DFLT_OFFSET ) ;
-      glVertex2i ( dx + max[0] - PU_DFLT_OFFSET, dy + max[1] - PU_DFLT_OFFSET ) ;
-      glVertex2i ( dx + max[0] - PU_DFLT_OFFSET, dy + min[1] + PU_DFLT_OFFSET ) ;
-    glEnd () ;
-    glDisable ( GL_LINE_STIPPLE ) ;
-  }
-}
-
-
-
diff --git a/Lib/PUI/puButton.cxx b/Lib/PUI/puButton.cxx
deleted file mode 100644
index 66ded922b..000000000
--- a/Lib/PUI/puButton.cxx
+++ /dev/null
@@ -1,61 +0,0 @@
-
-
-#include "puLocal.h"
-
-void puButton::draw ( int dx, int dy )
-{
-  if ( !visible ) return ;
-
-  /* If button is pushed or highlighted - use inverse style for button itself */
-
-  int tempStyle;
-
-  if ( parent && ( ( parent->getType() & PUCLASS_POPUPMENU ) ||
-                   ( parent->getType() & PUCLASS_MENUBAR   ) ) )
-    tempStyle =  ( getValue() ^ highlighted ) ? PUSTYLE_SMALL_SHADED : style ;
-  else
-    tempStyle =  ( getValue() ^ highlighted ) ? -style : style ;
-
-  abox . draw ( dx, dy, tempStyle, colour, isReturnDefault() ) ;
-
-  /* If greyed out then halve the opacity when drawing the label and legend */
-
-  if ( active )
-    glColor4fv ( colour [ PUCOL_LEGEND ] ) ;
-  else
-    glColor4f ( colour [ PUCOL_LEGEND ][0],
-                colour [ PUCOL_LEGEND ][1],
-                colour [ PUCOL_LEGEND ][2],
-                colour [ PUCOL_LEGEND ][3] / 2.0f ) ; /* 50% more transparent */
-
-  int xx = ( abox.max[0] - abox.min[0] - puGetStringWidth(legendFont,legend) ) / 2 ;
-  int yy = ( abox.max[1] - abox.min[1] - puGetStringHeight(legendFont) ) / 2 ;
-
-  puDrawString ( legendFont, legend,
-                  dx + abox.min[0] + xx,
-                  dy + abox.min[1] + yy ) ;
-
-  draw_label ( dx, dy ) ;
-}
-
-
-void puButton::doHit ( int button, int updown, int, int )
-{
-
-
-  if ( button == PU_LEFT_BUTTON )
-  {
-    if ( updown == active_mouse_edge || active_mouse_edge == PU_UP_AND_DOWN )
-    {
-      lowlight () ;
-      setValue ( (int) ! getValue () ) ;
-      invokeCallback () ;
-    }
-    else
-      highlight () ;
-  }
-  else
-    lowlight () ;
-}
-
-
diff --git a/Lib/PUI/puButtonBox.cxx b/Lib/PUI/puButtonBox.cxx
deleted file mode 100644
index f569ed787..000000000
--- a/Lib/PUI/puButtonBox.cxx
+++ /dev/null
@@ -1,100 +0,0 @@
-
-#include "puLocal.h"
-
-puButtonBox::puButtonBox ( int minx, int miny, int maxx, int maxy,
-                char **labels, int one_button ) :
-                    puObject ( minx, miny, maxx, maxy )
-{
-  type |= PUCLASS_BUTTONBOX ;
-  one_only = one_button ;
-
-  button_labels = labels ;
-
-  for ( num_kids = 0 ; button_labels [ num_kids ] != NULL ; num_kids++ )
-    /* Count number of labels */ ;
-}
-
-
-int puButtonBox::checkKey ( int key, int updown )
-{
-  if ( updown == PU_UP ||
-       ! isReturnDefault() ||
-       ( key != '\r' && key != '\n' ) )
-    return FALSE ;
-
-  int v = getValue () ;
-
-  if ( ! one_only )
-    v = ~v ;
-  else
-  if ( v++ > num_kids )
-    v = 0 ;
-
-  setValue ( v ) ;
-  invokeCallback() ;
-  return TRUE ;
-}
-
-
-int puButtonBox::checkHit ( int button, int updown, int x, int y )
-{
-  if ( ! isHit ( x, y ) ||
-       ( updown != active_mouse_edge &&
-         active_mouse_edge != PU_UP_AND_DOWN ) )
-    return FALSE ;
-
-  int i = num_kids - 1 - (( y - abox.min[1] - PUSTR_BGAP ) * num_kids ) /
-                          ( abox.max[1] - abox.min[1] - PUSTR_BGAP - PUSTR_TGAP ) ;
-
-  if ( i < 0 ) i = 0 ;
-  if ( i >= num_kids ) i = num_kids - 1 ;
-
-  if ( one_only )
-    setValue ( i ) ;
-  else
-    setValue ( getValue () ^ ( 1 << i ) ) ;
-
-  invokeCallback () ;
-  return TRUE ;
-}
-
-
-void puButtonBox::draw ( int dx, int dy )
-{
-  if ( !visible ) return ;
-
-  abox . draw ( dx, dy, style, colour, isReturnDefault() ) ;
-
-  for ( int i = 0 ; i < num_kids ; i++ )
-  {
-    puBox tbox ;
-
-    tbox . min [ 0 ] = abox.min [ 0 ] + PUSTR_LGAP + PUSTR_LGAP ;
-    tbox . min [ 1 ] = abox.min [ 1 ] + ((abox.max[1]-abox.min[1]-PUSTR_TGAP-PUSTR_BGAP)/num_kids) * (num_kids-1-i) ;
-    tbox . max [ 0 ] = tbox.min [ 0 ] ;
-    tbox . max [ 1 ] = tbox.min [ 1 ] ;
-
-    if (( one_only && i == getValue() ) ||
-        ( !one_only && ((1< sl ) cursor_position       = sl ;
-  if ( select_start_position > sl ) select_start_position = sl ;
-  if ( select_end_position   > sl ) select_end_position   = sl ;
-
-  /* Swap the ends of the select window if they get crossed over */
-
-  if ( select_end_position < select_start_position )
-  {
-    int tmp = select_end_position ;     
-    select_end_position = select_start_position ;     
-    select_start_position = tmp ;
-  }
-}
-
-void puInput::draw ( int dx, int dy )
-{
-  normalize_cursors () ;
-
-  if ( !visible ) return ;
-
-  /* 3D Input boxes look nicest if they are always in inverse style. */
-
-  abox . draw ( dx, dy, ( (style==PUSTYLE_SMALL_BEVELLED ||
-                           style==PUSTYLE_SMALL_SHADED) ) ? -style :
-                        (accepting ? -style : style ), colour, FALSE ) ;
-
-  int xx = puGetStringWidth ( legendFont, " " ) ;
-  int yy = ( abox.max[1] - abox.min[1] - puGetStringHeight(legendFont) ) / 2 ;
-
-  if ( accepting )
-  {
-    char val [ PUSTRING_MAX ] ;
-    getValue ( val ) ;
-
-    /* Highlight the select area */
-
-    if ( select_end_position > 0 &&
-         select_end_position != select_start_position )    
-    {
-      val [ select_end_position ] = '\0' ;
-      int cpos2 = puGetStringWidth ( legendFont, val ) + xx + dx + abox.min[0] ;
-      val [ select_start_position ] = '\0' ;
-      int cpos1 = puGetStringWidth ( legendFont, val ) + xx + dx + abox.min[0] ;
-
-      glColor3f ( 1.0f, 1.0f, 0.7f ) ;
-      glRecti ( cpos1, dy + abox.min[1] + 6 ,
-                cpos2, dy + abox.max[1] - 6 ) ;
-    }
-  }
-
-  /* Draw the text */
-
-  {
-    /* If greyed out then halve the opacity when drawing the label and legend */
-
-    if ( active )
-      glColor4fv ( colour [ PUCOL_LEGEND ] ) ;
-    else
-      glColor4f ( colour [ PUCOL_LEGEND ][0],
-		  colour [ PUCOL_LEGEND ][1],
-		  colour [ PUCOL_LEGEND ][2],
-		  colour [ PUCOL_LEGEND ][3] / 2.0f ) ; /* 50% more transparent */
-
-    char val [ PUSTRING_MAX ] ;
-    getValue ( val ) ;
-
-    puDrawString ( legendFont, val,
-                  dx + abox.min[0] + xx,
-                  dy + abox.min[1] + yy ) ;
-
-    draw_label ( dx, dy ) ;
-  }
-
-  if ( accepting )
-  { 
-    char val [ PUSTRING_MAX ] ;
-    getValue ( val ) ;
-
-    /* Draw the 'I' bar cursor. */
-
-    if ( cursor_position >= 0 )
-    {
-      val [ cursor_position ] = '\0' ;
-
-      int cpos = puGetStringWidth ( legendFont, val ) + xx + dx + abox.min[0] ;
-
-      glColor3f ( 0.1f, 0.1f, 1.0f ) ;
-      glBegin   ( GL_LINES ) ;
-      glVertex2i ( cpos    , dy + abox.min[1] + 7 ) ;
-      glVertex2i ( cpos    , dy + abox.max[1] - 7 ) ;
-      glVertex2i ( cpos - 1, dy + abox.min[1] + 7 ) ;
-      glVertex2i ( cpos - 1, dy + abox.max[1] - 7 ) ;
-      glVertex2i ( cpos - 4, dy + abox.min[1] + 7 ) ;
-      glVertex2i ( cpos + 3, dy + abox.min[1] + 7 ) ;
-      glVertex2i ( cpos - 4, dy + abox.max[1] - 7 ) ;
-      glVertex2i ( cpos + 3, dy + abox.max[1] - 7 ) ;
-      glEnd      () ;
-    }
-  }
-}
-
-
-void puInput::doHit ( int button, int updown, int x, int /* y */ )
-{
-  if ( button == PU_LEFT_BUTTON )
-  {
-    /* Most GUI's activate a button on button-UP not button-DOWN. */
-
-    if ( updown == active_mouse_edge || active_mouse_edge == PU_UP_AND_DOWN )
-    {
-      lowlight () ;
-
-      char *strval ;
-      getValue ( & strval ) ;
-      char *tmpval = new char [ strlen(strval) + 1 ] ;
-      strcpy ( tmpval, strval ) ;
-
-      int i = strlen ( tmpval ) ;
-
-      while ( x <= puGetStringWidth ( legendFont, tmpval ) + abox.min[0] &&
-              i >= 0 )
-        tmpval[--i] = '\0' ;
-    
-      accepting = TRUE ;
-      cursor_position = i ;
-      normalize_cursors () ;
-      invokeCallback () ;
-    }
-    else
-      highlight () ;
-  }
-  else
-    lowlight () ;
-}
-
-int puInput::checkKey ( int key, int updown )
-{
-  (updown,updown);
-
-  if ( ! isAcceptingInput() || ! isActive () || ! isVisible () )
-    return FALSE ;
-
-  normalize_cursors () ;
-
-  char *p ;
-
-  switch ( key )
-  {
-    case PU_KEY_PAGE_UP   :
-    case PU_KEY_PAGE_DOWN :
-    case PU_KEY_INSERT    : return FALSE ; 
-
-    case PU_KEY_UP   :
-    case PU_KEY_DOWN :
-    case 0x1B /* ESC */ :
-    case '\t' :
-    case '\r' :
-    case '\n' : /* Carriage return/Line Feed/TAB  -- End of input */
-      rejectInput () ;
-      normalize_cursors () ;
-      invokeCallback () ;
-      break ;
-
-    case '\b' : /* Backspace */
-      if ( cursor_position > 0 ) 
-        for ( p = & string [ --cursor_position ] ; *p != '\0' ; p++ )
-          *p = *(p+1) ;
-      break ;
-
-    case 0x7F : /* DEL */
-      if ( select_start_position != select_end_position )
-      {
-        char *p1 = & string [ select_start_position ] ;
-        char *p2 = & string [ select_end_position   ] ;
-
-        while ( *p1 != '\0' )
-          *p1++ = *p2++ ;
-
-        select_end_position = select_start_position ;
-      }
-      else
-	for ( p = & string [ cursor_position ] ; *p != '\0' ; p++ )
-	  *p = *(p+1) ;
-      break ;
-
-    case 0x15 /* ^U */ : string [ 0 ] = '\0' ; break ;
-    case PU_KEY_HOME   : cursor_position = 0 ; break ;
-    case PU_KEY_END    : cursor_position = PUSTRING_MAX ; break ;
-    case PU_KEY_LEFT   : cursor_position-- ; break ;
-    case PU_KEY_RIGHT  : cursor_position++ ; break ;
-
-    default:
-      if ( key < ' ' || key > 127 ) return FALSE ;
-
-      if ( strlen ( string ) >= PUSTRING_MAX )
-        return FALSE ;
-
-      for ( p = & string [ strlen(string) ] ;
-               p != &string[cursor_position] ; p-- )
-        *(p+1) = *p ;
-
-      *p = key ;
-      cursor_position++ ;
-      break ;
-  }
-
-  setValue ( string ) ;
-  normalize_cursors () ;
-  return TRUE ;
-}
-
-
diff --git a/Lib/PUI/puInterface.cxx b/Lib/PUI/puInterface.cxx
deleted file mode 100644
index 500f82971..000000000
--- a/Lib/PUI/puInterface.cxx
+++ /dev/null
@@ -1,268 +0,0 @@
-
-#include "puLocal.h"
-
-#define PUSTACK_MAX 100
-
-static int currLiveInterface = -1 ;
-static puInterface *liveInterfaceStack [ PUSTACK_MAX ] ;
-static int currInterface = -1 ;
-static puInterface *interfaceStack [ PUSTACK_MAX ] ;
-
-void puPushLiveInterface ( puInterface *in )
-{
-  if ( currLiveInterface < PUSTACK_MAX )
-    liveInterfaceStack [ ++currLiveInterface ] = in ;
-  else
-    fprintf ( stderr, "PUI: Too many live puInterfaces open at once!\n" ) ;
-}
-
-void puPushInterface ( puInterface *in )
-{
-  if ( currInterface < PUSTACK_MAX )
-    interfaceStack [ ++currInterface ] = in ;
-  else
-    fprintf ( stderr, "PUI: Too many puInterfaces open at once!\n" ) ;
-}
-
-void  puPopLiveInterface ( void )
-{
-  if ( currLiveInterface > 0 )
-    --currLiveInterface ;
-  else 
-    fprintf ( stderr, "PUI: Live puInterface stack is empty!\n" ) ;
-}
-
-void  puPopInterface ( void )
-{
-  if ( currInterface > 0 )
-    --currInterface ;
-  else 
-    fprintf ( stderr, "PUI: puInterface stack is empty!\n" ) ;
-}
-
-int  puNoLiveInterface ( void )
-{
-  return currLiveInterface < 0 ;
-}
-
-int  puNoInterface ( void )
-{
-  return currInterface < 0 ;
-}
-
-puInterface *puGetUltimateLiveInterface ( void )
-{
-  if ( currLiveInterface < 0 )
-  {
-    fprintf ( stderr, "PUI: No Live Interface!\n" ) ;
-    return NULL ;
-  }
-
-  return liveInterfaceStack [ 0 ] ;
-}
-
-
-puInterface *puGetBaseLiveInterface ( void )
-{
-  if ( currLiveInterface < 0 )
-  {
-    fprintf ( stderr, "PUI: No Live Interface!\n" ) ;
-    return NULL ;
-  }
-
-  /*
-    Work down the interface stack until you
-    either get to the bottom or find a block
-    in the form of a puDialogBox.
-  */
-
-  for ( int i = currLiveInterface ; i > 0 ; i-- )
-    if ( liveInterfaceStack [ i ] -> getType () & PUCLASS_DIALOGBOX )
-      return liveInterfaceStack [ i ] ; 
-
-  return liveInterfaceStack [ 0 ] ;
-}
-
-puInterface *puGetCurrInterface ( void )
-{
-  if ( currInterface < 0 )
-  {
-    fprintf ( stderr, "PUI: No Interface!\n" ) ;
-    return NULL ;
-  }
-
-  return interfaceStack [ currInterface ] ;
-}
-
-void puInterface::remove ( puObject *obj )
-{
-  if ( dlist == NULL )
-    return ;
-
-  /* Are we the first object in the list */
-
-  if ( obj -> prev == NULL )
-    dlist = obj -> next ;
-  else
-    obj -> prev -> next = obj -> next ;
-
-  /* Are we the last object in the list */
-
-  if ( obj -> next != NULL )
-    obj -> next -> prev = obj -> prev ;
-
-  obj -> next = NULL ;
-  obj -> prev = NULL ;
-
-  num_children-- ;
-  recalc_bbox () ;
-}
-
-void puInterface::add ( puObject *new_obj )
-{
-  if ( dlist == NULL )
-  {
-    dlist = new_obj ;
-    new_obj -> next = NULL ;
-    new_obj -> prev = NULL ;
-  }
-  else
-  {
-    puObject *last ;
-
-    for ( last = dlist ; last->next != NULL ; last = last->next )
-      /* Search for end of list. */ ;
-
-    last -> next = new_obj ;
-    new_obj -> prev = last ;
-    new_obj -> next = NULL ;
-  }
-
-  num_children++ ;
-  recalc_bbox () ;
-}
-
-int puInterface::checkKey ( int key, int updown )
-{
-  if ( dlist == NULL || ! isVisible () || ! isActive () )
-    return FALSE ;
-
-  puObject *bo ;
-
-  /*
-    We have to walk the list backwards to ensure that
-    the click order is the same as the DRAW order.
-  */
-
-  for ( bo = dlist ; bo->next != NULL ; bo = bo->next )
-    /* Find the last object in our list. */ ;
-
-  for ( ; bo != NULL ; bo = bo->prev )
-    if ( bo -> checkKey ( key, updown ) )
-      return TRUE ;
-
-  return FALSE ;
-}
-
-int puInterface::checkHit ( int button, int updown, int x, int y )
-{
-  if ( dlist == NULL || ! isVisible () || ! isActive () )
-    return FALSE ;
-
-  /*
-    This might be a bit redundant - but it's too hard to keep
-    track of changing abox sizes when daughter objects are
-    changing sizes.
-  */
-
-  recalc_bbox () ;
-
-  puObject *bo ;
-
-  x -= abox.min[0] ;
-  y -= abox.min[1] ;
-
-  /*
-    We have to walk the list backwards to ensure that
-    the click order is the same as the DRAW order.
-  */
-
-  for ( bo = dlist ; bo->next != NULL ; bo = bo->next )
-    /* Find the last object in our list. */ ;
-
-  for ( ; bo != NULL ; bo = bo->prev )
-    if ( bo -> checkHit ( button, updown, x, y ) )
-      return TRUE ;
-
-  return FALSE ;
-}
-
-
-void puInterface::draw ( int dx, int dy )
-{
-  if ( ! isVisible () )
-    return ;
-
-  for ( puObject *bo = dlist ; bo != NULL ; bo = bo->next )
-  {
-    /* June 16th, 98, Shammi :
-     * The next if statement checks if the object is
-     * a menu bar and makes sure it is repositioned
-     * correctly.
-     */
-
-    if ( bo->getType() & PUCLASS_MENUBAR )
-    {
-      int obWidth, obHeight ;
-      bo -> getSize ( &obWidth, &obHeight ) ;
-      bo -> setPosition ( 0, puGetWindowHeight() - obHeight ) ;
-    }
-
-    bo -> draw ( dx + abox.min[0], dy + abox.min[1] ) ;
-  }
-}
-
-
-void puInterface::recalc_bbox ( void ) 
-{
-  puBox contents ;
-  contents . empty () ;
-
-  for ( puObject *bo = dlist ; bo != NULL ; bo = bo->next )
-    contents . extend ( bo -> getBBox() ) ;
-
-  if ( contents . isEmpty () )
-  {
-    abox . max[0] = abox . min[0] ;
-    abox . max[1] = abox . min[1] ;
-  }
-  else
-  {
-    abox . max[0] = abox . min[0] + contents . max[0] ;
-    abox . max[1] = abox . min[1] + contents . max[1] ;
-  }
-
-  puObject::recalc_bbox () ;
-}
-
-
-void puInterface::doHit ( int, int, int, int )
-{
-}
-
-
-puInterface::~puInterface ()
-{
-    puPopLiveInterface () ;
-
-    puObject *bo = dlist ;
-
-    while ( bo != NULL ) {
-	puObject *tmp_bo = bo->next ;
-	delete bo ;
-	bo = tmp_bo ;
-    }
-}
-
-
-
diff --git a/Lib/PUI/puLocal.h b/Lib/PUI/puLocal.h
deleted file mode 100644
index a366d2873..000000000
--- a/Lib/PUI/puLocal.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifdef HAVE_CONFIG_H
-#  include 
-#endif
-
-#include 
-#include 
-#include 
-#ifdef WIN32
-#include 
-#else
-#include 
-#endif
-#include 
-
-#ifndef PU_NOT_USING_GLUT
-#include 
-#endif
-#include "pu.h"
-
diff --git a/Lib/PUI/puMenuBar.cxx b/Lib/PUI/puMenuBar.cxx
deleted file mode 100644
index 87a2299b4..000000000
--- a/Lib/PUI/puMenuBar.cxx
+++ /dev/null
@@ -1,83 +0,0 @@
-
-#include "puLocal.h"
-
-void drop_down_the_menu ( puObject *b )
-{
-  puPopupMenu *p = (puPopupMenu *) b -> getUserData () ;
-
-  if ( b -> getValue () )
-    p->reveal () ;
-  else
-    p->hide () ;
-
-  for ( puObject *child = b -> getParent () -> getFirstChild () ;
-        child != NULL ; child = child -> next )
-  {
-    if (( child -> getType() & PUCLASS_BUTTON    ) != 0 && child != b ) child -> clrValue () ;
-    if (( child -> getType() & PUCLASS_POPUPMENU ) != 0 && child != p ) child -> hide     () ;
-  }
-}
-
-void puMenuBar::add_submenu ( char *str, char *items[], puCallback cb[] )
-{
-  int w, h ;
-  getSize ( &w, &h ) ;
-
-  puOneShot    *b = new puOneShot ( w+10, 0, str ) ;
-  b -> setStyle ( PUSTYLE_SPECIAL_UNDERLINED ) ;
-  b -> setColourScheme ( colour[PUCOL_FOREGROUND][0],
-                         colour[PUCOL_FOREGROUND][1],
-                         colour[PUCOL_FOREGROUND][2],
-                         colour[PUCOL_FOREGROUND][3] ) ;
-  b -> setCallback ( drop_down_the_menu ) ;
-  b -> setActiveDirn ( PU_UP_AND_DOWN ) ;
-
-  puPopupMenu *p = new puPopupMenu ( w+10, 0 ) ;
-
-  b -> setUserData ( p ) ;
-
-  for ( int i = 0 ; items[i] != NULL ; i++ )
-    p -> add_item ( items[i], cb[i] ) ;
-
-  p->close () ;
-  recalc_bbox () ;
-}
-
-void puMenuBar::close (void)
-{
-  puInterface::close () ;
-
-  if ( dlist == NULL )
-    return ;
-
-  int width = 0 ;
-  puObject *ob ;
-
-  /*
-    Use alternate objects - which gets the puOneShot/puPopupMenu pairs
-  */
-
-  for ( ob = dlist ; ob != NULL ; ob = ob -> next )
-  {
-    int w, h ;
-
-    /* Reposition the button so it looks nice */
-
-    ob -> getSize ( &w, &h ) ;
-    ob -> setPosition ( width, 0 ) ;
-    ob = ob -> next ;
-
-    /* Reposition the submenu so it sits under the button */
-
-    int w2, h2 ;
-    ob -> getSize ( &w2, &h2 ) ;
-    ob -> setPosition ( width, -h2 ) ;
-
-    /* Next please! */
-    width += w ;
-  }
-
-  recalc_bbox () ;
-}
-
-
diff --git a/Lib/PUI/puObject.cxx b/Lib/PUI/puObject.cxx
deleted file mode 100644
index 00fc5a26c..000000000
--- a/Lib/PUI/puObject.cxx
+++ /dev/null
@@ -1,222 +0,0 @@
-
-#include "puLocal.h"
-
-inline float clamp01 ( float x )
-{
-  return (x >= 1.0f) ? 1.0f : x ;
-}
-
-static void load_colour_scheme ( float col[][4], float r, float g,
-                                                 float b, float a )
-{
-  puSetColour ( col [ PUCOL_FOREGROUND ], r, g, b, a ) ;
-  puSetColour ( col [ PUCOL_BACKGROUND ], r/2, g/2, b/2, a ) ;
-  puSetColour ( col [ PUCOL_HIGHLIGHT  ], clamp01(r*1.3f), clamp01(g*1.3f),
-                                             clamp01(b*1.3f), a ) ;
-
-  if ( 4 * g + 3 * r + b > 0.5 )
-    puSetColour ( col [ PUCOL_LEGEND ], 0.0, 0.0, 0.0, a ) ;
-  else
-    puSetColour ( col [ PUCOL_LEGEND ], 1.0, 1.0, 1.0, a ) ;
-}
-
-
-static int    defaultStyle = PUSTYLE_DEFAULT ;
-static puFont defaultLegendFont = NULL ;
-static puFont defaultLabelFont  = NULL ;
-static float  defaultColourScheme [ 4 ] ;
-
-void puSetDefaultStyle ( int  style ) { defaultStyle = style ; }
-int   puGetDefaultStyle ( void ) { return defaultStyle ; }
-
-void puSetDefaultFonts ( puFont legendFont, puFont labelFont )
-{
-  defaultLegendFont = legendFont ;
-  defaultLabelFont  = labelFont ;
-}
-
-void puGetDefaultFonts ( puFont *legendFont, puFont *labelFont )
-{
-  if ( legendFont ) *legendFont = defaultLegendFont ;
-  if ( labelFont  ) *labelFont  = defaultLabelFont  ;
-}
-
-void puSetDefaultColourScheme ( float r, float g, float b, float a )
-{
-  defaultColourScheme[0] = r ;
-  defaultColourScheme[1] = g ;
-  defaultColourScheme[2] = b ;
-  defaultColourScheme[3] = a ;
-  load_colour_scheme ( _puDefaultColourTable, r, g, b, a ) ;
-}
-
-void puGetDefaultColourScheme ( float *r, float *g, float *b, float *a )
-{
-  if ( r ) *r = defaultColourScheme[0] ;
-  if ( g ) *g = defaultColourScheme[1] ;
-  if ( b ) *b = defaultColourScheme[2] ;
-  if ( a ) *a = defaultColourScheme[3] ;
-}
-
-
-
-void puObject::setColourScheme ( float r, float g, float b, float a )
-{
-  load_colour_scheme ( colour, r, g, b, a ) ;
-}
-
-puObject::puObject ( int minx, int miny, int maxx, int maxy ) : puValue ()
-{
-  type |= PUCLASS_OBJECT ;
-  bbox.min[0] = abox.min[0] = minx ;
-  bbox.min[1] = abox.min[1] = miny ;
-  bbox.max[0] = abox.max[0] = maxx ;
-  bbox.max[1] = abox.max[1] = maxy ;
-
-  active_mouse_edge = PU_UP ;
-  style      = defaultStyle ;
-  visible = active  = TRUE  ;
-  highlighted       = FALSE ;
-  am_default        = FALSE ;
-
-  cb          = NULL ;
-  user_data   = NULL ;
-  next = prev = NULL ;
-  label       = NULL ;
-  labelPlace  = PUPLACE_DEFAULT   ;
-  labelFont   = defaultLabelFont  ;
-  legend      = NULL ;
-  legendFont  = defaultLegendFont ;
-
-  for ( int i = 0 ; i < PUCOL_MAX ; i++ )
-    puSetColour ( colour[i], _puDefaultColourTable[i] ) ;
-
-  if ( ! puNoInterface() )
-  {
-    parent = puGetCurrInterface() ;
-    parent -> add ( this ) ;
-  }
-  else
-    parent = NULL ;
-}
-
-
-puObject::~puObject ()
-{
-  if ( parent != this && parent != NULL )
-    parent -> remove ( this ) ;
-}
-
-void puObject::recalc_bbox ( void )
-{
-  bbox = abox ;
-
-  if ( label != NULL )
-    switch ( labelPlace )
-    {
-      case PUPLACE_ABOVE : bbox.max[1] += puGetStringHeight ( getLabelFont() ) + puGetStringDescender ( getLabelFont () ) + PUSTR_TGAP + PUSTR_BGAP ; break ;
-      case PUPLACE_BELOW : bbox.min[1] -= puGetStringHeight ( getLabelFont() ) + puGetStringDescender ( getLabelFont () ) + PUSTR_TGAP + PUSTR_BGAP ; break ;
-      case PUPLACE_LEFT  : bbox.min[0] -= puGetStringWidth  ( getLabelFont(), getLabel() ) + PUSTR_LGAP + PUSTR_RGAP ; break ;
-      case PUPLACE_RIGHT : bbox.max[0] += puGetStringWidth  ( getLabelFont(), getLabel() ) + PUSTR_LGAP + PUSTR_RGAP ; break ;
-    }
-
-  if ( parent != NULL )
-    parent -> recalc_bbox () ;
-}
-
-void puObject::draw_label ( int dx, int dy )
-{
-  if ( !visible ) return ;
-
-  /* If greyed out then halve the opacity when drawing the label */
-
-  if ( active )
-    glColor4fv ( colour [ PUCOL_LABEL ] ) ;
-  else
-    glColor4f ( colour [ PUCOL_LABEL ][0],
-                colour [ PUCOL_LABEL ][1],
-                colour [ PUCOL_LABEL ][2],
-                colour [ PUCOL_LABEL ][3] / 2.0f ) ; /* 50% more transparent */
-
-  switch ( labelPlace )
-  {
-    case PUPLACE_ABOVE : puDrawString ( labelFont, label, dx + abox.min[0] + PUSTR_LGAP, dy + abox.max[1] + puGetStringDescender(labelFont) + PUSTR_BGAP ) ; break ;
-    case PUPLACE_BELOW : puDrawString ( labelFont, label, dx + abox.min[0] + PUSTR_LGAP, dy + bbox.min[1] + puGetStringDescender(labelFont) + PUSTR_BGAP ) ; break ;
-    case PUPLACE_LEFT  : puDrawString ( labelFont, label, dx + bbox.min[0] + PUSTR_LGAP, dy + abox.min[1] + puGetStringDescender(labelFont) + PUSTR_BGAP ) ; break ;
-    case PUPLACE_RIGHT : puDrawString ( labelFont, label, dx + abox.max[0] + PUSTR_LGAP, dy + abox.min[1] + puGetStringDescender(labelFont) + PUSTR_BGAP ) ; break ;
-  }
-}
-
-
-int puObject::checkKey ( int key, int updown )
-{
-  if ( updown == PU_UP )
-    return FALSE ;
-
-  if ( isReturnDefault() && ( key == '\r' || key == '\n' ) )
-  {
-    checkHit ( PU_LEFT_BUTTON, PU_DOWN, (abox.min[0]+abox.max[0])/2,
-                                        (abox.min[1]+abox.max[1])/2 ) ;
-    checkHit ( PU_LEFT_BUTTON, PU_UP  , (abox.min[0]+abox.max[0])/2,
-                                        (abox.min[1]+abox.max[1])/2 ) ;
-    return TRUE ;
-  }
-
-  return FALSE ;
-}
-
-
-void puObject::doHit ( int button, int updown, int x, int y )
-{
-  (x,x);(y,y);
-
-  if ( button == PU_LEFT_BUTTON )
-  {
-    if ( updown == active_mouse_edge || active_mouse_edge == PU_UP_AND_DOWN )
-    {
-      lowlight () ;
-      invokeCallback () ;
-    }
-    else
-      highlight () ;
-  }
-  else
-    lowlight () ;
-}
-
-int puObject::checkHit ( int button, int updown, int x, int y )
-{
-  if ( isHit( x, y ) )
-  {
-    doHit ( button, updown, x, y ) ;
-    return TRUE ;
-  }
-
-  lowlight () ;
-  return FALSE ;
-}
-
- 
-char *puValue::getTypeString ( void )
-{
-  int i = getType () ;
-
-  if ( i & PUCLASS_DIALOGBOX   ) return "puDialogBox" ;
-  if ( i & PUCLASS_SLIDER      ) return "puSlider" ;
-  if ( i & PUCLASS_BUTTONBOX   ) return "puButtonBox" ;
-  if ( i & PUCLASS_INPUT       ) return "puInput" ;
-  if ( i & PUCLASS_MENUBAR     ) return "puMenuBar" ;
-  if ( i & PUCLASS_POPUPMENU   ) return "puPopupMenu" ;
-  if ( i & PUCLASS_POPUP       ) return "puPopup" ;
-  if ( i & PUCLASS_ONESHOT     ) return "puOneShot" ;
-  if ( i & PUCLASS_BUTTON      ) return "puButton" ;
-  if ( i & PUCLASS_TEXT        ) return "puText" ;
-  if ( i & PUCLASS_FRAME       ) return "puFrame" ;
-  if ( i & PUCLASS_INTERFACE   ) return "puInterface" ;
-  if ( i & PUCLASS_OBJECT      ) return "puObject" ;
-  if ( i & PUCLASS_VALUE       ) return "puValue" ;
-
-  return "Unknown Object type." ;
-}
-
-
diff --git a/Lib/PUI/puOneShot.cxx b/Lib/PUI/puOneShot.cxx
deleted file mode 100644
index 7d0f7c9ba..000000000
--- a/Lib/PUI/puOneShot.cxx
+++ /dev/null
@@ -1,9 +0,0 @@
-
-#include "puLocal.h"
-
-void puOneShot::doHit ( int button, int updown, int x, int y )
-{
-  puButton::doHit ( button, updown, x, y ) ;
-  setValue ( 0 ) ;
-}
-
diff --git a/Lib/PUI/puPopup.cxx b/Lib/PUI/puPopup.cxx
deleted file mode 100644
index 59a5fef5c..000000000
--- a/Lib/PUI/puPopup.cxx
+++ /dev/null
@@ -1,3 +0,0 @@
-
-#include "puLocal.h"
-
diff --git a/Lib/PUI/puPopupMenu.cxx b/Lib/PUI/puPopupMenu.cxx
deleted file mode 100644
index 0eed10231..000000000
--- a/Lib/PUI/puPopupMenu.cxx
+++ /dev/null
@@ -1,175 +0,0 @@
-#include "puLocal.h"
-
-#define PUMENU_BUTTON_HEIGHT       25
-#define PUMENU_BUTTON_EXTRA_WIDTH  25
-
-puObject *puPopupMenu::add_item ( char *str, puCallback cb )
-{
-  int w, h ;
-  getSize ( &w, &h ) ;
-  puOneShot *b = new puOneShot ( 0, h, str ) ;
-  b->setStyle        ( PUSTYLE_PLAIN ) ;
-  b->setColourScheme ( colour[PUCOL_FOREGROUND][0],
-		       colour[PUCOL_FOREGROUND][1],
-		       colour[PUCOL_FOREGROUND][2],
-		       colour[PUCOL_FOREGROUND][3] ) ;
-  b->setCallback     ( cb ) ;
-  recalc_bbox () ;
-  return b ;
-}
-
-void puPopupMenu::close ( void )
-{
-  puPopup::close () ;
-
-  int widest = 0 ;
-  puObject *ob = dlist ;
-
-  /*
-   * June 17th, 1998, Shammi
-   * There seems to be some mismatch with the
-   * #define pumenusize and the actual size
-   * There seems to be some overlap resulting
-   * in more than one option being highlighted.
-   * By setting the size to the actual values,
-   * the overlap area seems to be less now.
-   */
-
-  int w, h ;
-
-  for ( ob = dlist ; ob != NULL ; ob = ob -> next )
-  {
-    ob -> getSize ( &w, &h ) ;
-
-    if ( w > widest ) widest = w ;
-  }
-
-  for ( ob = dlist ; ob != NULL ; ob = ob -> next )
-  {
-    ob -> getSize ( &w, &h ) ;
-    ob -> setSize ( widest, h ) ;
-  }
-
-  recalc_bbox () ;
-}
-
-
-int puPopupMenu::checkKey ( int key, int updown )
-{
-  if ( dlist == NULL || ! isVisible () || ! isActive () )
-    return FALSE ;
-
-  if ( updown == PU_DOWN )
-  {
-    hide () ;
-
-    /* Turn everything off ready for next time. */
-
-    for ( puObject *bo = dlist ; bo != NULL ; bo = bo->next )
-      bo -> clrValue () ;
-  }
-
-  puObject *bo ;
-
-  /*
-    We have to walk the list backwards to ensure that
-    the click order is the same as the DRAW order.
-  */
-
-  for ( bo = dlist ; bo->next != NULL ; bo = bo->next )
-    /* Find the last object in our list. */ ;
-
-  for ( ; bo != NULL ; bo = bo->prev )
-    if ( bo -> checkKey ( key, updown ) )
-      return TRUE ;
-
-  return FALSE ;
-}
-
-
-int puPopupMenu::checkHit ( int button, int updown, int x, int y )
-{
-  if ( dlist == NULL || ! isVisible () || ! isActive () )
-    return FALSE ;
-
-  /* Must test 'isHit' before making the menu invisible! */
-
-  int hit = isHit ( x, y ) ;
-
-  /*
-   * June 17th, 1998, Shammi :
-   * There seemed to be a miscalculation with the menus initially
-   * Therefore I moved the recalculation stuff before the clearing.
-   */
-
-  /*
-    This might be a bit redundant - but it's too hard to keep
-    track of changing abox sizes when daughter objects are
-    changing sizes.
-  */
-
-  recalc_bbox();
-  x -= abox.min[0] ;
-  y -= abox.min[1] ;
-
-  /*
-   * June 17th, 1998, Shammi :
-   * Also clear the menu when the dragging the mouse and not hit.
-   */
-
-  if (   updown == active_mouse_edge || active_mouse_edge == PU_UP_AND_DOWN ||
-       ( updown == PU_DRAG && !hit ) )
-  {
-
-    /* June 17th, 1998, Shammi :
-     * Do not hide the menu if mouse is dragged out
-     */
-
-    if ( updown != PU_DRAG )
-      hide () ;
-
-    /* Turn everything off ready for next time. */
-
-    /* June 17th, 1998, Shammi:
-     * Make sure we check for a hit, if the mouse is moved
-     * out of the menu.
-     */
-
-    for ( puObject *bo = dlist ; bo != NULL ; bo = bo->next )
-    {
-      if ( ! hit )
-	bo -> checkHit ( button, updown, x , y ) ;
-
-      bo -> clrValue () ;
-    }
-  }
-
-  if ( ! hit )
-    return FALSE ;
-
-  puObject *bo ;
-  
-  /*
-    We have to walk the list backwards to ensure that
-    the click order is the same as the DRAW order.
-  */
-
-  /* June 17th, 1998, Shammi :
-   * If the mouse is dragged and the menuItem is not hit, 
-   * clear it
-   */
-
-  for ( bo = dlist ; bo->next != NULL ; bo = bo->next )
-    if ( updown == PU_DRAG && ! bo -> checkHit ( button, updown, x, y ) )
-      bo -> clrValue () ;
-
-    /* Find the last object in our list. */ ;
-
-  for ( ; bo != NULL ; bo = bo->prev )
-    if ( bo -> checkHit ( button, updown, x, y ) )
-      return TRUE ;
-
-  return FALSE ;
-}
-
-
diff --git a/Lib/PUI/puSlider.cxx b/Lib/PUI/puSlider.cxx
deleted file mode 100644
index aeab8f170..000000000
--- a/Lib/PUI/puSlider.cxx
+++ /dev/null
@@ -1,107 +0,0 @@
-
-#include "puLocal.h"
-
-void puSlider::draw ( int dx, int dy )
-{
-  if ( !visible ) return ;
-
-  abox . draw ( dx, dy,
-                (style==PUSTYLE_BEVELLED||
-                 style==PUSTYLE_SHADED) ? -PUSTYLE_BOXED : -style,
-                colour, FALSE ) ;
-
-  int sd, od ;
-
-  if ( isVertical() ) { sd = 1 ; od = 0 ; } else { sd = 0 ; od = 1 ; }
-
-  int sz = abox.max [sd] - abox.min [sd] ;
-
-  float val ;
-
-  getValue ( & val ) ;
-
-  if ( val < 0.0f ) val = 0.0f ;
-  if ( val > 1.0f ) val = 1.0f ;
-
-  val *= (float) sz * (1.0f - slider_fraction) ;
-
-  puBox bx ;
-    
-  bx . min [ sd ] = abox . min [ sd ] + (int) val ;
-  bx . max [ sd ] = (int) ( (float) bx . min [ sd ] + (float) sz * slider_fraction ) ;
-  bx . min [ od ] = abox . min [ od ] + 2 ;
-  bx . max [ od ] = abox . max [ od ] - 2 ;
-
-  bx . draw ( dx, dy, PUSTYLE_SMALL_SHADED, colour, FALSE ) ;
-
-  /* If greyed out then halve the opacity when drawing the label and legend */
-
-  if ( active )
-    glColor4fv ( colour [ PUCOL_LEGEND ] ) ;
-  else
-    glColor4f ( colour [ PUCOL_LEGEND ][0],
-                colour [ PUCOL_LEGEND ][1],
-                colour [ PUCOL_LEGEND ][2],
-                colour [ PUCOL_LEGEND ][3] / 2.0f ) ; /* 50% more transparent */
-
-  int xx = ( abox.max[0] - abox.min[0] - puGetStringWidth(legendFont,legend) ) / 2 ;
-  int yy = ( abox.max[1] - abox.min[1] - puGetStringHeight(legendFont) ) / 2 ;
-
-  puDrawString ( legendFont, legend,
-                  dx + abox.min[0] + xx,
-                  dy + abox.min[1] + yy ) ;
-
-  draw_label ( dx, dy ) ;
-}
-
-
-void puSlider::doHit ( int button, int updown, int x, int y )
-{
-  if ( button == PU_LEFT_BUTTON )
-  {
-    int sd = isVertical() ;
-    int sz = abox.max [sd] - abox.min [sd] ;
-    int coord = isVertical() ? y : x ;
-
-    float next_value ;
-
-    if ( sz == 0 )
-      next_value = 0.5f ;
-    else
-    {
-      next_value = ( (float)coord - (float)abox.min[sd] - (float)sz * slider_fraction / 2.0f ) /
-                   ( (float) sz * (1.0f - slider_fraction) ) ;
-    }
-
-    next_value = (next_value < 0.0f) ? 0.0f : (next_value > 1.0) ? 1.0f : next_value ;
-
-    setValue ( next_value ) ;
-
-    switch ( cb_mode )
-    {
-      case PUSLIDER_CLICK :
-        if ( updown == active_mouse_edge )
-        {
-	  last_cb_value = next_value ;
-	  invokeCallback () ;
-        }
-        break ;
-
-      case PUSLIDER_DELTA :
-        if ( fabs ( last_cb_value - next_value ) >= cb_delta )
-        {
-	  last_cb_value = next_value ;
-	  invokeCallback () ;
-        }
-        break ;
-
-      case PUSLIDER_ALWAYS :
-      default :
-        last_cb_value = next_value ;
-        invokeCallback () ;
-        break ;
-    }
-  }
-}
-
-
diff --git a/Lib/PUI/puText.cxx b/Lib/PUI/puText.cxx
deleted file mode 100644
index 032c01629..000000000
--- a/Lib/PUI/puText.cxx
+++ /dev/null
@@ -1,8 +0,0 @@
-
-#include "puLocal.h"
-
-void puText::draw ( int dx, int dy )
-{
-  draw_label ( dx, dy ) ;
-}
-
diff --git a/Lib/Serial/serial.cxx b/Lib/Serial/serial.cxx
index ed580f8af..15527b3ea 100644
--- a/Lib/Serial/serial.cxx
+++ b/Lib/Serial/serial.cxx
@@ -336,6 +336,9 @@ int fgSERIAL::write_port(const string& value) {
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:34  curt
+// Initial revision
+//
 // Revision 1.9  1999/02/02 20:13:23  curt
 // MSVC++ portability changes by Bernie Bright:
 //
diff --git a/Lib/Serial/serial.hxx b/Lib/Serial/serial.hxx
index 3b2c60b68..6f763bce8 100644
--- a/Lib/Serial/serial.hxx
+++ b/Lib/Serial/serial.hxx
@@ -80,6 +80,9 @@ public:
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:34  curt
+// Initial revision
+//
 // Revision 1.5  1999/03/02 01:01:58  curt
 // Tweaks for compiling with native SGI compilers.
 //
diff --git a/Lib/example/Makefile.am b/Lib/example/Makefile.am
deleted file mode 100644
index 8528348b9..000000000
--- a/Lib/example/Makefile.am
+++ /dev/null
@@ -1,17 +0,0 @@
-bin_PROGRAMS = example
-
-example_SOURCES = example.cxx
-
-example_LDADD = \
-	$(top_builddir)/Lib/Audio/src/libsl.a \
-	$(top_builddir)/Lib/Audio/src/libsm.a
-
-INCLUDES += -I$(top_builddir)/Lib/Audio/src
-
-if ENABLE_IRIX_AUDIO
-LIBS += -laudio
-endif
-
-if ENABLE_WIN32_AUDIO
-LIBS += -lwinmm
-endif
diff --git a/Lib/example/example.cxx b/Lib/example/example.cxx
deleted file mode 100644
index ae519786d..000000000
--- a/Lib/example/example.cxx
+++ /dev/null
@@ -1,89 +0,0 @@
-
-
-#include "sl.h"
-#include "sm.h"
-#include 
-
-/*
-  Construct a sound scheduler and a mixer.
-*/
-
-slScheduler sched ( 8000 ) ;
-smMixer mixer ;
-
-int main ()
-{
-  mixer . setMasterVolume ( 30 ) ;
-  sched . setSafetyMargin ( 0.128 ) ;
-
-  /* Just for fun, let's make a one second synthetic engine sample... */
-
-  Uchar buffer [ 8000 ] ;
-
-  for ( int i = 0 ; i < 8000 ; i++ )
-  {
-    /* Sum some sin waves and convert to range 0..1 */
-
-    float level = ( sin ( (double) i * 2.0 * M_PI / (8000.0/ 50.0) ) +
-                    sin ( (double) i * 2.0 * M_PI / (8000.0/149.0) ) +
-                    sin ( (double) i * 2.0 * M_PI / (8000.0/152.0) ) +
-                    sin ( (double) i * 2.0 * M_PI / (8000.0/192.0) )
-                  ) / 8.0f + 0.5f ;
-
-    /* Convert to unsigned byte */
-
-    buffer [ i ] = (Uchar) ( level * 255.0 ) ;
-  }
-
-  /* Set up four samples and a loop */
-
-  slSample  *s = new slSample ( buffer, 8000 ) ;
-  slSample *s1 = new slSample ( "scream.ub", & sched ) ;
-  slSample *s2 = new slSample ( "zzap.wav" , & sched ) ;
-  slSample *s3 = new slSample ( "cuckoo.au", & sched ) ;
-  slSample *s4 = new slSample ( "wheeee.ub", & sched ) ;
-
-  /* Mess about with some of the samples... */
-
-  s1 -> adjustVolume ( 2.2  ) ;
-  s2 -> adjustVolume ( 0.5  ) ;
-  s3 -> adjustVolume ( 0.2  ) ;
-
-  /* Play the engine sample continuously. */
-
-  sched . loopSample ( s ) ;
-
-  int tim = 0 ;  /* My periodic event timer. */
-
-  while ( SL_TRUE )
-  {
-    tim++ ;  /* Time passes */
-
-    if ( tim % 200 == 0 ) sched.playSample ( s1 ) ;
-    if ( tim % 180 == 0 ) sched.playSample ( s2 ) ;
-    if ( tim % 150 == 0 ) sched.playSample ( s3 ) ;
-    if ( tim % 120 == 0 ) sched.playSample ( s4 ) ;
-
-    /*
-      For the sake of realism, I'll delay for 1/30th second to
-      simulate a graphics update process.
-    */
-
-#ifdef WIN32
-    Sleep ( 1000 / 30 ) ;      /* 30Hz */
-#elif defined(sgi)
-    sginap( 3 );               /* ARG */
-#else
-    usleep ( 1000000 / 30 ) ;  /* 30Hz */
-#endif
-
-    /*
-      This would normally be called just before the graphics buffer swap
-      - but it could be anywhere where it's guaranteed to get called
-      fairly often.
-    */
-
-    sched . update () ;
-  }
-}
-
diff --git a/Lib/src/Makefile.am b/Lib/src/Makefile.am
deleted file mode 100644
index e9f453178..000000000
--- a/Lib/src/Makefile.am
+++ /dev/null
@@ -1,10 +0,0 @@
-noinst_LIBRARIES = libsl.a libsm.a
-
-libsl_a_SOURCES = \
-	sl.h slPortability.h \
-	slDSP.cxx slSample.cxx slEnvelope.cxx \
-	slSamplePlayer.cxx slScheduler.cxx
-
-libsm_a_SOURCES = sm.h slPortability.h smMixer.cxx
-
-INCLUDES += -I$(top_builddir) -I.
diff --git a/Lib/src/sl.h b/Lib/src/sl.h
deleted file mode 100644
index 5cbbc2adf..000000000
--- a/Lib/src/sl.h
+++ /dev/null
@@ -1,629 +0,0 @@
-
-#ifndef __SL_H__
-#define __SL_H__ 1
-
-#include "slPortability.h"
-
-#ifdef SL_USING_OSS_AUDIO
-#define SLDSP_DEFAULT_DEVICE "/dev/dsp"
-#elif defined(WIN32)
-#define SLDSP_DEFAULT_DEVICE "dsp"	
-#elif defined(__OpenBSD__)
-#define SLDSP_DEFAULT_DEVICE "/dev/audio"
-#elif defined(sgi)
-#define SLDSP_DEFAULT_DEVICE "dsp"		// dummy ...
-#else
-#error "Port me !"
-#endif
-
-# define SL_TRUE  1
-# define SL_FALSE 0
-
-typedef unsigned char  Uchar  ;
-typedef unsigned short Ushort ;
-
-#define SL_DEFAULT_SAMPLING_RATE 11025
-
-class slSample       ;
-class slSamplePlayer ;
-class slEnvelope     ;
-class slScheduler    ;
-class slDSP          ;
-
-extern char *__slPendingError ;
-
-class slDSP
-{
-private:
-
-  int stereo ;
-  int rate ;
-  int bps ;
-
-  int error ;
-  int fd ;
-
-#ifdef __OpenBSD__
-  audio_info_t    ainfo;        // ioctl structure
-  audio_offset_t  audio_offset; // offset in audiostream
-  long            counter;      // counter-written packets
-#elif defined(SL_USING_OSS_AUDIO)
-  audio_buf_info buff_info ;
-#elif defined(sgi)
-  ALconfig        config;       // configuration stuff
-  ALport          port;         // .. we are here 
-#endif
-
-
-#ifndef WIN32
-  int ioctl ( int cmd, int param = 0 )
-  {
-    if ( error ) return param ;
-
-    if ( ::ioctl ( fd, cmd, & param ) == -1 )
-    {
-      perror ( "slDSP: ioctl" ) ;
-      error = SL_TRUE ;
-    }
-
-    return param ;
-  }
-
-#elif defined(WIN32)
-
-   HWAVEOUT       hWaveOut;      // device handle 
-   WAVEFORMATEX   Format;        // open needs this
-   MMTIME         mmt;	         // timing 
-   WAVEHDR        wavehdr[ 3 ];  // for round robin ..
-   int            curr_header;   // index of actual wavehdr
-   long           counter;       // counter-written packets
-
-#endif
-
-  void open ( char *device, int _rate, int _stereo, int _bps ) ;
-  void close () ;
-  void getBufferInfo () ;
-  void write ( void *buffer, size_t length ) ;
-
-protected:
-
-  void setError () { error = SL_TRUE ; }
-  int getDriverBufferSize () ;
-
-public:
-
-  slDSP ( int _rate = SL_DEFAULT_SAMPLING_RATE,
-          int _stereo = SL_FALSE, int _bps = 8 )
-  {
-    open ( SLDSP_DEFAULT_DEVICE, _rate, _stereo, _bps ) ;
-  } 
-
-  slDSP ( char *device, int _rate = SL_DEFAULT_SAMPLING_RATE,
-          int _stereo = SL_FALSE, int _bps = 8 )
-  {
-    open ( device, _rate, _stereo, _bps ) ;
-  } 
-
- ~slDSP () { close () ; }
-  
-  float secondsRemaining () ;
-  float secondsUsed () ;
-
-  void play ( void *buffer, size_t length ) { write ( buffer, length ) ; } 
-
-  int working () { return !error ; }
-  int not_working () { return error ; }
-
-  int getBps   () { return bps    ; }
-  int getRate  () { return rate   ; }
-  int getStereo() { return stereo ; }
-
-  void sync () ;
-  void stop () ;
-} ;
-
-
-class slSample
-{
-  int    ref_count ;
-protected:
-
-  char  *comment;
-  int    rate   ;
-  int    bps    ;
-  int    stereo ;
-
-  Uchar *buffer ;
-  int    length ;
-
-  void init ()
-  {
-    ref_count = 0 ;
-    comment = NULL  ;
-    buffer  = NULL  ;
-    length  = 0     ;
-    rate    = SL_DEFAULT_SAMPLING_RATE ;
-    bps     = 8     ;
-    stereo  = SL_FALSE ;
-  }
-
-public:
-
-  slSample () { init () ; }
-
-  slSample ( Uchar *buff, int leng )
-  {
-    init () ;
-    setBuffer ( buff, leng ) ;
-  }
-
-  slSample ( char *fname, class slDSP *dsp = NULL )
-  {
-    init () ;
-    loadFile ( fname ) ;
-    autoMatch ( dsp ) ;
-  }
-
- ~slSample ()
-  {
-    if ( ref_count != 0 && __slPendingError == NULL )
-      __slPendingError =
-        "slSample: FATAL ERROR - Application deleted a sample while it was playing.\n" ;
-
-    delete buffer ;
-  }
-  
-  void ref   () { ref_count++ ; }
-  void unRef () { ref_count-- ; }
-
-  int getPlayCount () { return ref_count ; }
-
-  char  *getComment () { return comment ; }
-
-  void   setComment ( char *nc )
-  {
-    delete comment ;
-    comment = new char [ strlen ( nc ) + 1 ] ;
-    strcpy ( comment, nc ) ;
-  }
-
-  Uchar *getBuffer () { return buffer ; }
-  int    getLength () { return length ; }
-
-  void  autoMatch ( slDSP *dsp ) ;
-
-  void   setBuffer ( Uchar *buff, int leng )
-  {
-    delete buffer ;
-
-    buffer = new Uchar [ leng ] ;
-
-    if ( buff != NULL )
-      memcpy ( buffer, buff, leng ) ;
-
-    length = leng ;
-  }
-
-  /* These routines only set flags - use changeXXX () to convert a sound */
-
-  void setRate   ( int r ) { rate   = r ; }
-  void setBps    ( int b ) { bps    = b ; }
-  void setStereo ( int s ) { stereo = s ; }
-
-  int  getRate   ()        { return rate   ; }
-  int  getBps    ()        { return bps    ; }
-  int  getStereo ()        { return stereo ; }
-
-  float getDuration ()     { return (float) getLength() /
-                                    (float) ( (getStereo()?2.0f:1.0f)*
-                                              (getBps()/8.0f)*getRate() ) ; }
-
-  int loadFile    ( char *fname ) ;
-
-  int loadRawFile ( char *fname ) ;
-  int loadAUFile  ( char *fname ) ;
-  int loadWavFile ( char *fname ) ;
-
-  void changeRate       ( int r ) ;
-  void changeBps        ( int b ) ;
-  void changeStereo     ( int s ) ;
-  void changeToUnsigned () ;
-
-  void adjustVolume ( float vol ) ;
-
-  void print ( FILE *fd )
-  {
-    if ( buffer == NULL )
-    {
-      fprintf ( fd, "Empty sample buffer\n" ) ;
-    }
-    else
-    {
-      fprintf ( fd, "\"%s\"\n",(getComment() == NULL ||
-                                getComment()[0]=='\0') ? "Sample" : comment  ) ;
-      fprintf ( fd, "%s, %d bits per sample.\n",
-			    getStereo() ? "Stereo" : "Mono", getBps() ) ;
-      fprintf ( fd, "%gKHz sample rate.\n", (float) getRate() / 1000.0f ) ;
-      fprintf ( fd, "%d bytes of samples == %g seconds duration.\n", getLength(), getDuration() ) ;
-    }
-  }
-} ;
-
-
-enum slSampleStatus
-{
-  SL_SAMPLE_WAITING,  /* Sound hasn't started playing yet */
-  SL_SAMPLE_RUNNING,  /* Sound has started playing */
-  SL_SAMPLE_DONE   ,  /* Sound is complete */
-  SL_SAMPLE_PAUSED    /* Sound hasn't started playing yet */
-} ;
-
-
-enum slPreemptMode
-{
-  SL_SAMPLE_CONTINUE,  /* Don't allow yourself to be preempted   */
-  SL_SAMPLE_ABORT   ,  /* Abort playing the sound when preempted */
-  SL_SAMPLE_RESTART ,  /* Restart the sound when load permits    */
-  SL_SAMPLE_MUTE    ,  /* Continue silently until load permits   */
-  SL_SAMPLE_DELAY      /* Pause until load permits               */
-} ;
-
-
-enum slReplayMode
-{
-  SL_SAMPLE_LOOP,      /* Loop sound so that it plays forever */
-  SL_SAMPLE_ONE_SHOT   /* Play sound just once */
-} ;
-
-enum slEvent
-{
-  SL_EVENT_COMPLETE,  /* Sound finished playing */
-  SL_EVENT_LOOPED,    /* Sound looped back to the start */
-  SL_EVENT_PREEMPTED  /* Sound was preempted */
-} ;
-
-typedef void (*slCallBack) ( slSample *, slEvent, int ) ;
-
-class slEnvelope
-{
-public:  /* SJB TESTING! */
-
-  float *time  ;
-  float *value ;
-  int   nsteps ;
-  int   ref_count ;
-
-  slReplayMode replay_mode ;
-
-  int getStepDelta ( float *_time, float *delta ) ;
-
-public:
-
-  slEnvelope ( int _nsteps, slReplayMode _rm, float *_times, float *_values )
-  {
-    ref_count = 0 ;
-    nsteps = _nsteps ;
-    time  = new float [ nsteps ] ;
-    value = new float [ nsteps ] ;
-    memcpy ( time , _times , sizeof(float) * nsteps ) ;
-    memcpy ( value, _values, sizeof(float) * nsteps ) ;
-
-    replay_mode = _rm ;
-  }
-
-
-  slEnvelope ( int _nsteps = 1, slReplayMode _rm = SL_SAMPLE_ONE_SHOT )
-  {
-    ref_count = 0 ;
-    nsteps = _nsteps ;
-    time  = new float [ nsteps ] ;
-    value = new float [ nsteps ] ;
-
-    for ( int i = 0 ; i < nsteps ; i++ )
-      time [ i ] = value [ i ] = 0.0 ;
-
-    replay_mode = _rm ;
-  }
- 
- ~slEnvelope ()
-  {
-    if ( ref_count != 0 && __slPendingError == NULL )
-      __slPendingError =
-      "slEnvelope: FATAL ERROR - Application deleted an envelope while it was playing.\n" ;
-
-    delete time ;
-    delete value ;
-  }
-
-  void ref   () { ref_count++ ; }
-  void unRef () { ref_count-- ; }
-
-  int getPlayCount () { return ref_count ; }
-
-  void setStep ( int n, float _time, float _value )
-  {
-    if ( n >= 0 && n < nsteps )
-    {
-      time  [ n ] = _time  ;
-      value [ n ] = _value ;
-    }
-  }
-
-  float getStepValue ( int s ) { return value [ s ] ; }
-  float getStepTime  ( int s ) { return time  [ s ] ; }
-
-  int   getNumSteps  () { return nsteps ; }
-
-  float getValue ( float _time ) ;
-
-  void applyToPitch     ( Uchar *dst, slSamplePlayer *src, int nframes, int start, int next_env ) ;
-  void applyToInvPitch  ( Uchar *dst, slSamplePlayer *src, int nframes, int start, int next_env ) ;
-  void applyToVolume    ( Uchar *dst, Uchar *src, int nframes, int start ) ;
-  void applyToInvVolume ( Uchar *dst, Uchar *src, int nframes, int start ) ;
-} ;
-
-#define SL_MAX_PRIORITY  16
-#define SL_MAX_SAMPLES   16
-#define SL_MAX_CALLBACKS (SL_MAX_SAMPLES * 2)
-#define SL_MAX_ENVELOPES 4
-
-enum slEnvelopeType
-{
-  SL_PITCH_ENVELOPE , SL_INVERSE_PITCH_ENVELOPE ,
-  SL_VOLUME_ENVELOPE, SL_INVERSE_VOLUME_ENVELOPE,
-  SL_FILTER_ENVELOPE, SL_INVERSE_FILTER_ENVELOPE,
-  SL_PAN_ENVELOPE   , SL_INVERSE_PAN_ENVELOPE   ,
-  SL_ECHO_ENVELOPE  , SL_INVERSE_ECHO_ENVELOPE  ,
-
-  SL_NULL_ENVELOPE
-} ;
-
-struct slPendingCallBack
-{
-  slCallBack callback ;
-  slSample  *sample   ;
-  slEvent    event    ;
-  int        magic    ;
-} ;
-
-class slSamplePlayer
-{
-  int            lengthRemaining ;  /* Sample frames remaining until repeat */
-  Uchar         *bufferPos       ;  /* Sample frame to replay next */
-  slSample      *sample          ;
-
-  slEnvelope    *env            [ SL_MAX_ENVELOPES ] ;
-  slEnvelopeType env_type       [ SL_MAX_ENVELOPES ] ;
-  int            env_start_time [ SL_MAX_ENVELOPES ] ;
-
-  slReplayMode   replay_mode     ;
-  slPreemptMode  preempt_mode    ;
-  slSampleStatus status          ;
-  int            priority        ;
-
-  slCallBack     callback ;
-  int            magic ;
-
-  void  low_read ( int nframes, Uchar *dest ) ;
-
-public:
-
-  slSamplePlayer ( slSample *s, slReplayMode  rp_mode = SL_SAMPLE_ONE_SHOT, 
-		   int pri = 0, slPreemptMode pr_mode = SL_SAMPLE_DELAY,
-                   int _magic = 0, slCallBack cb = NULL )
-  {
-    magic           = _magic ;
-    sample          = s ;
-    callback        = cb ;
-
-    for ( int i = 0 ; i < SL_MAX_ENVELOPES ; i++ )
-    {
-      env [ i ] = NULL ;
-      env_type [ i ] = SL_NULL_ENVELOPE ;
-    }
-
-    if ( sample ) sample -> ref () ;
-
-    reset () ;
-
-    replay_mode     = rp_mode ;
-    preempt_mode    = pr_mode ;
-    priority        = pri ;
-  }
-
-  ~slSamplePlayer () ;
-
-  slPreemptMode getPreemptMode () { return preempt_mode ; }
-
-  int getPriority ()
-  {
-    return ( isRunning() &&
-             preempt_mode == SL_SAMPLE_CONTINUE ) ? (SL_MAX_PRIORITY+1) :
-                                                               priority ;
-  }
-
-  int preempt ( int delay ) ;
-  
-  void addEnvelope ( int i, slEnvelope *_env, slEnvelopeType _type ) ;
-
-  void pause ()
-  {
-    if ( status != SL_SAMPLE_DONE )
-      status = SL_SAMPLE_PAUSED ;
-  }
-
-  void resume ()
-  {
-    if ( status == SL_SAMPLE_PAUSED )
-      status = SL_SAMPLE_RUNNING ;
-  }
-
-  void reset ()
-  {
-    status = SL_SAMPLE_WAITING ;
-    lengthRemaining = sample->getLength () ;
-    bufferPos       = sample->getBuffer () ;
-  } 
-
-  void start ()
-  {
-    status = SL_SAMPLE_RUNNING ;
-    lengthRemaining = sample->getLength () ;
-    bufferPos       = sample->getBuffer () ;
-  } 
-
-  void stop ()
-  {
-    status = SL_SAMPLE_DONE ;
-    lengthRemaining = 0    ;
-    bufferPos       = NULL ;
-  } 
-
-  int       getMagic  () { return magic  ; }
-  slSample *getSample () { return sample ; }
-
-  int isWaiting () { return status == SL_SAMPLE_WAITING ; } 
-  int isPaused  () { return status == SL_SAMPLE_PAUSED  ; } 
-  int isRunning () { return status == SL_SAMPLE_RUNNING ; } 
-  int isDone    () { return status == SL_SAMPLE_DONE    ; }
-
-  void skip ( int nframes ) ;
-  void read ( int nframes, Uchar *dest, int next_env = 0 ) ;
-} ;
-
-
-class slScheduler : public slDSP
-{
-  slPendingCallBack pending_callback [ SL_MAX_CALLBACKS ] ;
-  int num_pending_callbacks ;
-
-  float safety_margin ;
-
-  int mixer_buffer_size ;
-
-  Uchar *mixer_buffer  ;
-  Uchar *spare_buffer0 ;
-  Uchar *spare_buffer1 ;
-  Uchar *spare_buffer2 ;
-  
-  Uchar *mixer ;
-  int amount_left ;
-
-  slSamplePlayer *samplePlayer [ SL_MAX_SAMPLES ] ;
-
-  void init () ;
-
-  void mixBuffer ( slSamplePlayer *a,
-                   slSamplePlayer *b ) ;
-
-  void mixBuffer ( slSamplePlayer *a,
-                   slSamplePlayer *b,
-                   slSamplePlayer *c ) ;
-
-  Uchar mix ( Uchar a, Uchar b )
-  {
-    register int r = a + b - 0x80 ;
-    return ( r > 255 ) ? 255 :
-           ( r <  0  ) ?  0  : r ;
-  }
-
-  Uchar mix ( Uchar a, Uchar b, Uchar c )
-  {
-    register int r = a + b + c - 0x80 - 0x80 ;
-    return ( r > 255 ) ? 255 :
-           ( r <  0  ) ?  0  : r ;
-  }
-
-  void realUpdate ( int dump_first = SL_FALSE ) ;
-
-  void initBuffers () ;
-
-  int now ;
-
-  static slScheduler *current ;
-
-public:
-
-  slScheduler ( int _rate = SL_DEFAULT_SAMPLING_RATE ) : slDSP ( _rate, SL_FALSE, 8 ) { init () ; }
-  slScheduler ( char *device,
-                int _rate = SL_DEFAULT_SAMPLING_RATE ) : slDSP ( device, _rate, SL_FALSE, 8 ) { init () ; }
- ~slScheduler () ;
-
-  static slScheduler *getCurrent () { return current ; }
-
-  int   getTimeNow     () { return now ; }
-  float getElapsedTime ( int then ) { return (float)(now-then)/(float)getRate() ; }
-
-  void flushCallBacks () ;
-  void addCallBack    ( slCallBack c, slSample *s, slEvent e, int m ) ;
-
-  void update     () { realUpdate ( SL_FALSE ) ; }
-  void dumpUpdate () { realUpdate ( SL_TRUE  ) ; }
-
-  void addSampleEnvelope ( slSample *s = NULL, int magic = 0,
-                           int slot = 1, slEnvelope *e = NULL, 
-                           slEnvelopeType t =  SL_VOLUME_ENVELOPE )
-  {
-    for ( int i = 0 ; i < SL_MAX_SAMPLES ; i++ )
-      if ( samplePlayer [ i ] != NULL &&
-           ( s  == NULL || samplePlayer [ i ] -> getSample () ==   s   ) &&
-           ( magic == 0 || samplePlayer [ i ] -> getMagic  () == magic ) )
-        samplePlayer [ i ] -> addEnvelope ( slot, e, t ) ;
-  }
- 
-  void resumeSample ( slSample *s = NULL, int magic = 0 )
-  {
-    for ( int i = 0 ; i < SL_MAX_SAMPLES ; i++ )
-      if ( samplePlayer [ i ] != NULL &&
-           ( s  == NULL || samplePlayer [ i ] -> getSample () ==   s   ) &&
-           ( magic == 0 || samplePlayer [ i ] -> getMagic  () == magic ) )
-        samplePlayer [ i ] -> resume () ;
-  }
- 
-  void pauseSample ( slSample *s = NULL, int magic = 0 )
-  {
-    for ( int i = 0 ; i < SL_MAX_SAMPLES ; i++ )
-      if ( samplePlayer [ i ] != NULL &&
-           ( s  == NULL || samplePlayer [ i ] -> getSample () ==   s   ) &&
-           ( magic == 0 || samplePlayer [ i ] -> getMagic  () == magic ) )
-        samplePlayer [ i ] -> pause () ;
-  }
- 
-  void stopSample ( slSample *s = NULL, int magic = 0 )
-  {
-    for ( int i = 0 ; i < SL_MAX_SAMPLES ; i++ )
-      if ( samplePlayer [ i ] != NULL &&
-           ( s  == NULL || samplePlayer [ i ] -> getSample () ==   s   ) &&
-           ( magic == 0 || samplePlayer [ i ] -> getMagic  () == magic ) )
-        samplePlayer [ i ] -> stop () ;
-  }
- 
-  int loopSample ( slSample *s, int pri = 0, slPreemptMode mode = SL_SAMPLE_MUTE, int magic = 0, slCallBack cb = NULL )
-  {
-    for ( int i = 0 ; i < SL_MAX_SAMPLES ; i++ )
-      if ( samplePlayer [ i ] == NULL )
-      {
-        samplePlayer [ i ] = new slSamplePlayer ( s, SL_SAMPLE_LOOP, pri, mode, magic, cb ) ;
-        return i ;
-      }
-
-    return -1 ;
-  }
-
-  int playSample ( slSample *s, int pri = 1, slPreemptMode mode = SL_SAMPLE_ABORT, int magic = 0, slCallBack cb = NULL )
-  {
-    for ( int i = 0 ; i < SL_MAX_SAMPLES ; i++ )
-      if ( samplePlayer [ i ] == NULL )
-      {
-        samplePlayer [ i ] = new slSamplePlayer ( s, SL_SAMPLE_ONE_SHOT, pri, mode, magic, cb ) ;
-        return SL_TRUE ;
-      }
-
-    return SL_FALSE ;
-  }
-
-  void setSafetyMargin ( float seconds ) { safety_margin = seconds ; }
-} ;
-
-#endif
-
diff --git a/Lib/src/slDSP.cxx b/Lib/src/slDSP.cxx
deleted file mode 100644
index a8a96d4da..000000000
--- a/Lib/src/slDSP.cxx
+++ /dev/null
@@ -1,669 +0,0 @@
-
-#include "sl.h"
-
-static int init_bytes ;
-
-#ifdef SL_USING_OSS_AUDIO
-
-/* ------------------------------------------------------------ */
-/* OSSAUDIO - Linux, FreeBSD, etc                               */
-/* ------------------------------------------------------------ */
-
-void slDSP::open ( char *device, int _rate, int _stereo, int _bps )
-{
-  fd = ::open ( device, O_WRONLY ) ;
-
-  if ( fd < 0 )
-  {
-    perror ( "slDSP: open" ) ;
-    error = SL_TRUE ;
-
-    stereo     = SL_FALSE ;
-    bps        =    1     ;
-    rate       =  8000    ;
-    init_bytes =    0     ;
-  }
-  else
-  {
-    error = SL_FALSE ;
-
-    /* Set up a driver fragment size of 1024 (ie 2^10) */
-
-    ioctl ( SNDCTL_DSP_SETFRAGMENT, 0x7FFF000A ) ;
-
-    stereo = ioctl ( SOUND_PCM_WRITE_CHANNELS, _stereo ? 2 : 1 ) >= 2 ; 
-    bps    = ioctl ( SOUND_PCM_WRITE_BITS, _bps ) ; 
-    rate   = ioctl ( SOUND_PCM_WRITE_RATE, _rate ) ; 
-
-    getBufferInfo () ;
-    init_bytes = buff_info.bytes ;
-  }
-}
-
-
-void slDSP::close ()
-{
-  if ( fd >= 0 )
-    ::close ( fd ) ;
-}
-
-
-int slDSP::getDriverBufferSize ()
-{
-  if ( error )
-    return 0 ;
-
-  getBufferInfo () ;
-  return buff_info.fragsize ;
-}
-
-void slDSP::getBufferInfo ()
-{
-  if ( error )
-    return ;
-
-  if ( ::ioctl ( fd, SNDCTL_DSP_GETOSPACE, & buff_info ) < 0 )
-  {
-    perror ( "slDSP: getBufferInfo" ) ;
-    error = SL_TRUE ;
-    return ;
-  }
-}
-
-
-void slDSP::write ( void *buffer, size_t length )
-{
-  if ( error || length <= 0 )
-    return ;
-
-  int nwritten = ::write ( fd, (const char *) buffer, length ) ;
-
-  if ( nwritten < 0 )
-    perror ( "slDSP: write" ) ;
-  else
-  if ( nwritten != length )
-    perror ( "slDSP: short write" ) ;
-}
-
-
-float slDSP::secondsRemaining ()
-{
-  if ( error )
-    return 0.0f ;
-
-  getBufferInfo () ;
-
-  int samples_left = buff_info.fragments * buff_info.fragsize ;
-
-  if (   stereo  ) samples_left /= 2 ;
-  if ( bps == 16 ) samples_left /= 2 ;
-  return   (float) samples_left / (float) rate ;
-}
-
-
-float slDSP::secondsUsed ()
-{
-  if ( error )
-    return 0.0f ;
-
-  getBufferInfo () ;
-
-  int samples_used = init_bytes - buff_info.bytes ;
-
-  if (  stereo   ) samples_used /= 2 ;
-  if ( bps == 16 ) samples_used /= 2 ;
-  return   (float) samples_used / (float) rate ;
-}
-
-
-void slDSP::sync ()
-{ 
-   if ( !error) ::ioctl ( fd, SOUND_PCM_SYNC , 0 ) ; 
-}
-
-void slDSP::stop ()
-{ 
-   if ( !error) ::ioctl ( fd, SOUND_PCM_RESET, 0 ) ; 
-}
-
-#endif
-
-#ifdef WIN32
-
-/* ------------------------------------------------------------ */
-/* win32                                                        */
-/* ------------------------------------------------------------ */
-
-static	void	wperror(MMRESULT num)
-{
-   char	buffer[0xff];  // yes, this is hardcoded :-)
-
-   waveOutGetErrorText( num, buffer, sizeof(buffer)-1);
-
-   fprintf( stderr, "SlDSP: %s\n", buffer );
-   fflush ( stderr );
-}
-
-
-
-void CALLBACK waveOutProc( HWAVEOUT hwo, UINT uMsg,	
-      DWORD dwInstance, DWORD dwParam1, DWORD dwParam2 )
-{   
-   switch( uMsg )
-   {
-   case    WOM_CLOSE:
-      break;
-
-   case    WOM_OPEN:
-      break;
-
-   case    WOM_DONE:
-      waveOutUnprepareHeader( (HWAVEOUT)dwParam1, 
-         (LPWAVEHDR)dwParam2, sizeof( WAVEHDR ));
-      break;
-   }
-}
-
-
-void slDSP::open ( char *device, int _rate, int _stereo, int _bps )
-{
-   MMRESULT	result;
-
-   hWaveOut   	= NULL;
-   curr_header	= 0;
-   counter     = 0;
-
-   Format.wFormatTag       = WAVE_FORMAT_PCM;		
-   Format.nChannels        = _stereo ? 2 : 1;
-   Format.nSamplesPerSec   = _rate;
-   Format.wBitsPerSample   = _bps;
-   Format.nBlockAlign      = 1;
-   Format.nAvgBytesPerSec  = _rate * Format.nChannels;
-   Format.cbSize           = 0;
-
-   result = waveOutOpen( & hWaveOut, WAVE_MAPPER, & Format, NULL, 
-      0L, WAVE_FORMAT_QUERY );
-
-   if ( result != MMSYSERR_NOERROR )
-   {
-      wperror( result);
-
-      error      = SL_TRUE  ;
-      stereo     = SL_FALSE ;
-      bps        = _bps     ;
-      rate       = _rate    ;
-      init_bytes =    0     ;
-      
-      return;
-   }
-
-   // Now the hwaveouthandle "should" be valid 
-
-   if ( ( result = waveOutOpen( & hWaveOut, WAVE_MAPPER, 
-         (WAVEFORMATEX *)& Format, (DWORD)waveOutProc, 
-         0L, CALLBACK_FUNCTION )) != MMSYSERR_NOERROR )
-   {
-      wperror( result);
-
-      error      = SL_TRUE ;
-      stereo     = SL_FALSE ;
-      bps        = _bps     ;
-      rate       = _rate    ;
-      init_bytes =    0     ;
-      return;
-   }
-   else
-   {
-      error  = SL_FALSE ;
-      stereo = _stereo;
-      bps    = _bps;
-      rate   = _rate;
-
-      /* hmm ?! */ 
-
-      init_bytes = 1024*8;
-   }
-}
-
-
-void slDSP::close ()
-{
-   if ( hWaveOut != NULL )
-   {
-      waveOutClose( hWaveOut );
-      hWaveOut = NULL;
-   }
-}
-
-int slDSP::getDriverBufferSize ()
-{
-   if ( error )
-      return 0 ;
-
-   /* hmm ?! */
-
-   return    1024*8;
-}
-
-void slDSP::getBufferInfo ()
-{
-    return ;
-}
-
-
-void slDSP::write ( void *buffer, size_t length )
-{
-   MMRESULT	result;
-
-   if ( error || length <= 0 )
-      return ;
-
-   wavehdr[curr_header].lpData          = (LPSTR) buffer;
-   wavehdr[curr_header].dwBufferLength  = (long) length;
-   wavehdr[curr_header].dwBytesRecorded = 0L;
-   wavehdr[curr_header].dwUser          = NULL;
-   wavehdr[curr_header].dwFlags         = 0;
-   wavehdr[curr_header].dwLoops         = 0;
-   wavehdr[curr_header].lpNext          = NULL;
-   wavehdr[curr_header].reserved        = 0;
-
-
-   result = waveOutPrepareHeader( hWaveOut, & wavehdr[curr_header], 
-      sizeof(WAVEHDR));
-
-   if ( result != MMSYSERR_NOERROR ) 
-   {
-      wperror ( result );
-      error = SL_TRUE;
-   }
-
-   result = waveOutWrite(hWaveOut, & wavehdr[curr_header], 
-      sizeof(WAVEHDR));
-   if ( result != MMSYSERR_NOERROR )
-   {
-      wperror ( result );
-      error = SL_TRUE;
-   }
-   
-   counter ++; 
-   
-   curr_header = ( curr_header + 1 ) % 3;
-}
-
-
-float slDSP::secondsRemaining ()
-{
-   if ( error )
-      return 0.0f ;
-   
-   return 0.0f ;
-}
-
-
-float slDSP::secondsUsed ()
-{
-   int      samples_used;
-   MMRESULT	result;
-   float    samp_time;
-
-   if ( error )
-      return 0.0f ;
-
-   mmt.wType = TIME_BYTES;
-
-   result = waveOutGetPosition( hWaveOut, &mmt, sizeof( mmt ));
-
-   if ( mmt.u.cb == 0 || counter == 0)
-      return    (float)0.0;
-
-   samples_used = ( init_bytes * counter ) - mmt.u.cb;
-
-   if (  stereo   ) samples_used /= 2 ;
-   if ( bps == 16 ) samples_used /= 2 ;
-
-   samp_time  = (float) samples_used / (float) rate ;
-
-   //printf("%0.2f position=%ld total written=%ld\n", 
-   // samp_time, mmt.u.cb, init_bytes * counter );
-   
-   return   samp_time;
-}
-
-
-void slDSP::sync ()
-{
-}
-
-void slDSP::stop ()
-{
-   if ( error )
-     return ;
-
-   waveOutReset( hWaveOut );
-}
-
-/* ------------------------------------------------------------ */
-/* OpenBSD 2.3 this should be very close to SUN Audio           */
-/* ------------------------------------------------------------ */
-
-#elif defined(__OpenBSD__)
-void slDSP::open ( char *device, int _rate, int _stereo, int _bps )
-{
-
-  counter = 0;
-  
-  fd = ::open ( device, O_RDWR ) ;
-    
-  if ( fd < 0 )
-  {
-    perror ( "slDSP: open" ) ;
-    error = SL_TRUE ;
-  }
-  else
-  {    
-  
-    if( ::ioctl( fd, AUDIO_GETINFO, &ainfo) == -1)
-    {
-      perror("slDSP: open - getinfo");
-      stereo     = SL_FALSE ;
-      bps        =    8     ;
-      rate       =  8000    ;
-      init_bytes =    0     ;
-      
-      return;
-    }
-      
-    ainfo.play.sample_rate  = _rate;
-    ainfo.play.precision    = _bps;    
-    ainfo.play.channels     = _stereo ? 2 : 1;
-    
-    ainfo.play.encoding     = AUDIO_ENCODING_ULINEAR;
-
-    if( :: ioctl(fd, AUDIO_SETINFO, &ainfo) == -1)
-    {
-      perror("slDSP: open - setinfo");
-      stereo     = SL_FALSE ;
-      bps        =    8     ;
-      rate       =  8000    ;
-      init_bytes =    0     ;
-      return;
-    }
-
-    rate    = _rate;
-    stereo  = _stereo;
-    bps     = _bps;
-
-    error = SL_FALSE ;
-
-    getBufferInfo ();
-    
-    // I could not change the size, 
-    // so let's try this ...
-    
-    init_bytes = 1024 * 8;
-  }
-}
-
-
-void slDSP::close ()
-{
-  if ( fd >= 0 )
-    ::close ( fd ) ;
-}
-
-
-int slDSP::getDriverBufferSize ()
-{
-  if ( error )
-    return 0 ;
-
-  getBufferInfo () ;
-  
-  // HW buffer is 0xffff on my box
-  //return ainfo.play.buffer_size;
-  
-  return  1024 * 8;
-}
-
-void slDSP::getBufferInfo ()
-{
-  if ( error )
-    return ;
-
-  if( ::ioctl( fd, AUDIO_GETINFO, &ainfo) < 0)
-  {
-    perror ( "slDSP: getBufferInfo" ) ;
-    error = SL_TRUE ;
-    return ;
-  }
-    
-  if( ::ioctl( fd, AUDIO_GETOOFFS, &audio_offset ) < 0)
-  {
-    perror ( "slDSP: getBufferInfo" ) ;
-    error = SL_TRUE ;
-    return ;
-  }
-}
-
-
-void slDSP::write ( void *buffer, size_t length )
-{
-  if ( error || length <= 0 )
-    return ;
-  
-  int nwritten = ::write ( fd, (const char *) buffer, length ) ;
-
-  if ( nwritten < 0 )
-    perror ( "slDSP: write" ) ;
-  else if ( nwritten != length )
-      perror ( "slDSP: short write" ) ;
-      
-  counter ++; /* hmmm */
-}
-
-
-float slDSP::secondsRemaining ()
-{
-    return 0.0f ;
-}
-
-
-float slDSP::secondsUsed ()
-{
-  /*
-   * original formula from Steve:
-   * -----------------------------
-   *
-   * int samples_used = init_bytes - buff_info.bytes ;
-   *                    |            |
-   *                    |            +--- current available
-   *                    |                 space in bytes !
-   *                    +---------------- available space
-   *                                      when empty;
-   * 
-   * sample_used contains the number of bytes which are
-   * "used" or in the DSP "pipeline".
-   */
-
-
-  int samples_used;
-  
-  if ( error )
-    return 0.0f ;
-
-  getBufferInfo () ;
-
-  //This is wrong: this is the hw queue in the kernel !
-  //samples_used   = ainfo.play.buffer_size - audio_offset.offset ;
-
-  // This is: all data written minus where we are now in the queue
-  
-  if ( counter == 0 )
-      return 0.0;
-
-  samples_used = ( counter * init_bytes ) - audio_offset.samples;
-  
-  if (  stereo   ) samples_used /= 2 ;
-  if ( bps == 16 ) samples_used /= 2 ;
-
-  return   (float) samples_used / (float) rate ;
-}
-
-
-void slDSP::sync ()
-{ 
-   if ( !error) ::ioctl ( fd, AUDIO_FLUSH , 0 ) ; 
-}
-
-void slDSP::stop ()
-{ 
-   // nothing found yet 
-}
-
-/* ------------------------------------------------------------ */
-/* SGI IRIX audio                                               */
-/* ------------------------------------------------------------ */
-
-#elif defined(sgi)
-
-void slDSP::open ( char *device, int _rate, int _stereo, int _bps )
-{
-  if ( _bps != 8 )
-  {
-    perror ( "slDSP: supports only 8bit audio for sgi" ) ;
-    error = SL_TRUE;
-    return;
-  }
-
-  init_bytes = 1024 * 8;
-
-  config  = ALnewconfig();
-  
-  ALsetchannels (  config, _stereo ? AL_STEREO : AL_MONO );
-  ALsetwidth    (  config, _bps == 8 ? AL_SAMPLE_8 : AL_SAMPLE_16 );
-  ALsetqueuesize(  config, init_bytes );
-
-  port = ALopenport( device, "w", config );
-    
-  if ( port == NULL )
-  {
-    perror ( "slDSP: open" ) ;
-    error = SL_TRUE ;
-  }
-  else
-  {    
-    long params[2] = {AL_OUTPUT_RATE, 0 };
-
-    params[1] = _rate;
-
-    if ( ALsetparams(AL_DEFAULT_DEVICE, params, 2) != 0 )
-	{
-       perror ( "slDSP: open - ALsetparams" ) ;
-       error = SL_TRUE ;
-       return;
-	}
-  
-    rate    = _rate;
-    stereo  = _stereo;
-    bps     = _bps;
-
-    error = SL_FALSE ;
-
-  }
-}
-
-
-void slDSP::close ()
-{
-  if ( port != NULL )
-  {
-     ALcloseport ( port   );
-     ALfreeconfig( config );
-     port = NULL;
-  }
-}
-
-
-int slDSP::getDriverBufferSize ()
-{
-  if ( error )
-    return 0 ;
-
-  return  ALgetqueuesize( config );
-}
-
-void slDSP::getBufferInfo ()
-{
-  if ( error )
-    return ;
-}
-
-
-void slDSP::write ( void *buffer, size_t length )
-{
-  char *buf = (char *)buffer;
-  int  i;
-
-  if ( error || length <= 0 )
-    return ;
-
-  // Steve: is this a problem ??
-
-  for ( i = 0; i < length; i ++ )
-    buf[i] = buf[i] >> 1;
-
-  ALwritesamps(port, (void *)buf, length );
-}
-
-
-float slDSP::secondsRemaining ()
-{
-  int   samples_remain;
-
-  if ( error )
-    return 0.0f ;
-
-  samples_remain = ALgetfillable(port);
-
-  if (  stereo   ) samples_remain /= 2 ;
-  if ( bps == 16 ) samples_remain /= 2 ;
-
-  return   (float) samples_remain / (float) rate ;
-}
-
-
-float slDSP::secondsUsed ()
-{
-  int   samples_used;
-  
-  if ( error )
-    return 0.0f ;
-
-  samples_used = ALgetfilled(port);
-
-  if (  stereo   ) samples_used /= 2 ;
-  if ( bps == 16 ) samples_used /= 2 ;
-
-  return   (float) samples_used / (float) rate ;
-}
-
-
-void slDSP::sync ()
-{ 
-   if ( error )
-     return ;
-
-  /* found this in the header file - but no description
-   * or example for the long parameter.
-   */
-
-  // ALflush(ALport, long);
-}
-
-void slDSP::stop ()
-{ 
-}
-
-
-#endif
-
diff --git a/Lib/src/slEnvelope.cxx b/Lib/src/slEnvelope.cxx
deleted file mode 100644
index 13e726c4c..000000000
--- a/Lib/src/slEnvelope.cxx
+++ /dev/null
@@ -1,170 +0,0 @@
-
-#include "sl.h"
-
-float slEnvelope::getValue ( float _time )
-{
-  float delta ;
-  int   step = getStepDelta ( &_time, &delta ) ;
-
-  return delta * (_time - time[step]) + value[step] ;
-}
-
-
-
-int slEnvelope::getStepDelta ( float *_time, float *delta )
-{
-  float tt ;
-
-  if ( replay_mode == SL_SAMPLE_LOOP )
-  {
-    tt = floor ( *_time / time [ nsteps-1 ] ) ; 
-    *_time -= tt * time [ nsteps-1 ] ;
-  }
-
-  tt = *_time ;
-
-  if ( tt <= time[    0   ] ) { *delta = 0.0f ; return 0 ; }
-  if ( tt >= time[nsteps-1] ) { *delta = 0.0f ; return nsteps-1 ; }
-
-  for ( int i = 1 ; i <= nsteps-1 ; i++ )
-    if ( tt <= time[i] )
-    {
-      float t1 = time[i-1] ; float v1 = value[i-1] ;
-      float t2 = time[ i ] ; float v2 = value[ i ] ;
-
-      if ( t1 == t2 )
-      {
-        *delta = 0.0f ;
-	return i ;
-      }
-
-      *delta = (v2-v1) / (t2-t1) ;
-      return i-1 ;
-    }
-
-  *delta = 0.0f ;
-  return nsteps - 1 ;
-}
-
-
-void slEnvelope::applyToPitch  ( Uchar *dst, slSamplePlayer *src,
-                                 int nframes, int start, int next_env )
-{
-  float  delta ;
-  float  _time = slScheduler::getCurrent() -> getElapsedTime ( start ) ;
-  int     step = getStepDelta ( &_time, &delta ) ;
-  float _value = delta * (_time - time[step]) + value[step] ;
-
-  delta /= (float) slScheduler::getCurrent() -> getRate () ;
-
-  unsigned char tmp [ 512 ] ;
-  float  pos = 0 ;
-  float npos = 0 ;
-  unsigned char last = 0x80 ;
-
-  while ( nframes-- )
-  {
-    npos += _value ;
-    _value += delta ;
-
-    int offset = (int) ( npos - pos ) ;
-
-    if ( offset > 512 )
-      offset = 512 ;
-
-    if ( offset < 1 )
-      *(dst++) = last ;
-    else
-    {
-      pos += offset ;
-
-      src -> read ( offset, tmp, next_env ) ;
-
-      *(dst++) = last = tmp [ offset-1 ] ; 
-    }
-  }
-}
-
-
-void slEnvelope::applyToInvPitch  ( Uchar *dst, slSamplePlayer *src,
-                                    int nframes, int start, int next_env )
-{
-  float  delta ;
-  float  _time = slScheduler::getCurrent() -> getElapsedTime ( start ) ;
-  int     step = getStepDelta ( &_time, &delta ) ;
-  float _value = delta * (_time - time[step]) + value[step] ;
-
-  delta /= (float) slScheduler::getCurrent() -> getRate () ;
-
-  unsigned char tmp [ 512 ] ;
-  float  pos = 0 ;
-  float npos = 0 ;
-  unsigned char last = 0x80 ;
-
-  while ( nframes-- )
-  {
-    npos += 1.0 / _value ;
-    _value += delta ;
-
-    int offset = (int) ( npos - pos ) ;
-
-    if ( offset > 512 )
-      offset = 512 ;
-
-    if ( offset < 1 )
-      *(dst++) = last ;
-    else
-    {
-      pos += offset ;
-
-      src -> read ( offset, tmp, next_env ) ;
-
-      *(dst++) = last = tmp [ offset-1 ] ; 
-    }
-  }
-}
-
-void slEnvelope::applyToVolume ( Uchar *dst, Uchar *src,
-                                 int nframes, int start )
-{
-  float  delta ;
-  float  _time = slScheduler::getCurrent() -> getElapsedTime ( start ) ;
-  int     step = getStepDelta ( &_time, &delta ) ;
-  float _value = delta * (_time - time[step]) + value[step] ;
-
-  delta /= (float) slScheduler::getCurrent() -> getRate () ;
-
-  while ( nframes-- )
-  {
-    register int res = (int)( (float)((int)*(src++)-0x80) * _value ) + 0x80 ;
-
-    _value += delta ;
-
-    *(dst++) = ( res > 255 ) ? 255 : ( res < 0 ) ? 0 : res ;
-  }
-}
-
-void slEnvelope::applyToInvVolume ( Uchar *dst, Uchar *src,
-                                    int nframes, int start )
-{
-  float  delta ;
-  float  _time = slScheduler::getCurrent() -> getElapsedTime ( start ) ;
-  int     step = getStepDelta ( &_time, &delta ) ;
-  float _value = delta * (_time - time[step]) + value[step] ;
-
-  delta /= (float) slScheduler::getCurrent() -> getRate () ;
-
-  delta = - delta ;
-  _value = 1.0 - _value ;
-
-  while ( nframes-- )
-  {
-    register int res = (int)( (float)((int)*(src++)-0x80) * _value ) + 0x80 ;
-
-    _value += delta ;
-
-    *(dst++) = ( res > 255 ) ? 255 : ( res < 0 ) ? 0 : res ;
-  }
-}
-
-
diff --git a/Lib/src/slPortability.h b/Lib/src/slPortability.h
deleted file mode 100644
index 08d780c14..000000000
--- a/Lib/src/slPortability.h
+++ /dev/null
@@ -1,71 +0,0 @@
-
-#ifndef __SLPORTABILITY_H__
-#define __SLPORTABILITY_H__ 1
-
-/* ------------------------------------------------------------- */
-/* OS specific includes and defines ...                          */
-/* ------------------------------------------------------------- */
-
-#ifdef HAVE_CONFIG_H
-#  include 
-#endif
-#undef VERSION
-
-#include 
-#include 
-
-#ifndef  WIN32
-#include 
-#include 
-#else
-#include 
-#if defined( __CYGWIN__ ) || defined( __CYGWIN32__ )
-#  define NEAR /* */
-#  define FAR  /* */
-#endif
-#include 
-#endif
-
-#include 
-#include 
-#include 
-#include 
-
-#if defined(__linux__) || defined(__FreeBSD__)
-#define SL_USING_OSS_AUDIO 1
-#endif
-
-#ifdef SL_USING_OSS_AUDIO
-#if defined(__linux__)
-#include 
-#elif defined(__FreeBSD__)
-#include 
-#else
-/*
-  Tom thinks this file may be  under some
-  unixen - but that isn't where the OSS manuals say it
-  should be.
-
-  If you ever find out the truth, please email me:
-     Steve Baker 
-*/
-#include 
-#endif
-#endif
-
-#ifdef	__OpenBSD__
-#include 
-#endif
-
-#ifdef WIN32
-#define strcasecmp stricmp   /* Yes, Steve really does *HATE* Windoze */
-#endif
-
-/* Tom */
-
-#ifdef	sgi
-#include 
-#endif
-
-#endif
-
diff --git a/Lib/src/slSample.cxx b/Lib/src/slSample.cxx
deleted file mode 100644
index 386a3ce29..000000000
--- a/Lib/src/slSample.cxx
+++ /dev/null
@@ -1,505 +0,0 @@
-
-
-#include "sl.h"
-#include 
-
-void slSample::autoMatch ( slDSP *dsp )
-{
-  if ( dsp == NULL ) return ;
-
-  changeRate   ( dsp->getRate   () ) ;
-  changeBps    ( dsp->getBps    () ) ;
-  changeStereo ( dsp->getStereo () ) ;
-}
-
-void slSample::adjustVolume ( float vol )
-{
-  for ( int i = 0 ; i < length ; i++ )
-  {
-    int s = (int)(((float) buffer[i] - (float) 0x80) * vol) + 0x80 ;
-
-    buffer [ i ] = ( s > 255 ) ? 255 :
-                     ( s < 0 ) ? 0 : s ;
-  }
-}
-
-
-void slSample::changeRate   ( int r )
-{
-  if ( r == rate ) return ;
-
-  int    length1 = length / (getBps ()/8) ;
-  int    length2 = (int) ( (float) length1 * ( (float) r / (float) rate ) ) ;
-  Uchar *buffer2 = new Uchar [ length2 ] ;
-
-  float step = (float) length1 / (float) length2 ;
-
-  for ( int i = 0 ; i < length2 / (getBps()/8); i++ )
-  {
-    float pos = (float) i * step ;
-
-    int p1 = (int) floor ( pos ) ;
-    int p2 = (int) ceil  ( pos ) ;
-
-    if ( stereo )
-    {
-      if ( ( p1 & 1 ) != ( i & 1 ) ) { pos++ ; p1++ ; p2++ ; }
-      p2++ ;
-    }
-
-    float ratio = pos - (float) p1 ;
-
-    float b1 = (getBps()==8) ?
-        (float)           buffer [(p1<0)?0:(p1>=length1)?length1-1:p1] :
-        (float) ((Ushort*)buffer)[(p1<0)?0:(p1>=length1)?length1-1:p1] ;
-    float b2 = (getBps()==8) ?
-        (float)           buffer [(p2<0)?0:(p2>=length1)?length1-1:p2] :
-        (float) ((Ushort*)buffer)[(p2<0)?0:(p2>=length1)?length1-1:p2] ;
-
-    float res = b1 * (1.0-ratio) + b2 * ratio ;
-
-    if ( getBps () == 8 )
-      buffer2 [ i ] = (Uchar) ( (res < 0) ? 0 : (res > 255) ? 255 : res ) ;
-    else
-      ((Ushort *) buffer2 ) [ i ] = 
-                (Ushort) ( (res < 0) ? 0 : (res > 65535) ? 65535 : res ) ;
-  }
-
-  rate   = r ;
-  length = length2 ;
-  delete buffer ;
-  buffer = buffer2 ;
-}
-
-
-void slSample::changeToUnsigned ()
-{
-  if ( getBps() == 16 )
-  {
-    int length2 = length / 2 ;
-    Ushort *buffer2 = (Ushort *) buffer ;
-
-    for ( int i = 0 ; i < length2 ; i++ )
-      buffer2 [ i ] = buffer2 [ i ] + 32768 ;
-  }
-  else
-  {
-    for ( int i = 0 ; i < length ; i++ )
-      buffer [ i ] = (buffer [ i ]>0x80) ? (buffer[i]-0x80) :
-                                           (0xFF-buffer[i]) ;
-  }
-}
-
-
-
-void slSample::changeBps    ( int b )
-{
-  if ( b == getBps () ) return ;
-
-  if ( b == 8 && getBps() == 16 )
-  {
-    length /= 2 ;
-    Uchar *buffer2 = new Uchar [ length ] ;
-
-    for ( int i = 0 ; i < length ; i++ )
-      buffer2 [ i ] = ((Ushort *)buffer) [ i ] >> 8 ;
-
-    delete buffer ;
-    buffer = buffer2 ;
-    setBps ( b ) ;
-  }
-  else
-  if ( b == 16 && getBps() == 8 )
-  {
-    Ushort *buffer2 = new Ushort [ length ] ;
-
-    for ( int i = 0 ; i < length ; i++ )
-      buffer2 [ i ] = buffer [ i ] << 8 ;
-
-    delete buffer ;
-    buffer = (Uchar *) buffer2 ;
-    length *= 2 ;
-    setBps ( b ) ;
-  }
-}
-
-void slSample::changeStereo ( int s )
-{
-  if ( s == getStereo () )
-    return ;
-
-  if ( s && ! getStereo () )
-  {
-    if ( getBps () == 8 )
-    {
-       Uchar *buffer2 = new Uchar [ length * 2 ] ;
-
-       for ( int i = 0 ; i < length ; i++ )
-         buffer2 [ i*2 ] = buffer2 [ i*2+1 ] = buffer [ i ] ;
-
-       delete buffer ;
-       buffer = buffer2 ;
-       length *= 2 ;
-       setStereo ( SL_TRUE ) ;
-    }
-    else
-    {
-       Ushort *buffer2 = new Ushort [ length ] ;
-
-       for ( int i = 0 ; i < length / 2 ; i++ )
-         buffer2 [ i*2 ] = buffer2 [ i*2+1 ] = ((Ushort *) buffer) [ i ] ;
-
-       delete buffer ;
-       buffer = (Uchar *)buffer2 ;
-       length *= 2 ;
-       setStereo ( SL_TRUE ) ;
-    }
-  }
-  else
-  {
-    if ( getBps () == 8 )
-    {
-       Uchar *buffer2 = new Uchar [ length / 2 ] ;
-
-       for ( int i = 0 ; i < (length-1)/2 ; i++ )
-         buffer2 [ i ] = ((int)buffer [ i*2 ] + (int)buffer [ i*2 + 1 ] ) / 2 ;
-
-       delete buffer ;
-       buffer = buffer2 ;
-       length /= 2 ;
-       setStereo ( SL_FALSE ) ;
-    }
-    else
-    {
-       Ushort *buffer2 = new Ushort [ length / 4 ] ;
-
-       for ( int i = 0 ; i < (length-3) / 4 ; i++ )
-         buffer2 [ i ] = ((int)((Ushort *)buffer) [ i*2 ] +
-                          (int)((Ushort *)buffer) [ i*2 + 1 ] ) / 2 ;
-
-       delete buffer ;
-       buffer = (Uchar *)buffer2 ;
-       length /= 4 ;
-       setStereo ( SL_FALSE ) ;
-    }
-  }
-}
-
-
-static void swap_Ushort ( Ushort *i )
-{
-  *i = ((*i << 8) & 0xFF00) +
-       ((*i >> 8) & 0x00FF) ;
-}
-
-static void swap_int ( int *i )
-{
-  *i = ((*i << 24) & 0xFF000000) +
-       ((*i <<  8) & 0x00FF0000) +
-       ((*i >>  8) & 0x0000FF00) +
-       ((*i >> 24) & 0x000000FF) ;
-}
-
-int slSample::loadFile ( char *fname )
-{
-  if ( strcasecmp ( & fname [ strlen ( fname ) - 4 ], ".wav" ) == 0 )
-    return loadWavFile ( fname ) ;
-
-  if ( strcasecmp ( & fname [ strlen ( fname ) - 3 ], ".au" ) == 0 )
-    return loadAUFile ( fname ) ;
-
-  if ( strcasecmp ( & fname [ strlen ( fname ) - 3 ], ".ub" ) == 0 )
-    return loadRawFile ( fname ) ;
-
-  fprintf ( stderr, "slSample:loadFile: Unknown file type for '%s'.\n",
-                                    fname ) ;
-  return SL_FALSE ;
-}
-
-
-int slSample::loadWavFile ( char *fname )
-{
-  int found_header   = SL_FALSE ;
-  int needs_swabbing = SL_FALSE ;
-
-  delete buffer ;
-  buffer = NULL ;
-  length = 0 ;
-
-  FILE *fd = fopen ( fname, "rb" ) ;
-
-  if ( fd == NULL )
-  {
-    fprintf ( stderr,
-	     "slSample: loadWavFile: Cannot open '%s' for reading.\n",
-	     fname ) ;
-    return SL_FALSE ;
-  }
-
-  char magic [ 8 ] ;
-
-  if ( fread ( magic, 4, 1, fd ) == 0 ||
-       magic[0] != 'R' || magic[1] != 'I' ||
-       magic[2] != 'F' || magic[3] != 'F' )
-  {
-    fprintf ( stderr, "slWavSample: File '%s' has wrong magic number\n", fname ) ;
-    fprintf ( stderr, "            - it probably isn't in '.wav' format.\n" ) ;
-    fclose ( fd ) ;
-    return SL_FALSE ;
-  }
-
-  int leng1 ;
-
-  if ( fread ( & leng1, sizeof(int), 1, fd ) == 0 )
-  {
-    fprintf ( stderr, "slSample: File '%s' has premature EOF in header\n", fname ) ;
-    fclose ( fd ) ;
-    return SL_FALSE ;
-  }
-
-  fread ( magic, 4, 1, fd ) ;
-
-  if ( magic[0] != 'W' || magic[1] != 'A' ||
-       magic[2] != 'V' || magic[3] != 'E' )
-  {
-    fprintf ( stderr, "slSample: File '%s' has no WAVE tag.\n", fname ) ;
-    fclose ( fd ) ;
-    return SL_FALSE ;
-  }
-
-  while ( ! feof ( fd ) )
-  {
-    fread ( magic, 4, 1, fd ) ;
-
-    if ( magic[0] == 'f' && magic[1] == 'm' &&
-	 magic[2] == 't' && magic[3] == ' ' )
-    {
-      found_header = SL_TRUE ;
-
-      if ( fread ( & leng1, sizeof(int), 1, fd ) == 0 )
-      {
-	fprintf ( stderr, "slSample: File '%s' has premature EOF in header\n", fname ) ;
-	fclose ( fd ) ;
-	return SL_FALSE ;
-      }
-
-      if ( leng1 > 65536 )
-      {
-	needs_swabbing = SL_TRUE ;
-	swap_int ( & leng1 ) ;
-      }
-
-      Ushort header [ 8 ] ;
-
-      if ( leng1 != sizeof ( header ) )
-	fprintf ( stderr,
-               "slSample: File '%s' has unexpectedly long (%d byte) header\n",
-               fname, leng1 ) ;
-
-      fread ( & header, sizeof(header), 1, fd ) ;
-
-      for ( int junk = sizeof(header) ; junk < leng1 ; junk++ )
-        fgetc ( fd ) ;
-
-      if ( needs_swabbing )
-      {
-	swap_Ushort ( & header[0] ) ;
-	swap_Ushort ( & header[1] ) ;
-	swap_int    ( (int *) & header[2] ) ;
-	swap_int    ( (int *) & header[4] ) ;
-	swap_Ushort ( & header[6] ) ;
-	swap_Ushort ( & header[7] ) ;
-      }
-
-      if ( header [ 0 ] != 0x0001 )
-      {
-	fprintf ( stderr, "slSample: File '%s' is not WAVE_FORMAT_PCM!\n", fname ) ;
-	fclose ( fd ) ;
-	return SL_FALSE ;
-      }
-
-      setStereo ( header[1] > 1 ) ;
-      setRate   ( *((int *) (& header[2])) ) ;
-      setBps    ( header[7] ) ;
-    }
-    else
-    if ( magic[0] == 'd' && magic[1] == 'a' &&
-	 magic[2] == 't' && magic[3] == 'a' )
-    {
-      if ( ! found_header )
-      {
-	fprintf ( stderr, "slSample: File '%s' has no data section\n", fname ) ;
-	fclose ( fd ) ;
-	return SL_FALSE ;
-      }
-
-      if ( fread ( & length, sizeof(int), 1, fd ) == 0 )
-      {
-	fprintf ( stderr, "slSample: File '%s' has premature EOF in data\n", fname ) ;
-	fclose ( fd ) ;
-	return SL_FALSE ;
-      }
-
-      if ( needs_swabbing )
-	swap_int ( & length ) ;
-
-      buffer = new Uchar [ length ] ;
-
-      fread ( buffer, 1, length, fd ) ;
-
-      if ( getBps () == 16 )
-      {
-        Ushort *b = (Ushort*) buffer ;
-
-        for ( int i = 0 ; i < length/2 ; i++ )
-          b [ i ] = (Ushort) ( (int)((short) b [ i ]) + 32768 ) ;
-      }
-
-      fclose ( fd ) ;
-      return SL_TRUE ;
-    }
-  }
-
-  fclose ( fd ) ;
-  return SL_FALSE ;
-}
-
-int slSample::loadAUFile ( char *fname )
-{
-  delete buffer ;
-  buffer = NULL ;
-  length = 0 ;
-
-  FILE *fd = fopen ( fname, "rb" ) ;
-
-  if ( fd == NULL )
-  {
-    fprintf ( stderr,
-	     "slSample: loadAUFile: Cannot open '%s' for reading.\n",
-	     fname ) ;
-    return SL_FALSE ;
-  }
-
-  char magic [ 4 ] ;
-
-  if ( fread ( magic, 4, 1, fd ) == 0 ||
-       magic[0] != '.' || magic[1] != 's' ||
-       magic[2] != 'n' || magic[3] != 'd' )
-  {
-    fprintf ( stderr, "slSample: File '%s' has wrong magic number\n", fname ) ;
-    fprintf ( stderr, "            - it probably isn't in '.au' format.\n" ) ;
-    fclose ( fd ) ;
-    return SL_FALSE ;
-  }
-
-  int hdr_length ;
-  int dat_length ;
-  int nbytes ;
-  int irate  ;
-  int nchans ;
-
-  if ( fread ( & hdr_length, sizeof(int), 1, fd ) == 0 ||
-       fread ( & dat_length, sizeof(int), 1, fd ) == 0 ||
-       fread ( & nbytes    , sizeof(int), 1, fd ) == 0 ||
-       fread ( & irate     , sizeof(int), 1, fd ) == 0 ||
-       fread ( & nchans    , sizeof(int), 1, fd ) == 0 )
-  {
-    fprintf ( stderr, "slSample: File '%s' has premature EOF in header\n", fname ) ;
-    fclose ( fd ) ;
-    return SL_FALSE ;
-  }
-
-  if ( hdr_length > 65536 )
-  {
-    swap_int ( & hdr_length ) ;
-    swap_int ( & dat_length ) ;
-    swap_int ( & nbytes ) ;
-    swap_int ( & irate  ) ;
-    swap_int ( & nchans ) ;
-  }
-
-  bps    = nbytes * 8 ;
-  stereo = (nchans>1) ;
-  rate   = irate      ;
-
-  if ( nbytes > 2 || nbytes <= 0 || hdr_length > 512 || hdr_length < 24 ||
-       irate > 65526 || irate <= 1000 || nchans < 1 || nchans > 2 )
-  {
-    fprintf ( stderr, "slSample: File '%s' has a very strange header\n", fname ) ;
-
-    fprintf ( stderr, "  Header Length = %d\n", hdr_length ) ;
-    fprintf ( stderr, "  Data   Length = %d\n", dat_length ) ;
-    fprintf ( stderr, "  Bytes/sample  = %d\n", nbytes     ) ;
-    fprintf ( stderr, "  Sampling Rate = %dHz\n",irate     ) ;
-    fprintf ( stderr, "  Num Channels  = %d\n", nchans     ) ;
-    fprintf ( stderr, "\n" ) ;
-    fclose ( fd ) ;
-    return SL_FALSE ;
-  }
-
-  if ( hdr_length > 24 )
-  {
-    delete comment ;
-    comment = new char [ hdr_length - 24 + 1 ] ;
-
-    fread ( comment, 1, hdr_length - 24, fd ) ;
-  }
-
-  if ( dat_length > 0 )
-  {
-    buffer = new Uchar [ dat_length ] ;
-    length = fread ( buffer, 1, dat_length, fd ) ;
-
-    if ( length != dat_length )
-      fprintf ( stderr, "slAUSample: File '%s' has premature EOF in data.\n", fname ) ;
-  }
-
-  fclose ( fd ) ;
-  return SL_TRUE ;
-}
-
-
-int slSample::loadRawFile ( char *fname )
-{
-  delete buffer ;
-  buffer = NULL ;
-  length = 0 ;
-
-  FILE *fd = fopen ( fname, "rb" ) ;
-
-  if ( fd == NULL )
-  {
-    fprintf ( stderr,
-              "slSample: loadRawFile: Cannot open '%s' for reading.\n",
-             fname ) ;
-    return SL_FALSE ;
-  }
-
-  struct stat stat_buf ;
-
-  if ( fstat ( fileno ( fd ), & stat_buf ) != 0 )
-  {
-    fprintf ( stderr,
-             "slSample: loadRawFile: Cannot get status for '%s'.\n",
-             fname ) ;        
-    fclose ( fd ) ;
-    return SL_FALSE ;
-  }
-
-  length = stat_buf . st_size ;
-
-  if ( length > 0 )
-  {
-    buffer = new Uchar [ length ] ;
-    length = fread ( buffer, 1, length, fd ) ;
-  }
-
-  bps    = 8     ;
-  stereo = SL_FALSE ;
-  rate   = 8000  ;  /* Guess */
-
-  fclose ( fd ) ;
-  return SL_TRUE ;
-}
-
-
diff --git a/Lib/src/slSamplePlayer.cxx b/Lib/src/slSamplePlayer.cxx
deleted file mode 100644
index 12eecaf65..000000000
--- a/Lib/src/slSamplePlayer.cxx
+++ /dev/null
@@ -1,188 +0,0 @@
-
-#include "sl.h"
-
-void slSamplePlayer::addEnvelope ( int i, slEnvelope *_env, slEnvelopeType _type )
-{
-  if ( i < 0 || i >= SL_MAX_ENVELOPES ) return ;
-
-  if ( env [ i ] != NULL )
-    env [ i ] -> unRef () ;
-
-  env [ i ] = _env ;
-
-  if ( _env != NULL )
-    env [ i ] -> ref () ;
-
-  env_type [ i ] = _type ;
-  env_start_time [ i ] = slScheduler::getCurrent() -> getTimeNow () ;
-}
-
-int slSamplePlayer::preempt ( int delay )
-{
-  slScheduler::getCurrent() -> addCallBack ( callback, sample, SL_EVENT_PREEMPTED, magic ) ;
-
-  switch ( preempt_mode )
-  {
-    case SL_SAMPLE_CONTINUE: if ( isRunning() )
-			       return SL_FALSE ;
-			     /* FALLTHROUGH! */
-    case SL_SAMPLE_DELAY   :                   break ;
-    case SL_SAMPLE_MUTE    : skip  ( delay ) ; break ;
-    case SL_SAMPLE_ABORT   : stop  ()        ; break ;
-    case SL_SAMPLE_RESTART : reset ()        ; break ;
-  }
-
-  return SL_TRUE ;
-}
-
-slSamplePlayer::~slSamplePlayer ()
-{
-  if ( sample )
-    sample -> unRef () ;
-
-  slScheduler::getCurrent() -> addCallBack ( callback, sample, SL_EVENT_COMPLETE, magic ) ;
-}
-
-void slSamplePlayer::skip ( int nframes )
-{
-  if ( nframes < lengthRemaining )
-  {
-    lengthRemaining -= nframes ;
-    bufferPos       += nframes ;
-  }
-  else 
-  if ( replay_mode == SL_SAMPLE_LOOP )
-  {
-    slScheduler::getCurrent() -> addCallBack ( callback, sample, SL_EVENT_LOOPED, magic ) ;
-
-    nframes -= lengthRemaining ;
-
-    while ( nframes >= sample->getLength () )
-      nframes -= sample->getLength () ;
-
-    lengthRemaining = sample->getLength() - nframes ;
-    bufferPos = & ( sample->getBuffer() [ nframes ] ) ;
-  }
-  else
-    stop () ;
-}
-
-
-void slSamplePlayer::read ( int nframes, Uchar *dst, int next_env )
-{
-  /*
-    WARNING:
-
-       CO-RECURSIVE!
-  */
-
-  /* Find the next envelope */
-
-  while ( next_env < SL_MAX_ENVELOPES && env [ next_env ] == NULL )
-    next_env++ ;
-
-  /*
-    If there are no fancy envelopes to process then return
-    the raw data.
-  */
-
-  if ( next_env >= SL_MAX_ENVELOPES ) /* No fancy envelopes left */
-  {
-    low_read ( nframes, dst ) ;
-    return ;
-  }
-
-  /*
-    Envelope processing required...
-
-    Process the next envelope using data read recursively through
-    the remaining envelopes.
-  */
-
-  switch ( env_type [ next_env ] )
-  {
-    /* For Volume envelopes, SRC and DST can be the same buffer */
-
-    case SL_INVERSE_VOLUME_ENVELOPE:
-      read ( nframes, dst, next_env+1 ) ;
-      env[ next_env ]->applyToInvVolume ( dst,dst,nframes,env_start_time[ next_env ] ) ;
-      break ;
-
-    case SL_VOLUME_ENVELOPE :
-      read ( nframes, dst, next_env+1 ) ;
-      env[ next_env ]->applyToVolume ( dst,dst,nframes,env_start_time[ next_env ] ) ;
-      break ;
-
-    case SL_INVERSE_PITCH_ENVELOPE :
-      env[ next_env ]->applyToInvPitch ( dst,this,nframes,env_start_time[ next_env ], next_env+1 ) ;
-      break ;
-
-    case SL_PITCH_ENVELOPE  :
-      env[ next_env ]->applyToPitch ( dst,this,nframes,env_start_time[ next_env ], next_env+1 ) ;
-      break ;
-
-    case SL_INVERSE_FILTER_ENVELOPE:
-    case SL_FILTER_ENVELOPE :
-      read ( nframes, dst, next_env+1 ) ;
-      break ;
-
-    case SL_INVERSE_PAN_ENVELOPE   :
-    case SL_PAN_ENVELOPE    :
-      read ( nframes, dst, next_env+1 ) ;
-      break ;
-
-    case SL_INVERSE_ECHO_ENVELOPE  :
-    case SL_ECHO_ENVELOPE   :
-      read ( nframes, dst, next_env+1 ) ;
-      break ;
-  }
-}
-
-
-void slSamplePlayer::low_read ( int nframes, Uchar *dst )
-{
-  if ( isWaiting() ) start () ;
-
-  if ( bufferPos == NULL )  /* Run out of sample & no repeats */
-  {
-    memset ( dst, 0x80, nframes ) ;
-    return ;
-  }
-
-  while ( SL_TRUE )
-  {
-    /*
-      If we can satisfy this request in one read (with data left in
-      the sample buffer ready for next time around) - then we are done...
-    */
-
-    if ( nframes < lengthRemaining )
-    {
-      memcpy ( dst, bufferPos, nframes ) ;
-      bufferPos       += nframes ;
-      lengthRemaining -= nframes ;
-      return ;
-    }
-
-    memcpy ( dst, bufferPos, lengthRemaining ) ;
-    bufferPos       += lengthRemaining ;
-    dst             += lengthRemaining ;
-    nframes         -= lengthRemaining ;
-    lengthRemaining  = 0 ;
-
-    if ( replay_mode == SL_SAMPLE_ONE_SHOT )
-    {
-      stop () ;
-      memset ( dst, 0x80, nframes ) ;
-      return ;
-    }
-    else
-    {
-      slScheduler::getCurrent() -> addCallBack ( callback, sample, SL_EVENT_LOOPED, magic ) ;
-      start () ;
-    }
-  }
-}
-
-
-
diff --git a/Lib/src/slScheduler.cxx b/Lib/src/slScheduler.cxx
deleted file mode 100644
index 5fe4caa91..000000000
--- a/Lib/src/slScheduler.cxx
+++ /dev/null
@@ -1,253 +0,0 @@
-
-#include "sl.h"
-
-char *__slPendingError = NULL ;
-
-slScheduler *slScheduler::current = NULL ;
-
-void slScheduler::init ()
-{
-  current = this ;
-
-  if ( not_working () )
-  {
-    fprintf ( stderr, "slScheduler: soundcard init failed.\n" ) ;
-    setError () ;
-    return ;
-  }
-
-  if ( getBps() != 8 )
-  {
-    fprintf ( stderr, "slScheduler: Needs a sound card that supports 8 bits per sample.\n" ) ;
-    setError () ;
-    return ;
-  }
-
-  if ( getStereo() )
-  {
-    fprintf ( stderr, "slScheduler: Needs a sound card that supports monophonic replay.\n" ) ;
-    setError () ;
-    return ;
-  }
-
-  for ( int i = 0 ; i < SL_MAX_SAMPLES ; i++ )
-    samplePlayer [ i ] = NULL ;
-
-  amount_left = 0 ;
-  now = 0 ;
-  num_pending_callbacks = 0 ;
-  safety_margin = 1.0 ;
-
-  mixer = NULL ;
-
-  mixer_buffer  = NULL ;
-  spare_buffer0 = NULL ;
-  spare_buffer1 = NULL ;
-  spare_buffer2 = NULL ;
-
-  initBuffers () ;
-}
-
-void slScheduler::initBuffers ()
-{
-  if ( not_working () )
-    return ;
-
-  delete mixer_buffer ;
-  delete spare_buffer0 ;
-  delete spare_buffer1 ;
-  delete spare_buffer2 ;
-
-  mixer_buffer_size = getDriverBufferSize () ;
-
-  mixer_buffer = new Uchar [ mixer_buffer_size ] ;
-  memset ( mixer_buffer, 0x80, mixer_buffer_size ) ;
-
-  spare_buffer0 = new Uchar [ mixer_buffer_size ] ;
-  spare_buffer1 = new Uchar [ mixer_buffer_size ] ;
-  spare_buffer2 = new Uchar [ mixer_buffer_size ] ;
-}
-
-slScheduler::~slScheduler ()
-{
-  if ( current == this )
-    current = NULL ;
-
-  delete mixer_buffer ;
-
-  delete spare_buffer0 ;
-  delete spare_buffer1 ;
-  delete spare_buffer2 ;
-}
-
-
-
-
-
-void slScheduler::mixBuffer ( slSamplePlayer *spa, slSamplePlayer *spb )
-{
-  register int    l = mixer_buffer_size ;
-  register Uchar *d = mixer_buffer ;
-
-  register Uchar *a = spare_buffer0 ;
-  register Uchar *b = spare_buffer1 ;
-
-  spa -> read ( l, a ) ;
-  spb -> read ( l, b ) ;
-
-  while ( l-- ) *d++ = mix ( *a++, *b++ ) ;
-}
-
-
-
-void slScheduler::mixBuffer ( slSamplePlayer *spa, slSamplePlayer *spb,
-                              slSamplePlayer *spc )
-{
-  register int    l = mixer_buffer_size ;
-  register Uchar *d = mixer_buffer ;
-
-  register Uchar *a = spare_buffer0 ;
-  register Uchar *b = spare_buffer1 ;
-  register Uchar *c = spare_buffer2 ;
-
-  spa -> read ( l, a ) ;
-  spb -> read ( l, b ) ;
-  spc -> read ( l, c ) ;
-
-  while ( l-- ) *d++ = mix ( *a++, *b++, *c++ ) ;
-}
-
-
-void slScheduler::realUpdate ( int dump_first )
-{
-  if ( not_working () )
-    return ;
-
-  if ( __slPendingError != NULL )
-  {
-    fprintf ( stderr, "%s", __slPendingError ) ;
-    exit ( 1 ) ;
-  }
-
-  int i ;
-
-  while ( secondsUsed() <= safety_margin )
-  {
-    slSamplePlayer *psp [ 3 ] ;
-    int             pri [ 3 ] ;
-
-    pri [ 0 ] = pri [ 1 ] = pri [ 2 ] =  -1  ;
-
-    for ( i = 0 ; i < SL_MAX_SAMPLES ; i++ )
-    {
-      if ( samplePlayer [ i ] == NULL )
-	continue ;
-
-      /* Clean up dead sample players */
-
-      if ( samplePlayer [ i ] -> isDone () )
-      {
-	delete samplePlayer [ i ] ;
-	samplePlayer [ i ] = NULL ;
-	continue ;
-      }
-
-      if ( samplePlayer [ i ] -> isPaused () )
-	continue ;
-
-      int lowest = ( pri [0] <= pri [2] ) ?
-		     (( pri [0] <= pri [1] ) ? 0 : 1 ) :
-		     (( pri [1] <= pri [2] ) ? 1 : 2 ) ;
-
-      if ( samplePlayer[i]->getPriority() > pri[lowest] )
-      {
-	psp[lowest] = samplePlayer[i] ;
-	pri[lowest] = samplePlayer[i]->getPriority() ;
-      }
-    }
-
-    for ( i = 0 ; i < SL_MAX_SAMPLES ; i++ )
-    {
-      if ( samplePlayer [ i ] == NULL )
-	continue ;
-
-      if ( ! samplePlayer [ i ] -> isPaused () &&
-           samplePlayer [ i ] != psp[0] &&
-           samplePlayer [ i ] != psp[1] &&
-           samplePlayer [ i ] != psp[2] )
-      {
-        samplePlayer [ i ] -> preempt ( mixer_buffer_size ) ;
-      }
-    }
-
-    if ( pri[0] < 0 )
-    {
-      memset ( mixer_buffer, 0x80, mixer_buffer_size ) ;
-      amount_left = 0 ;
-    }
-    else
-    if ( pri[1] < 0 )
-      psp[0] -> read ( mixer_buffer_size, mixer_buffer ) ;
-    else
-    if ( pri[2] < 0 )
-      mixBuffer ( psp[0], psp[1] ) ;
-    else
-      mixBuffer ( psp[0], psp[1], psp[2] ) ;
-
-    if ( dump_first )
-    {
-      stop () ;
-      dump_first = SL_FALSE ;
-    }
-
-    play ( mixer_buffer, mixer_buffer_size ) ;
-
-    now += mixer_buffer_size ;
-  }
-
-  flushCallBacks () ;
-}
-
-void slScheduler::addCallBack ( slCallBack c, slSample *s, slEvent e, int m )
-{
-  if ( not_working () )
-    return ;
-
-  if ( num_pending_callbacks >= SL_MAX_CALLBACKS )
-  {
-    fprintf ( stderr, "slScheduler: Too many pending callback events!\n" ) ;
-    return ;
-  }
-
-  slPendingCallBack *p = & ( pending_callback [ num_pending_callbacks++ ] ) ;
-
-  p -> callback = c ;
-  p -> sample   = s ;
-  p -> event    = e ;
-  p -> magic    = m ;
-}
-
-void slScheduler::flushCallBacks ()
-{
-  if ( not_working () )
-    return ;
-
-  /*
-    Execute all the callbacks that we accumulated
-    in this iteration.
-
-    This is done at the end of 'update' to reduce the risk
-    of nasty side-effects caused by 'unusual' activities
-    in the application's callback function.
-  */
-
-  while ( num_pending_callbacks > 0 )
-  {
-    slPendingCallBack *p = & ( pending_callback [ --num_pending_callbacks ] ) ;
-
-    if ( p -> callback )
-      (*(p->callback))( p->sample, p->event, p->magic ) ;
-  }
-}
-
-
diff --git a/Lib/src/sm.h b/Lib/src/sm.h
deleted file mode 100644
index f884cd037..000000000
--- a/Lib/src/sm.h
+++ /dev/null
@@ -1,89 +0,0 @@
-
-#ifndef __SM_H__
-#define __SM_H__ 1
-
-#include "slPortability.h"
-
-#ifdef SL_USING_OSS_AUDIO
-#define SMMIXER_DEFAULT_DEVICE "/dev/mixer"
-// static char *labels [] = SOUND_DEVICE_LABELS;
-#elif defined(WIN32)
-#define SMMIXER_DEFAULT_DEVICE "mixer"
-#else
-#endif
-
-
-# define SM_TRUE  1
-# define SM_FALSE 0
-
-typedef unsigned char  Uchar  ;
-typedef unsigned short Ushort ;
-
-
-class smMixer
-{
-private:
-
-  int devices ;
-  int error ;
-  int fd ;
-
-#ifdef SL_USING_OSS_AUDIO
-  // static char *labels [] = SOUND_DEVICE_LABELS ;
-
-  int ioctl ( int cmd, int param = 0 )
-  {
-    if ( error ) return param ;
-
-    if ( ::ioctl ( fd, cmd, & param ) == -1 )
-    {
-      perror ( "smMixer: ioctl" ) ;
-      error = SM_TRUE ;
-    }
-
-    return param ;
-  }
-#endif
-  void open ( char *device ) ;
-  void close () ;
-
-public:
-
-  /* Tom */
-
-  smMixer ();
-  smMixer ( char *device );
- ~smMixer ();
-  
-  int not_working ();
-
-  /* Volume controls are in integer percentages */
-
-  int  getVolume        ( int channel             );
-  void setVolume        ( int channel, int volume ); 
-
-  void getVolume        ( int channel, int *left, int *right );
-  void setVolume        ( int channel, int  left, int  right );
-
-  void setTreble       ( int treble );
-  void setBass         ( int bass   );
-
-  void setMasterVolume ( int volume );
-  void setSynthVolume  ( int volume );
-  void setPCMVolume    ( int volume );
-  void setSpeakerVolume( int volume );
-  void setLineVolume   ( int volume );
-  void setMicVolume    ( int volume );
-  void setCDVolume     ( int volume );
-
-  void setMasterVolume ( int left, int right );
-  void setSynthVolume  ( int left, int right );
-  void setPCMVolume    ( int left, int right );
-  void setSpeakerVolume( int left, int right );
-  void setLineVolume   ( int left, int right );
-  void setMicVolume    ( int left, int right );
-  void setCDVolume     ( int left, int right );
-} ;
-
-#endif
-
diff --git a/Lib/src/smMixer.cxx b/Lib/src/smMixer.cxx
deleted file mode 100644
index f7be007d7..000000000
--- a/Lib/src/smMixer.cxx
+++ /dev/null
@@ -1,256 +0,0 @@
-#include "sm.h"
-
-#ifdef SL_USING_OSS_AUDIO
-/* ------------------------------------------------------------ */
-/* OSSAUDIO - Linux, FreeBSD                                    */
-/* ------------------------------------------------------------ */
-
-
-void smMixer::open ( char *device )
-{
-  fd = ::open ( device, O_WRONLY ) ;
-
-  if ( fd < 0 )
-  {
-    perror ( "smMixer: open" ) ;
-    error = SM_TRUE ;
-  }
-  else
-    error = SM_FALSE ;
-
-  devices = ioctl ( SOUND_MIXER_READ_DEVMASK ) ;
-}
-  
-void smMixer::close ()
-{
-  if ( fd >= 0 )
-    ::close ( fd ) ;
-}
-
-
-smMixer::smMixer ()               
-{ 
-   open ( SMMIXER_DEFAULT_DEVICE ) ; 
-} 
-
-smMixer::smMixer ( char *device ) 
-{ 
-   open ( device ) ; 
-} 
-
-smMixer::~smMixer ()               
-{ 
-   close () ; 
-}
-  
-int smMixer::not_working () 
-{ 
-   return error ; 
-}
-
-  /* Volume controls are in integer percentages */
-
-int  smMixer::getVolume ( int channel             ) 
-{ 
-   return ioctl ( MIXER_READ  ( channel ) ) & 0xFF ; 
-}
-
-
-void smMixer::setVolume ( int channel, int volume ) 
-{ 
-   ioctl ( MIXER_WRITE ( channel ), (( volume & 255 ) << 8 ) |
-                                     ( volume & 255 ) ) ; 
-}
-
-void smMixer::getVolume ( int channel, int *left, int *right )
-{
-   int vv = ioctl ( MIXER_READ ( channel ) ) ;
-
-   if ( left  ) *left  =  vv     & 0xFF ;
-   if ( right ) *right = (vv>>8) & 0xFF ;
-}
-
-void smMixer::setVolume ( int channel, int  left, int  right )
-{
-   ioctl ( MIXER_WRITE ( channel ), (( right & 255 ) << 8 ) | 
-      ( left & 255 ) ) ;
-}
-
-void smMixer::setTreble       ( int treble ) 
-{ 
-   setVolume ( SOUND_MIXER_TREBLE , treble ) ; 
-}
-
-void smMixer::setBass         ( int bass   ) 
-{ 
-   setVolume ( SOUND_MIXER_TREBLE , bass   ) ; 
-}
-
-void smMixer::setMasterVolume ( int volume ) 
-{ 
-   setVolume ( SOUND_MIXER_VOLUME , volume ) ; 
-}
-
-void smMixer::setSynthVolume  ( int volume ) 
-{ 
-   setVolume ( SOUND_MIXER_SYNTH  , volume ) ; 
-}
-
-void smMixer::setPCMVolume    ( int volume ) 
-{ 
-   setVolume ( SOUND_MIXER_PCM    , volume ) ; 
-}
-
-void smMixer::setSpeakerVolume( int volume ) 
-{ 
-   setVolume ( SOUND_MIXER_SPEAKER, volume ) ; 
-}
-
-void smMixer::setLineVolume   ( int volume ) 
-{ 
-   setVolume ( SOUND_MIXER_LINE   , volume ) ; 
-}
-
-void smMixer::setMicVolume    ( int volume ) 
-{ 
-   setVolume ( SOUND_MIXER_MIC    , volume ) ; 
-}
-
-void smMixer::setCDVolume     ( int volume ) 
-{ 
-   setVolume ( SOUND_MIXER_CD     , volume ) ; 
-}
-
-void smMixer::setMasterVolume ( int left, int right ) 
-{ 
-   setVolume ( SOUND_MIXER_VOLUME , left, right ) ; 
-}
-
-void smMixer::setSynthVolume  ( int left, int right ) 
-{  
-   setVolume ( SOUND_MIXER_SYNTH  , left, right ) ; 
-}
-
-void smMixer::setPCMVolume    ( int left, int right ) 
-{ 
-   setVolume ( SOUND_MIXER_PCM    , left, right ) ; 
-}
-
-void smMixer::setSpeakerVolume( int left, int right ) 
-{ 
-   setVolume ( SOUND_MIXER_SPEAKER, left, right ) ; 
-}
-
-void smMixer::setLineVolume   ( int left, int right ) 
-{ 
-   setVolume ( SOUND_MIXER_LINE   , left, right ) ; 
-}
-
-void smMixer::setMicVolume    ( int left, int right ) 
-{ 
-   setVolume ( SOUND_MIXER_MIC    , left, right ) ; 
-}
-
-void smMixer::setCDVolume     ( int left, int right ) 
-{ 
-   setVolume ( SOUND_MIXER_CD     , left, right ) ; 
-}
-
-#elif defined(__OpenBSD__)
-
-/* ------------------------------------------------------------ */
-/* OpenBSD 2.3                                                  */
-/* ------------------------------------------------------------ */
-
-void smMixer::open ( char *device )
-{
-}
-  
-void smMixer::close (){}
-
-smMixer::smMixer ()    {} 
-smMixer::smMixer ( char * ) {} 
-smMixer::~smMixer ()         {}
-  
-int smMixer::not_working () 
-{ 
-   return error ; 
-}
-
-  /* Volume controls are in integer percentages */
-
-int  smMixer::getVolume ( int             ) { return 50 ; }
-void smMixer::getVolume ( int, int *left, int *right )
-{
-  if ( left  ) *left  = 50 ;
-  if ( right ) *right = 50 ;
-}
-
-void smMixer::setVolume ( int , int  ) {}
-void smMixer::setVolume ( int , int , int  ){}
-void smMixer::setTreble       ( int  ) {}
-void smMixer::setBass         ( int    ) {}
-void smMixer::setMasterVolume ( int  ) {}
-void smMixer::setSynthVolume  ( int  ) {}
-void smMixer::setPCMVolume    ( int  ) {}
-void smMixer::setSpeakerVolume( int  ) {}
-void smMixer::setLineVolume   ( int  ) {}
-void smMixer::setMicVolume    ( int  ) {}
-void smMixer::setCDVolume     ( int ) {}
-void smMixer::setMasterVolume ( int, int ) {}
-void smMixer::setSynthVolume  ( int, int ) {}
-void smMixer::setPCMVolume    ( int, int ) {}
-void smMixer::setSpeakerVolume( int, int ) {}
-void smMixer::setLineVolume   ( int, int ) {}
-void smMixer::setMicVolume    ( int, int ) {}
-void smMixer::setCDVolume     ( int, int ) {} 
-
-
-#else
-/* ------------------------------------------------------------ */
-/* win32                                                        */
-/* ------------------------------------------------------------ */
-
-void smMixer::open ( char * ) {}
-  
-void smMixer::close (){}
-
-smMixer::smMixer ()    {} 
-smMixer::smMixer ( char * ) {} 
-smMixer::~smMixer ()         {}
-  
-int smMixer::not_working () 
-{ 
-   return error ; 
-}
-
-  /* Volume controls are in integer percentages */
-
-int  smMixer::getVolume ( int             ) { return 50 ; }
-void smMixer::getVolume ( int, int *left, int *right )
-{
-  if ( left  ) *left  = 50 ;
-  if ( right ) *right = 50 ;
-}
-
-void smMixer::setVolume ( int, int ) {}
-void smMixer::setVolume ( int, int, int ){}
-void smMixer::setTreble       ( int ) {}
-void smMixer::setBass         ( int   ) {}
-void smMixer::setMasterVolume ( int ) {}
-void smMixer::setSynthVolume  ( int ) {}
-void smMixer::setPCMVolume    ( int ) {}
-void smMixer::setSpeakerVolume( int ) {}
-void smMixer::setLineVolume   ( int ) {}
-void smMixer::setMicVolume    ( int ) {}
-void smMixer::setCDVolume     ( int ) {}
-void smMixer::setMasterVolume ( int, int ) {}
-void smMixer::setSynthVolume  ( int, int ) {}
-void smMixer::setPCMVolume    ( int, int ) {}
-void smMixer::setSpeakerVolume( int, int ) {}
-void smMixer::setLineVolume   ( int, int ) {}
-void smMixer::setMicVolume    ( int, int ) {}
-void smMixer::setCDVolume     ( int, int ) {} 
-
-
-#endif
diff --git a/Lib/zlib/ChangeLog b/Lib/zlib/ChangeLog
deleted file mode 100644
index 57386a26f..000000000
--- a/Lib/zlib/ChangeLog
+++ /dev/null
@@ -1,471 +0,0 @@
-
-		ChangeLog file for zlib
-
-Changes in 1.1.3 (9 July 1998)
-- fix "an inflate input buffer bug that shows up on rare but persistent
-  occasions" (Mark)
-- fix gzread and gztell for concatenated .gz files (Didier Le Botlan)
-- fix gzseek(..., SEEK_SET) in write mode
-- fix crc check after a gzeek (Frank Faubert)
-- fix miniunzip when the last entry in a zip file is itself a zip file
-  (J Lillge)
-- add contrib/asm586 and contrib/asm686 (Brian Raiter)
-  See http://www.muppetlabs.com/~breadbox/software/assembly.html
-- add support for Delphi 3 in contrib/delphi (Bob Dellaca)
-- add support for C++Builder 3 and Delphi 3 in contrib/delphi2 (Davide Moretti)
-- do not exit prematurely in untgz if 0 at start of block (Magnus Holmgren)
-- use macro EXTERN instead of extern to support DLL for BeOS (Sander Stoks)
-- added a FAQ file
-
-- Support gzdopen on Mac with Metrowerks (Jason Linhart)
-- Do not redefine Byte on Mac (Brad Pettit & Jason Linhart)
-- define SEEK_END too if SEEK_SET is not defined (Albert Chin-A-Young)
-- avoid some warnings with Borland C (Tom Tanner)
-- fix a problem in contrib/minizip/zip.c for 16-bit MSDOS (Gilles Vollant)
-- emulate utime() for WIN32 in contrib/untgz  (Gilles Vollant)
-- allow several arguments to configure (Tim Mooney, Frodo Looijaard)
-- use libdir and includedir in Makefile.in (Tim Mooney)
-- support shared libraries on OSF1 V4 (Tim Mooney)
-- remove so_locations in "make clean"  (Tim Mooney)
-- fix maketree.c compilation error (Glenn, Mark)
-- Python interface to zlib now in Python 1.5 (Jeremy Hylton)
-- new Makefile.riscos (Rich Walker)
-- initialize static descriptors in trees.c for embedded targets (Nick Smith)
-- use "foo-gz" in example.c for RISCOS and VMS (Nick Smith)
-- add the OS/2 files in Makefile.in too (Andrew Zabolotny)
-- fix fdopen and halloc macros for Microsoft C 6.0 (Tom Lane)
-- fix maketree.c to allow clean compilation of inffixed.h (Mark)
-- fix parameter check in deflateCopy (Gunther Nikl)
-- cleanup trees.c, use compressed_len only in debug mode (Christian Spieler)
-- Many portability patches by Christian Spieler:
-  . zutil.c, zutil.h: added "const" for zmem*
-  . Make_vms.com: fixed some typos
-  . Make_vms.com: msdos/Makefile.*: removed zutil.h from some dependency lists
-  . msdos/Makefile.msc: remove "default rtl link library" info from obj files
-  . msdos/Makefile.*: use model-dependent name for the built zlib library
-  . msdos/Makefile.emx, nt/Makefile.emx, nt/Makefile.gcc:
-     new makefiles, for emx (DOS/OS2), emx&rsxnt and mingw32 (Windows 9x / NT)
-- use define instead of typedef for Bytef also for MSC small/medium (Tom Lane)
-- replace __far with _far for better portability (Christian Spieler, Tom Lane)
-- fix test for errno.h in configure (Tim Newsham)
-
-Changes in 1.1.2 (19 March 98)
-- added contrib/minzip, mini zip and unzip based on zlib (Gilles Vollant)
-  See http://www.winimage.com/zLibDll/unzip.html
-- preinitialize the inflate tables for fixed codes, to make the code
-  completely thread safe (Mark)
-- some simplifications and slight speed-up to the inflate code (Mark)
-- fix gzeof on non-compressed files (Allan Schrum)
-- add -std1 option in configure for OSF1 to fix gzprintf (Martin Mokrejs)
-- use default value of 4K for Z_BUFSIZE for 16-bit MSDOS (Tim Wegner + Glenn)
-- added os2/Makefile.def and os2/zlib.def (Andrew Zabolotny)
-- add shared lib support for UNIX_SV4.2MP (MATSUURA Takanori)
-- do not wrap extern "C" around system includes (Tom Lane)
-- mention zlib binding for TCL in README (Andreas Kupries)
-- added amiga/Makefile.pup for Amiga powerUP SAS/C PPC (Andreas Kleinert)
-- allow "make install prefix=..." even after configure (Glenn Randers-Pehrson)
-- allow "configure --prefix $HOME" (Tim Mooney)
-- remove warnings in example.c and gzio.c (Glenn Randers-Pehrson)
-- move Makefile.sas to amiga/Makefile.sas
-
-Changes in 1.1.1 (27 Feb 98)
-- fix macros _tr_tally_* in deflate.h for debug mode  (Glenn Randers-Pehrson)
-- remove block truncation heuristic which had very marginal effect for zlib
-  (smaller lit_bufsize than in gzip 1.2.4) and degraded a little the
-  compression ratio on some files. This also allows inlining _tr_tally for
-  matches in deflate_slow.
-- added msdos/Makefile.w32 for WIN32 Microsoft Visual C++ (Bob Frazier)
-
-Changes in 1.1.0 (24 Feb 98)
-- do not return STREAM_END prematurely in inflate (John Bowler)
-- revert to the zlib 1.0.8 inflate to avoid the gcc 2.8.0 bug (Jeremy Buhler)
-- compile with -DFASTEST to get compression code optimized for speed only
-- in minigzip, try mmap'ing the input file first (Miguel Albrecht)
-- increase size of I/O buffers in minigzip.c and gzio.c (not a big gain
-  on Sun but significant on HP)
-
-- add a pointer to experimental unzip library in README (Gilles Vollant)
-- initialize variable gcc in configure (Chris Herborth)
-
-Changes in 1.0.9 (17 Feb 1998)
-- added gzputs and gzgets functions
-- do not clear eof flag in gzseek (Mark Diekhans)
-- fix gzseek for files in transparent mode (Mark Diekhans)
-- do not assume that vsprintf returns the number of bytes written (Jens Krinke)
-- replace EXPORT with ZEXPORT to avoid conflict with other programs
-- added compress2 in zconf.h, zlib.def, zlib.dnt
-- new asm code from Gilles Vollant in contrib/asm386
-- simplify the inflate code (Mark):
- . Replace ZALLOC's in huft_build() with single ZALLOC in inflate_blocks_new()
- . ZALLOC the length list in inflate_trees_fixed() instead of using stack
- . ZALLOC the value area for huft_build() instead of using stack
- . Simplify Z_FINISH check in inflate()
-
-- Avoid gcc 2.8.0 comparison bug a little differently than zlib 1.0.8
-- in inftrees.c, avoid cc -O bug on HP (Farshid Elahi)
-- in zconf.h move the ZLIB_DLL stuff earlier to avoid problems with
-  the declaration of FAR (Gilles VOllant)
-- install libz.so* with mode 755 (executable) instead of 644 (Marc Lehmann)
-- read_buf buf parameter of type Bytef* instead of charf*
-- zmemcpy parameters are of type Bytef*, not charf* (Joseph Strout)
-- do not redeclare unlink in minigzip.c for WIN32 (John Bowler)
-- fix check for presence of directories in "make install" (Ian Willis)
-
-Changes in 1.0.8 (27 Jan 1998)
-- fixed offsets in contrib/asm386/gvmat32.asm (Gilles Vollant)
-- fix gzgetc and gzputc for big endian systems (Markus Oberhumer)
-- added compress2() to allow setting the compression level
-- include sys/types.h to get off_t on some systems (Marc Lehmann & QingLong)
-- use constant arrays for the static trees in trees.c instead of computing
-  them at run time (thanks to Ken Raeburn for this suggestion). To create
-  trees.h, compile with GEN_TREES_H and run "make test".
-- check return code of example in "make test" and display result
-- pass minigzip command line options to file_compress
-- simplifying code of inflateSync to avoid gcc 2.8 bug
-
-- support CC="gcc -Wall" in configure -s (QingLong)
-- avoid a flush caused by ftell in gzopen for write mode (Ken Raeburn)
-- fix test for shared library support to avoid compiler warnings
-- zlib.lib -> zlib.dll in msdos/zlib.rc (Gilles Vollant)
-- check for TARGET_OS_MAC in addition to MACOS (Brad Pettit)
-- do not use fdopen for Metrowerks on Mac (Brad Pettit))
-- add checks for gzputc and gzputc in example.c
-- avoid warnings in gzio.c and deflate.c (Andreas Kleinert)
-- use const for the CRC table (Ken Raeburn)
-- fixed "make uninstall" for shared libraries
-- use Tracev instead of Trace in infblock.c
-- in example.c use correct compressed length for test_sync
-- suppress +vnocompatwarnings in configure for HPUX (not always supported)
-
-Changes in 1.0.7 (20 Jan 1998)
-- fix gzseek which was broken in write mode
-- return error for gzseek to negative absolute position
-- fix configure for Linux (Chun-Chung Chen)
-- increase stack space for MSC (Tim Wegner)
-- get_crc_table and inflateSyncPoint are EXPORTed (Gilles Vollant)
-- define EXPORTVA for gzprintf (Gilles Vollant)
-- added man page zlib.3 (Rick Rodgers)
-- for contrib/untgz, fix makedir() and improve Makefile
-
-- check gzseek in write mode in example.c
-- allocate extra buffer for seeks only if gzseek is actually called
-- avoid signed/unsigned comparisons (Tim Wegner, Gilles Vollant)
-- add inflateSyncPoint in zconf.h
-- fix list of exported functions in nt/zlib.dnt and mdsos/zlib.def
-
-Changes in 1.0.6 (19 Jan 1998)
-- add functions gzprintf, gzputc, gzgetc, gztell, gzeof, gzseek, gzrewind and
-  gzsetparams (thanks to Roland Giersig and Kevin Ruland for some of this code)
-- Fix a deflate bug occuring only with compression level 0 (thanks to
-  Andy Buckler for finding this one).
-- In minigzip, pass transparently also the first byte for .Z files.
-- return Z_BUF_ERROR instead of Z_OK if output buffer full in uncompress()
-- check Z_FINISH in inflate (thanks to Marc Schluper)
-- Implement deflateCopy (thanks to Adam Costello)
-- make static libraries by default in configure, add --shared option.
-- move MSDOS or Windows specific files to directory msdos
-- suppress the notion of partial flush to simplify the interface
-  (but the symbol Z_PARTIAL_FLUSH is kept for compatibility with 1.0.4)
-- suppress history buffer provided by application to simplify the interface
-  (this feature was not implemented anyway in 1.0.4)
-- next_in and avail_in must be initialized before calling inflateInit or
-  inflateInit2
-- add EXPORT in all exported functions (for Windows DLL)
-- added Makefile.nt (thanks to Stephen Williams)
-- added the unsupported "contrib" directory:
-   contrib/asm386/ by Gilles Vollant 
-	386 asm code replacing longest_match().
-   contrib/iostream/ by Kevin Ruland 
-        A C++ I/O streams interface to the zlib gz* functions
-   contrib/iostream2/  by Tyge Løvset 
-	Another C++ I/O streams interface
-   contrib/untgz/  by "Pedro A. Aranda Guti\irrez" 
-	A very simple tar.gz file extractor using zlib
-   contrib/visual-basic.txt by Carlos Rios 
-        How to use compress(), uncompress() and the gz* functions from VB.
-- pass params -f (filtered data), -h (huffman only), -1 to -9 (compression
-  level) in minigzip (thanks to Tom Lane)
-
-- use const for rommable constants in deflate
-- added test for gzseek and gztell in example.c
-- add undocumented function inflateSyncPoint() (hack for Paul Mackerras)
-- add undocumented function zError to convert error code to string
-  (for Tim Smithers)
-- Allow compilation of gzio with -DNO_DEFLATE to avoid the compression code.
-- Use default memcpy for Symantec MSDOS compiler.
-- Add EXPORT keyword for check_func (needed for Windows DLL)
-- add current directory to LD_LIBRARY_PATH for "make test"
-- create also a link for libz.so.1
-- added support for FUJITSU UXP/DS (thanks to Toshiaki Nomura)
-- use $(SHAREDLIB) instead of libz.so in Makefile.in (for HPUX)
-- added -soname for Linux in configure (Chun-Chung Chen,
-- assign numbers to the exported functions in zlib.def (for Windows DLL)
-- add advice in zlib.h for best usage of deflateSetDictionary
-- work around compiler bug on Atari (cast Z_NULL in call of s->checkfn)
-- allow compilation with ANSI keywords only enabled for TurboC in large model
-- avoid "versionString"[0] (Borland bug)
-- add NEED_DUMMY_RETURN for Borland
-- use variable z_verbose for tracing in debug mode (L. Peter Deutsch).
-- allow compilation with CC
-- defined STDC for OS/2 (David Charlap)	
-- limit external names to 8 chars for MVS (Thomas Lund)
-- in minigzip.c, use static buffers only for 16-bit systems
-- fix suffix check for "minigzip -d foo.gz"
-- do not return an error for the 2nd of two consecutive gzflush() (Felix Lee)
-- use _fdopen instead of fdopen for MSC >= 6.0 (Thomas Fanslau)
-- added makelcc.bat for lcc-win32 (Tom St Denis)
-- in Makefile.dj2, use copy and del instead of install and rm (Frank Donahoe)
-- Avoid expanded $Id$. Use "rcs -kb" or "cvs admin -kb" to avoid Id expansion.
-- check for unistd.h in configure (for off_t)
-- remove useless check parameter in inflate_blocks_free
-- avoid useless assignment of s->check to itself in inflate_blocks_new
-- do not flush twice in gzclose (thanks to Ken Raeburn)
-- rename FOPEN as F_OPEN to avoid clash with /usr/include/sys/file.h
-- use NO_ERRNO_H instead of enumeration of operating systems with errno.h
-- work around buggy fclose on pipes for HP/UX
-- support zlib DLL with BORLAND C++ 5.0 (thanks to Glenn Randers-Pehrson)
-- fix configure if CC is already equal to gcc
-
-Changes in 1.0.5 (3 Jan 98)
-- Fix inflate to terminate gracefully when fed corrupted or invalid data
-- Use const for rommable constants in inflate
-- Eliminate memory leaks on error conditions in inflate
-- Removed some vestigial code in inflate
-- Update web address in README
-  
-Changes in 1.0.4 (24 Jul 96)
-- In very rare conditions, deflate(s, Z_FINISH) could fail to produce an EOF
-  bit, so the decompressor could decompress all the correct data but went
-  on to attempt decompressing extra garbage data. This affected minigzip too.
-- zlibVersion and gzerror return const char* (needed for DLL)
-- port to RISCOS (no fdopen, no multiple dots, no unlink, no fileno)
-- use z_error only for DEBUG (avoid problem with DLLs)
-
-Changes in 1.0.3 (2 Jul 96)
-- use z_streamp instead of z_stream *, which is now a far pointer in MSDOS
-  small and medium models; this makes the library incompatible with previous
-  versions for these models. (No effect in large model or on other systems.)
-- return OK instead of BUF_ERROR if previous deflate call returned with
-  avail_out as zero but there is nothing to do
-- added memcmp for non STDC compilers
-- define NO_DUMMY_DECL for more Mac compilers (.h files merged incorrectly)
-- define __32BIT__ if __386__ or i386 is defined (pb. with Watcom and SCO)
-- better check for 16-bit mode MSC (avoids problem with Symantec)
-
-Changes in 1.0.2 (23 May 96)
-- added Windows DLL support
-- added a function zlibVersion (for the DLL support)
-- fixed declarations using Bytef in infutil.c (pb with MSDOS medium model)
-- Bytef is define's instead of typedef'd only for Borland C
-- avoid reading uninitialized memory in example.c
-- mention in README that the zlib format is now RFC1950
-- updated Makefile.dj2
-- added algorithm.doc
-
-Changes in 1.0.1 (20 May 96) [1.0 skipped to avoid confusion]
-- fix array overlay in deflate.c which sometimes caused bad compressed data
-- fix inflate bug with empty stored block
-- fix MSDOS medium model which was broken in 0.99
-- fix deflateParams() which could generated bad compressed data.
-- Bytef is define'd instead of typedef'ed (work around Borland bug)
-- added an INDEX file
-- new makefiles for DJGPP (Makefile.dj2), 32-bit Borland (Makefile.b32),
-  Watcom (Makefile.wat), Amiga SAS/C (Makefile.sas)
-- speed up adler32 for modern machines without auto-increment
-- added -ansi for IRIX in configure
-- static_init_done in trees.c is an int
-- define unlink as delete for VMS
-- fix configure for QNX
-- add configure branch for SCO and HPUX
-- avoid many warnings (unused variables, dead assignments, etc...)
-- no fdopen for BeOS
-- fix the Watcom fix for 32 bit mode (define FAR as empty)
-- removed redefinition of Byte for MKWERKS
-- work around an MWKERKS bug (incorrect merge of all .h files)
-
-Changes in 0.99 (27 Jan 96)
-- allow preset dictionary shared between compressor and decompressor
-- allow compression level 0 (no compression)
-- add deflateParams in zlib.h: allow dynamic change of compression level
-  and compression strategy.
-- test large buffers and deflateParams in example.c
-- add optional "configure" to build zlib as a shared library
-- suppress Makefile.qnx, use configure instead
-- fixed deflate for 64-bit systems (detected on Cray)
-- fixed inflate_blocks for 64-bit systems (detected on Alpha)
-- declare Z_DEFLATED in zlib.h (possible parameter for deflateInit2)
-- always return Z_BUF_ERROR when deflate() has nothing to do
-- deflateInit and inflateInit are now macros to allow version checking
-- prefix all global functions and types with z_ with -DZ_PREFIX
-- make falloc completely reentrant (inftrees.c)
-- fixed very unlikely race condition in ct_static_init
-- free in reverse order of allocation to help memory manager
-- use zlib-1.0/* instead of zlib/* inside the tar.gz
-- make zlib warning-free with "gcc -O3 -Wall -Wwrite-strings -Wpointer-arith
-  -Wconversion -Wstrict-prototypes -Wmissing-prototypes"
-- allow gzread on concatenated .gz files
-- deflateEnd now returns Z_DATA_ERROR if it was premature
-- deflate is finally (?) fully deterministic (no matches beyond end of input)
-- Document Z_SYNC_FLUSH
-- add uninstall in Makefile
-- Check for __cpluplus in zlib.h
-- Better test in ct_align for partial flush
-- avoid harmless warnings for Borland C++
-- initialize hash_head in deflate.c
-- avoid warning on fdopen (gzio.c) for HP cc -Aa
-- include stdlib.h for STDC compilers
-- include errno.h for Cray
-- ignore error if ranlib doesn't exist
-- call ranlib twice for NeXTSTEP
-- use exec_prefix instead of prefix for libz.a
-- renamed ct_* as _tr_* to avoid conflict with applications
-- clear z->msg in inflateInit2 before any error return
-- initialize opaque in example.c, gzio.c, deflate.c and inflate.c
-- fixed typo in zconf.h (_GNUC__ => __GNUC__)
-- check for WIN32 in zconf.h and zutil.c (avoid farmalloc in 32-bit mode)
-- fix typo in Make_vms.com (f$trnlnm -> f$getsyi)
-- in fcalloc, normalize pointer if size > 65520 bytes
-- don't use special fcalloc for 32 bit Borland C++
-- use STDC instead of __GO32__ to avoid redeclaring exit, calloc, etc...
-- use Z_BINARY instead of BINARY
-- document that gzclose after gzdopen will close the file
-- allow "a" as mode in gzopen.
-- fix error checking in gzread
-- allow skipping .gz extra-field on pipes
-- added reference to Perl interface in README
-- put the crc table in FAR data (I dislike more and more the medium model :)
-- added get_crc_table
-- added a dimension to all arrays (Borland C can't count).
-- workaround Borland C bug in declaration of inflate_codes_new & inflate_fast
-- guard against multiple inclusion of *.h (for precompiled header on Mac)
-- Watcom C pretends to be Microsoft C small model even in 32 bit mode.
-- don't use unsized arrays to avoid silly warnings by Visual C++:
-     warning C4746: 'inflate_mask' : unsized array treated as  '__far'
-     (what's wrong with far data in far model?).
-- define enum out of inflate_blocks_state to allow compilation with C++
-
-Changes in 0.95 (16 Aug 95)
-- fix MSDOS small and medium model (now easier to adapt to any compiler)
-- inlined send_bits
-- fix the final (:-) bug for deflate with flush (output was correct but
-  not completely flushed in rare occasions).
-- default window size is same for compression and decompression
-  (it's now sufficient to set MAX_WBITS in zconf.h).
-- voidp -> voidpf and voidnp -> voidp (for consistency with other
-  typedefs and because voidnp was not near in large model).
-
-Changes in 0.94 (13 Aug 95)
-- support MSDOS medium model
-- fix deflate with flush (could sometimes generate bad output)
-- fix deflateReset (zlib header was incorrectly suppressed)
-- added support for VMS
-- allow a compression level in gzopen()
-- gzflush now calls fflush
-- For deflate with flush, flush even if no more input is provided.
-- rename libgz.a as libz.a
-- avoid complex expression in infcodes.c triggering Turbo C bug
-- work around a problem with gcc on Alpha (in INSERT_STRING)
-- don't use inline functions (problem with some gcc versions)
-- allow renaming of Byte, uInt, etc... with #define.
-- avoid warning about (unused) pointer before start of array in deflate.c
-- avoid various warnings in gzio.c, example.c, infblock.c, adler32.c, zutil.c
-- avoid reserved word 'new' in trees.c
-
-Changes in 0.93 (25 June 95)
-- temporarily disable inline functions
-- make deflate deterministic
-- give enough lookahead for PARTIAL_FLUSH
-- Set binary mode for stdin/stdout in minigzip.c for OS/2
-- don't even use signed char in inflate (not portable enough)
-- fix inflate memory leak for segmented architectures
-
-Changes in 0.92 (3 May 95)
-- don't assume that char is signed (problem on SGI)
-- Clear bit buffer when starting a stored block
-- no memcpy on Pyramid
-- suppressed inftest.c
-- optimized fill_window, put longest_match inline for gcc
-- optimized inflate on stored blocks.
-- untabify all sources to simplify patches
-
-Changes in 0.91 (2 May 95)
-- Default MEM_LEVEL is 8 (not 9 for Unix) as documented in zlib.h
-- Document the memory requirements in zconf.h
-- added "make install"
-- fix sync search logic in inflateSync
-- deflate(Z_FULL_FLUSH) now works even if output buffer too short
-- after inflateSync, don't scare people with just "lo world"
-- added support for DJGPP
-
-Changes in 0.9 (1 May 95)
-- don't assume that zalloc clears the allocated memory (the TurboC bug
-  was Mark's bug after all :)
-- let again gzread copy uncompressed data unchanged (was working in 0.71)
-- deflate(Z_FULL_FLUSH), inflateReset and inflateSync are now fully implemented
-- added a test of inflateSync in example.c
-- moved MAX_WBITS to zconf.h because users might want to change that.
-- document explicitly that zalloc(64K) on MSDOS must return a normalized
-  pointer (zero offset)
-- added Makefiles for Microsoft C, Turbo C, Borland C++
-- faster crc32()
-
-Changes in 0.8 (29 April 95)
-- added fast inflate (inffast.c)
-- deflate(Z_FINISH) now returns Z_STREAM_END when done. Warning: this
-  is incompatible with previous versions of zlib which returned Z_OK.
-- work around a TurboC compiler bug (bad code for b << 0, see infutil.h)
-  (actually that was not a compiler bug, see 0.81 above)
-- gzread no longer reads one extra byte in certain cases
-- In gzio destroy(), don't reference a freed structure
-- avoid many warnings for MSDOS
-- avoid the ERROR symbol which is used by MS Windows
-
-Changes in 0.71 (14 April 95)
-- Fixed more MSDOS compilation problems :( There is still a bug with
-  TurboC large model.
-
-Changes in 0.7 (14 April 95)
-- Added full inflate support.
-- Simplified the crc32() interface. The pre- and post-conditioning
-  (one's complement) is now done inside crc32(). WARNING: this is
-  incompatible with previous versions; see zlib.h for the new usage.
-
-Changes in 0.61 (12 April 95)
-- workaround for a bug in TurboC. example and minigzip now work on MSDOS.
-
-Changes in 0.6 (11 April 95)
-- added minigzip.c
-- added gzdopen to reopen a file descriptor as gzFile
-- added transparent reading of non-gziped files in gzread.
-- fixed bug in gzread (don't read crc as data)
-- fixed bug in destroy (gzio.c) (don't return Z_STREAM_END for gzclose).
-- don't allocate big arrays in the stack (for MSDOS)
-- fix some MSDOS compilation problems
-
-Changes in 0.5:
-- do real compression in deflate.c. Z_PARTIAL_FLUSH is supported but
-  not yet Z_FULL_FLUSH.
-- support decompression but only in a single step (forced Z_FINISH)
-- added opaque object for zalloc and zfree.
-- added deflateReset and inflateReset
-- added a variable zlib_version for consistency checking.
-- renamed the 'filter' parameter of deflateInit2 as 'strategy'.
-  Added Z_FILTERED and Z_HUFFMAN_ONLY constants.
-
-Changes in 0.4:
-- avoid "zip" everywhere, use zlib instead of ziplib.
-- suppress Z_BLOCK_FLUSH, interpret Z_PARTIAL_FLUSH as block flush
-  if compression method == 8.
-- added adler32 and crc32
-- renamed deflateOptions as deflateInit2, call one or the other but not both
-- added the method parameter for deflateInit2.
-- added inflateInit2
-- simplied considerably deflateInit and inflateInit by not supporting
-  user-provided history buffer. This is supported only in deflateInit2
-  and inflateInit2.
-
-Changes in 0.3:
-- prefix all macro names with Z_
-- use Z_FINISH instead of deflateEnd to finish compression.
-- added Z_HUFFMAN_ONLY
-- added gzerror()
diff --git a/Lib/zlib/INDEX b/Lib/zlib/INDEX
deleted file mode 100644
index 8a2457664..000000000
--- a/Lib/zlib/INDEX
+++ /dev/null
@@ -1,86 +0,0 @@
-ChangeLog		history of changes
-INDEX			this file
-FAQ			Frequently Asked Questions about zlib
-Make_vms.com		script for Vax/VMS
-Makefile		makefile for Unix (generated by configure)
-Makefile.in		makefile for Unix (template for configure)
-Makefile.riscos 	makefile for RISCOS
-README			guess what
-algorithm.txt		description of the (de)compression algorithm
-configure		configure script for Unix
-descrip.mms		makefile for Vax/VMS
-zlib.3			mini man page for zlib (volunteers to write full
-			man pages from zlib.h welcome. write to jloup@gzip.org)
-
-amiga/Makefile.sas	makefile for Amiga SAS/C
-amiga/Makefile.pup      makefile for Amiga powerUP SAS/C PPC
-
-msdos/Makefile.w32      makefile for Microsoft Visual C++ 32-bit
-msdos/Makefile.b32	makefile for Borland C++   32-bit
-msdos/Makefile.bor	makefile for Borland C/C++ 16-bit
-msdos/Makefile.dj2	makefile for DJGPP 2.x
-msdos/Makefile.emx	makefile for EMX 0.9c (32-bit DOS/OS2)
-msdos/Makefile.msc	makefile for Microsoft C 16-bit
-msdos/Makefile.tc	makefile for Turbo C
-msdos/Makefile.wat	makefile for Watcom C
-msdos/zlib.def        	definition file for Windows DLL
-msdos/zlib.rc         	definition file for Windows DLL
-
-nt/Makefile.nt		makefile for Windows NT
-nt/zlib.dnt		definition file for Windows NT DLL
-nt/Makefile.emx		makefile for EMX 0.9c/RSXNT 1.41 (Win32 Intel)
-nt/Makefile.gcc		makefile for Windows NT using GCC (mingw32)
-
-
-		zlib public header files (must be kept):
-zconf.h
-zlib.h
-
-		private source files used to build the zlib library:
-adler32.c
-compress.c
-crc32.c
-deflate.c
-deflate.h
-gzio.c
-infblock.c
-infblock.h
-infcodes.c
-infcodes.h
-inffast.c
-inffast.h
-inflate.c
-inftrees.c
-inftrees.h
-infutil.c
-infutil.h
-maketree.c
-trees.c
-uncompr.c
-zutil.c
-zutil.h
-
-		source files for sample programs:
-example.c
-minigzip.c
-
-		unsupported contribution by third parties
-
-contrib/asm386/ by Gilles Vollant 
-	386 asm code replacing longest_match().
-
-contrib/minizip/ by Gilles Vollant 
-	Mini zip and unzip based on zlib
-        See http://www.winimage.com/zLibDll/unzip.html
-
-contrib/iostream/ by Kevin Ruland 
-        A C++ I/O streams interface to the zlib gz* functions
-
-contrib/iostream2/  by Tyge Løvset 
-	Another C++ I/O streams interface
-
-contrib/untgz/  by "Pedro A. Aranda Guti\irrez" 
-	A very simple tar.gz extractor using zlib
-
-contrib/visual-basic.txt by Carlos Rios 
-        How to use compress(), uncompress() and the gz* functions from VB.
diff --git a/Lib/zlib/Makefile.am b/Lib/zlib/Makefile.am
deleted file mode 100644
index 0c93862fc..000000000
--- a/Lib/zlib/Makefile.am
+++ /dev/null
@@ -1,31 +0,0 @@
-EXTRA_DIST = ChangeLog INDEX Make_vms.com Makefile.riscos README \
-	algorithm.txt descrip.mms example.c maketree.c minigzip.c zlib.3
-
-lib_LIBRARIES = libz.a
-
-libz_a_SOURCES = \
-	adler32.c \
-	compress.c \
-	crc32.c \
-	deflate.c \
-	deflate.h \
-	gzio.c \
-	infblock.c \
-	infblock.h \
-	infcodes.c \
-	infcodes.h \
-	inffast.c \
-	inffast.h \
-	inffixed.h \
-	inflate.c \
-	inftrees.c \
-	inftrees.h \
-	infutil.c \
-	infutil.h \
-	trees.c \
-	trees.h \
-	uncompr.c \
-	zconf.h \
-	zlib.h \
-	zutil.c \
-	zutil.h
diff --git a/Lib/zlib/README b/Lib/zlib/README
deleted file mode 100644
index 8ff458799..000000000
--- a/Lib/zlib/README
+++ /dev/null
@@ -1,148 +0,0 @@
-zlib 1.1.3 is a general purpose data compression library.  All the code
-is thread safe.  The data format used by the zlib library
-is described by RFCs (Request for Comments) 1950 to 1952 in the files 
-ftp://ds.internic.net/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate
-format) and rfc1952.txt (gzip format). These documents are also available in
-other formats from ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html
-
-All functions of the compression library are documented in the file zlib.h
-(volunteer to write man pages welcome, contact jloup@gzip.org). A usage
-example of the library is given in the file example.c which also tests that
-the library is working correctly. Another example is given in the file
-minigzip.c. The compression library itself is composed of all source files
-except example.c and minigzip.c.
-
-To compile all files and run the test program, follow the instructions
-given at the top of Makefile. In short "make test; make install"
-should work for most machines. For Unix: "configure; make test; make install"
-For MSDOS, use one of the special makefiles such as Makefile.msc.
-For VMS, use Make_vms.com or descrip.mms.
-
-Questions about zlib should be sent to , or to
-Gilles Vollant  for the Windows DLL version.
-The zlib home page is http://www.cdrom.com/pub/infozip/zlib/
-The official zlib ftp site is ftp://ftp.cdrom.com/pub/infozip/zlib/
-Before reporting a problem, please check those sites to verify that
-you have the latest version of zlib; otherwise get the latest version and
-check whether the problem still exists or not.
-
-Mark Nelson  wrote an article about zlib for the Jan. 1997
-issue of  Dr. Dobb's Journal; a copy of the article is available in
-http://web2.airmail.net/markn/articles/zlibtool/zlibtool.htm
-
-The changes made in version 1.1.3 are documented in the file ChangeLog.
-The main changes since 1.1.2 are:
-
-- fix "an inflate input buffer bug that shows up on rare but persistent
-  occasions" (Mark)
-- fix gzread and gztell for concatenated .gz files (Didier Le Botlan)
-- fix gzseek(..., SEEK_SET) in write mode
-- fix crc check after a gzeek (Frank Faubert)
-- fix miniunzip when the last entry in a zip file is itself a zip file
-  (J Lillge)
-- add contrib/asm586 and contrib/asm686 (Brian Raiter)
-  See http://www.muppetlabs.com/~breadbox/software/assembly.html
-- add support for Delphi 3 in contrib/delphi (Bob Dellaca)
-- add support for C++Builder 3 and Delphi 3 in contrib/delphi2 (Davide Moretti)
-- do not exit prematurely in untgz if 0 at start of block (Magnus Holmgren)
-- use macro EXTERN instead of extern to support DLL for BeOS (Sander Stoks)
-- added a FAQ file
-
-plus many changes for portability.
-
-Unsupported third party contributions are provided in directory "contrib".
-
-A Java implementation of zlib is available in the Java Development Kit 1.1
-http://www.javasoft.com/products/JDK/1.1/docs/api/Package-java.util.zip.html
-See the zlib home page http://www.cdrom.com/pub/infozip/zlib/ for details.
-
-A Perl interface to zlib written by Paul Marquess 
-is in the CPAN (Comprehensive Perl Archive Network) sites, such as:
-ftp://ftp.cis.ufl.edu/pub/perl/CPAN/modules/by-module/Compress/Compress-Zlib*
-
-A Python interface to zlib written by A.M. Kuchling 
-is available in Python 1.5 and later versions, see
-http://www.python.org/doc/lib/module-zlib.html
-
-A zlib binding for TCL written by Andreas Kupries 
-is availlable at http://www.westend.com/~kupries/doc/trf/man/man.html
-
-An experimental package to read and write files in .zip format,
-written on top of zlib by Gilles Vollant , is
-available at http://www.winimage.com/zLibDll/unzip.html
-and also in the contrib/minizip directory of zlib.
-
-
-Notes for some targets:
-
-- To build a Windows DLL version, include in a DLL project zlib.def, zlib.rc
-  and all .c files except example.c and minigzip.c; compile with -DZLIB_DLL
-  The zlib DLL support was initially done by Alessandro Iacopetti and is
-  now maintained by Gilles Vollant . Check the zlib DLL
-  home page at http://www.winimage.com/zLibDll
-
-  From Visual Basic, you can call the DLL functions which do not take
-  a structure as argument: compress, uncompress and all gz* functions.
-  See contrib/visual-basic.txt for more information, or get
-  http://www.tcfb.com/dowseware/cmp-z-it.zip
-
-- For 64-bit Irix, deflate.c must be compiled without any optimization.
-  With -O, one libpng test fails. The test works in 32 bit mode (with
-  the -n32 compiler flag). The compiler bug has been reported to SGI.
-
-- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1   
-  it works when compiled with cc.
-
-- on Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1
-  is necessary to get gzprintf working correctly. This is done by configure.
-
-- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works
-  with other compilers. Use "make test" to check your compiler.
-
-- gzdopen is not supported on RISCOS, BEOS and by some Mac compilers.
-
-- For Turbo C the small model is supported only with reduced performance to
-  avoid any far allocation; it was tested with -DMAX_WBITS=11 -DMAX_MEM_LEVEL=3
-
-- For PalmOs, see http://www.cs.uit.no/~perm/PASTA/pilot/software.html
-  Per Harald Myrvang 
-
-
-Acknowledgments:
-
-  The deflate format used by zlib was defined by Phil Katz. The deflate
-  and zlib specifications were written by L. Peter Deutsch. Thanks to all the
-  people who reported problems and suggested various improvements in zlib;
-  they are too numerous to cite here.
-
-Copyright notice:
-
- (C) 1995-1998 Jean-loup Gailly and Mark Adler
-
-  This software is provided 'as-is', without any express or implied
-  warranty.  In no event will the authors be held liable for any damages
-  arising from the use of this software.
-
-  Permission is granted to anyone to use this software for any purpose,
-  including commercial applications, and to alter it and redistribute it
-  freely, subject to the following restrictions:
-
-  1. The origin of this software must not be misrepresented; you must not
-     claim that you wrote the original software. If you use this software
-     in a product, an acknowledgment in the product documentation would be
-     appreciated but is not required.
-  2. Altered source versions must be plainly marked as such, and must not be
-     misrepresented as being the original software.
-  3. This notice may not be removed or altered from any source distribution.
-
-  Jean-loup Gailly        Mark Adler
-  jloup@gzip.org          madler@alumni.caltech.edu
-
-If you use the zlib library in a product, we would appreciate *not*
-receiving lengthy legal documents to sign. The sources are provided
-for free but without warranty of any kind.  The library has been
-entirely written by Jean-loup Gailly and Mark Adler; it does not
-include third-party code.
-
-If you redistribute modified sources, we would appreciate that you include
-in the file ChangeLog history information documenting your changes.
diff --git a/Lib/zlib/adler32.c b/Lib/zlib/adler32.c
deleted file mode 100644
index 16cf9a703..000000000
--- a/Lib/zlib/adler32.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/* adler32.c -- compute the Adler-32 checksum of a data stream
- * Copyright (C) 1995-1998 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* @(#) $Id$ */
-
-#include "zlib.h"
-
-#define BASE 65521L /* largest prime smaller than 65536 */
-#define NMAX 5552
-/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
-
-#define DO1(buf,i)  {s1 += buf[i]; s2 += s1;}
-#define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1);
-#define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2);
-#define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);
-#define DO16(buf)   DO8(buf,0); DO8(buf,8);
-
-/* ========================================================================= */
-uLong ZEXPORT adler32(adler, buf, len)
-    uLong adler;
-    const Bytef *buf;
-    uInt len;
-{
-    unsigned long s1 = adler & 0xffff;
-    unsigned long s2 = (adler >> 16) & 0xffff;
-    int k;
-
-    if (buf == Z_NULL) return 1L;
-
-    while (len > 0) {
-        k = len < NMAX ? len : NMAX;
-        len -= k;
-        while (k >= 16) {
-            DO16(buf);
-	    buf += 16;
-            k -= 16;
-        }
-        if (k != 0) do {
-            s1 += *buf++;
-	    s2 += s1;
-        } while (--k);
-        s1 %= BASE;
-        s2 %= BASE;
-    }
-    return (s2 << 16) | s1;
-}
diff --git a/Lib/zlib/algorithm.txt b/Lib/zlib/algorithm.txt
deleted file mode 100644
index cdc830b5d..000000000
--- a/Lib/zlib/algorithm.txt
+++ /dev/null
@@ -1,213 +0,0 @@
-1. Compression algorithm (deflate)
-
-The deflation algorithm used by gzip (also zip and zlib) is a variation of
-LZ77 (Lempel-Ziv 1977, see reference below). It finds duplicated strings in
-the input data.  The second occurrence of a string is replaced by a
-pointer to the previous string, in the form of a pair (distance,
-length).  Distances are limited to 32K bytes, and lengths are limited
-to 258 bytes. When a string does not occur anywhere in the previous
-32K bytes, it is emitted as a sequence of literal bytes.  (In this
-description, `string' must be taken as an arbitrary sequence of bytes,
-and is not restricted to printable characters.)
-
-Literals or match lengths are compressed with one Huffman tree, and
-match distances are compressed with another tree. The trees are stored
-in a compact form at the start of each block. The blocks can have any
-size (except that the compressed data for one block must fit in
-available memory). A block is terminated when deflate() determines that
-it would be useful to start another block with fresh trees. (This is
-somewhat similar to the behavior of LZW-based _compress_.)
-
-Duplicated strings are found using a hash table. All input strings of
-length 3 are inserted in the hash table. A hash index is computed for
-the next 3 bytes. If the hash chain for this index is not empty, all
-strings in the chain are compared with the current input string, and
-the longest match is selected.
-
-The hash chains are searched starting with the most recent strings, to
-favor small distances and thus take advantage of the Huffman encoding.
-The hash chains are singly linked. There are no deletions from the
-hash chains, the algorithm simply discards matches that are too old.
-
-To avoid a worst-case situation, very long hash chains are arbitrarily
-truncated at a certain length, determined by a runtime option (level
-parameter of deflateInit). So deflate() does not always find the longest
-possible match but generally finds a match which is long enough.
-
-deflate() also defers the selection of matches with a lazy evaluation
-mechanism. After a match of length N has been found, deflate() searches for
-a longer match at the next input byte. If a longer match is found, the
-previous match is truncated to a length of one (thus producing a single
-literal byte) and the process of lazy evaluation begins again. Otherwise,
-the original match is kept, and the next match search is attempted only N
-steps later.
-
-The lazy match evaluation is also subject to a runtime parameter. If
-the current match is long enough, deflate() reduces the search for a longer
-match, thus speeding up the whole process. If compression ratio is more
-important than speed, deflate() attempts a complete second search even if
-the first match is already long enough.
-
-The lazy match evaluation is not performed for the fastest compression
-modes (level parameter 1 to 3). For these fast modes, new strings
-are inserted in the hash table only when no match was found, or
-when the match is not too long. This degrades the compression ratio
-but saves time since there are both fewer insertions and fewer searches.
-
-
-2. Decompression algorithm (inflate)
-
-2.1 Introduction
-
-The real question is, given a Huffman tree, how to decode fast.  The most
-important realization is that shorter codes are much more common than
-longer codes, so pay attention to decoding the short codes fast, and let
-the long codes take longer to decode.
-
-inflate() sets up a first level table that covers some number of bits of
-input less than the length of longest code.  It gets that many bits from the
-stream, and looks it up in the table.  The table will tell if the next
-code is that many bits or less and how many, and if it is, it will tell
-the value, else it will point to the next level table for which inflate()
-grabs more bits and tries to decode a longer code.
-
-How many bits to make the first lookup is a tradeoff between the time it
-takes to decode and the time it takes to build the table.  If building the
-table took no time (and if you had infinite memory), then there would only
-be a first level table to cover all the way to the longest code.  However,
-building the table ends up taking a lot longer for more bits since short
-codes are replicated many times in such a table.  What inflate() does is
-simply to make the number of bits in the first table a variable, and set it
-for the maximum speed.
-
-inflate() sends new trees relatively often, so it is possibly set for a
-smaller first level table than an application that has only one tree for
-all the data.  For inflate, which has 286 possible codes for the
-literal/length tree, the size of the first table is nine bits.  Also the
-distance trees have 30 possible values, and the size of the first table is
-six bits.  Note that for each of those cases, the table ended up one bit
-longer than the ``average'' code length, i.e. the code length of an
-approximately flat code which would be a little more than eight bits for
-286 symbols and a little less than five bits for 30 symbols.  It would be
-interesting to see if optimizing the first level table for other
-applications gave values within a bit or two of the flat code size.
-
-
-2.2 More details on the inflate table lookup
-
-Ok, you want to know what this cleverly obfuscated inflate tree actually  
-looks like.  You are correct that it's not a Huffman tree.  It is simply a  
-lookup table for the first, let's say, nine bits of a Huffman symbol.  The  
-symbol could be as short as one bit or as long as 15 bits.  If a particular  
-symbol is shorter than nine bits, then that symbol's translation is duplicated
-in all those entries that start with that symbol's bits.  For example, if the  
-symbol is four bits, then it's duplicated 32 times in a nine-bit table.  If a  
-symbol is nine bits long, it appears in the table once.
-
-If the symbol is longer than nine bits, then that entry in the table points  
-to another similar table for the remaining bits.  Again, there are duplicated  
-entries as needed.  The idea is that most of the time the symbol will be short
-and there will only be one table look up.  (That's whole idea behind data  
-compression in the first place.)  For the less frequent long symbols, there  
-will be two lookups.  If you had a compression method with really long  
-symbols, you could have as many levels of lookups as is efficient.  For  
-inflate, two is enough.
-
-So a table entry either points to another table (in which case nine bits in  
-the above example are gobbled), or it contains the translation for the symbol  
-and the number of bits to gobble.  Then you start again with the next  
-ungobbled bit.
-
-You may wonder: why not just have one lookup table for how ever many bits the  
-longest symbol is?  The reason is that if you do that, you end up spending  
-more time filling in duplicate symbol entries than you do actually decoding.   
-At least for deflate's output that generates new trees every several 10's of  
-kbytes.  You can imagine that filling in a 2^15 entry table for a 15-bit code  
-would take too long if you're only decoding several thousand symbols.  At the  
-other extreme, you could make a new table for every bit in the code.  In fact,
-that's essentially a Huffman tree.  But then you spend two much time  
-traversing the tree while decoding, even for short symbols.
-
-So the number of bits for the first lookup table is a trade of the time to  
-fill out the table vs. the time spent looking at the second level and above of
-the table.
-
-Here is an example, scaled down:
-
-The code being decoded, with 10 symbols, from 1 to 6 bits long:
-
-A: 0
-B: 10
-C: 1100
-D: 11010
-E: 11011
-F: 11100
-G: 11101
-H: 11110
-I: 111110
-J: 111111
-
-Let's make the first table three bits long (eight entries):
-
-000: A,1
-001: A,1
-010: A,1
-011: A,1
-100: B,2
-101: B,2
-110: -> table X (gobble 3 bits)
-111: -> table Y (gobble 3 bits)
-
-Each entry is what the bits decode to and how many bits that is, i.e. how  
-many bits to gobble.  Or the entry points to another table, with the number of
-bits to gobble implicit in the size of the table.
-
-Table X is two bits long since the longest code starting with 110 is five bits
-long:
-
-00: C,1
-01: C,1
-10: D,2
-11: E,2
-
-Table Y is three bits long since the longest code starting with 111 is six  
-bits long:
-
-000: F,2
-001: F,2
-010: G,2
-011: G,2
-100: H,2
-101: H,2
-110: I,3
-111: J,3
-
-So what we have here are three tables with a total of 20 entries that had to  
-be constructed.  That's compared to 64 entries for a single table.  Or  
-compared to 16 entries for a Huffman tree (six two entry tables and one four  
-entry table).  Assuming that the code ideally represents the probability of  
-the symbols, it takes on the average 1.25 lookups per symbol.  That's compared
-to one lookup for the single table, or 1.66 lookups per symbol for the  
-Huffman tree.
-
-There, I think that gives you a picture of what's going on.  For inflate, the  
-meaning of a particular symbol is often more than just a letter.  It can be a  
-byte (a "literal"), or it can be either a length or a distance which  
-indicates a base value and a number of bits to fetch after the code that is  
-added to the base value.  Or it might be the special end-of-block code.  The  
-data structures created in inftrees.c try to encode all that information  
-compactly in the tables.
-
-
-Jean-loup Gailly        Mark Adler
-jloup@gzip.org          madler@alumni.caltech.edu
-
-
-References:
-
-[LZ77] Ziv J., Lempel A., ``A Universal Algorithm for Sequential Data
-Compression,'' IEEE Transactions on Information Theory, Vol. 23, No. 3,
-pp. 337-343.
-
-``DEFLATE Compressed Data Format Specification'' available in
-ftp://ds.internic.net/rfc/rfc1951.txt
diff --git a/Lib/zlib/compress.c b/Lib/zlib/compress.c
deleted file mode 100644
index 1cee47091..000000000
--- a/Lib/zlib/compress.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/* compress.c -- compress a memory buffer
- * Copyright (C) 1995-1998 Jean-loup Gailly.
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* @(#) $Id$ */
-
-#include "zlib.h"
-
-/* ===========================================================================
-     Compresses the source buffer into the destination buffer. The level
-   parameter has the same meaning as in deflateInit.  sourceLen is the byte
-   length of the source buffer. Upon entry, destLen is the total size of the
-   destination buffer, which must be at least 0.1% larger than sourceLen plus
-   12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
-
-     compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
-   memory, Z_BUF_ERROR if there was not enough room in the output buffer,
-   Z_STREAM_ERROR if the level parameter is invalid.
-*/
-int ZEXPORT compress2 (dest, destLen, source, sourceLen, level)
-    Bytef *dest;
-    uLongf *destLen;
-    const Bytef *source;
-    uLong sourceLen;
-    int level;
-{
-    z_stream stream;
-    int err;
-
-    stream.next_in = (Bytef*)source;
-    stream.avail_in = (uInt)sourceLen;
-#ifdef MAXSEG_64K
-    /* Check for source > 64K on 16-bit machine: */
-    if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
-#endif
-    stream.next_out = dest;
-    stream.avail_out = (uInt)*destLen;
-    if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
-
-    stream.zalloc = (alloc_func)0;
-    stream.zfree = (free_func)0;
-    stream.opaque = (voidpf)0;
-
-    err = deflateInit(&stream, level);
-    if (err != Z_OK) return err;
-
-    err = deflate(&stream, Z_FINISH);
-    if (err != Z_STREAM_END) {
-        deflateEnd(&stream);
-        return err == Z_OK ? Z_BUF_ERROR : err;
-    }
-    *destLen = stream.total_out;
-
-    err = deflateEnd(&stream);
-    return err;
-}
-
-/* ===========================================================================
- */
-int ZEXPORT compress (dest, destLen, source, sourceLen)
-    Bytef *dest;
-    uLongf *destLen;
-    const Bytef *source;
-    uLong sourceLen;
-{
-    return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION);
-}
diff --git a/Lib/zlib/crc32.c b/Lib/zlib/crc32.c
deleted file mode 100644
index a91101a81..000000000
--- a/Lib/zlib/crc32.c
+++ /dev/null
@@ -1,162 +0,0 @@
-/* crc32.c -- compute the CRC-32 of a data stream
- * Copyright (C) 1995-1998 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* @(#) $Id$ */
-
-#include "zlib.h"
-
-#define local static
-
-#ifdef DYNAMIC_CRC_TABLE
-
-local int crc_table_empty = 1;
-local uLongf crc_table[256];
-local void make_crc_table OF((void));
-
-/*
-  Generate a table for a byte-wise 32-bit CRC calculation on the polynomial:
-  x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
-
-  Polynomials over GF(2) are represented in binary, one bit per coefficient,
-  with the lowest powers in the most significant bit.  Then adding polynomials
-  is just exclusive-or, and multiplying a polynomial by x is a right shift by
-  one.  If we call the above polynomial p, and represent a byte as the
-  polynomial q, also with the lowest power in the most significant bit (so the
-  byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
-  where a mod b means the remainder after dividing a by b.
-
-  This calculation is done using the shift-register method of multiplying and
-  taking the remainder.  The register is initialized to zero, and for each
-  incoming bit, x^32 is added mod p to the register if the bit is a one (where
-  x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
-  x (which is shifting right by one and adding x^32 mod p if the bit shifted
-  out is a one).  We start with the highest power (least significant bit) of
-  q and repeat for all eight bits of q.
-
-  The table is simply the CRC of all possible eight bit values.  This is all
-  the information needed to generate CRC's on data a byte at a time for all
-  combinations of CRC register values and incoming bytes.
-*/
-local void make_crc_table()
-{
-  uLong c;
-  int n, k;
-  uLong poly;            /* polynomial exclusive-or pattern */
-  /* terms of polynomial defining this crc (except x^32): */
-  static const Byte p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
-
-  /* make exclusive-or pattern from polynomial (0xedb88320L) */
-  poly = 0L;
-  for (n = 0; n < sizeof(p)/sizeof(Byte); n++)
-    poly |= 1L << (31 - p[n]);
- 
-  for (n = 0; n < 256; n++)
-  {
-    c = (uLong)n;
-    for (k = 0; k < 8; k++)
-      c = c & 1 ? poly ^ (c >> 1) : c >> 1;
-    crc_table[n] = c;
-  }
-  crc_table_empty = 0;
-}
-#else
-/* ========================================================================
- * Table of CRC-32's of all single-byte values (made by make_crc_table)
- */
-local const uLongf crc_table[256] = {
-  0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
-  0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
-  0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
-  0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
-  0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
-  0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
-  0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
-  0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
-  0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
-  0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
-  0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
-  0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
-  0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
-  0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
-  0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
-  0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
-  0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
-  0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
-  0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
-  0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
-  0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
-  0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
-  0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
-  0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
-  0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
-  0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
-  0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
-  0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
-  0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
-  0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
-  0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
-  0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
-  0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
-  0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
-  0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
-  0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
-  0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
-  0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
-  0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
-  0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
-  0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
-  0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
-  0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
-  0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
-  0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
-  0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
-  0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
-  0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
-  0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
-  0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
-  0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
-  0x2d02ef8dL
-};
-#endif
-
-/* =========================================================================
- * This function can be used by asm versions of crc32()
- */
-const uLongf * ZEXPORT get_crc_table()
-{
-#ifdef DYNAMIC_CRC_TABLE
-  if (crc_table_empty) make_crc_table();
-#endif
-  return (const uLongf *)crc_table;
-}
-
-/* ========================================================================= */
-#define DO1(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8);
-#define DO2(buf)  DO1(buf); DO1(buf);
-#define DO4(buf)  DO2(buf); DO2(buf);
-#define DO8(buf)  DO4(buf); DO4(buf);
-
-/* ========================================================================= */
-uLong ZEXPORT crc32(crc, buf, len)
-    uLong crc;
-    const Bytef *buf;
-    uInt len;
-{
-    if (buf == Z_NULL) return 0L;
-#ifdef DYNAMIC_CRC_TABLE
-    if (crc_table_empty)
-      make_crc_table();
-#endif
-    crc = crc ^ 0xffffffffL;
-    while (len >= 8)
-    {
-      DO8(buf);
-      len -= 8;
-    }
-    if (len) do {
-      DO1(buf);
-    } while (--len);
-    return crc ^ 0xffffffffL;
-}
diff --git a/Lib/zlib/deflate.c b/Lib/zlib/deflate.c
deleted file mode 100644
index 25d5818e2..000000000
--- a/Lib/zlib/deflate.c
+++ /dev/null
@@ -1,1350 +0,0 @@
-/* deflate.c -- compress data using the deflation algorithm
- * Copyright (C) 1995-1998 Jean-loup Gailly.
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/*
- *  ALGORITHM
- *
- *      The "deflation" process depends on being able to identify portions
- *      of the input text which are identical to earlier input (within a
- *      sliding window trailing behind the input currently being processed).
- *
- *      The most straightforward technique turns out to be the fastest for
- *      most input files: try all possible matches and select the longest.
- *      The key feature of this algorithm is that insertions into the string
- *      dictionary are very simple and thus fast, and deletions are avoided
- *      completely. Insertions are performed at each input character, whereas
- *      string matches are performed only when the previous match ends. So it
- *      is preferable to spend more time in matches to allow very fast string
- *      insertions and avoid deletions. The matching algorithm for small
- *      strings is inspired from that of Rabin & Karp. A brute force approach
- *      is used to find longer strings when a small match has been found.
- *      A similar algorithm is used in comic (by Jan-Mark Wams) and freeze
- *      (by Leonid Broukhis).
- *         A previous version of this file used a more sophisticated algorithm
- *      (by Fiala and Greene) which is guaranteed to run in linear amortized
- *      time, but has a larger average cost, uses more memory and is patented.
- *      However the F&G algorithm may be faster for some highly redundant
- *      files if the parameter max_chain_length (described below) is too large.
- *
- *  ACKNOWLEDGEMENTS
- *
- *      The idea of lazy evaluation of matches is due to Jan-Mark Wams, and
- *      I found it in 'freeze' written by Leonid Broukhis.
- *      Thanks to many people for bug reports and testing.
- *
- *  REFERENCES
- *
- *      Deutsch, L.P.,"DEFLATE Compressed Data Format Specification".
- *      Available in ftp://ds.internic.net/rfc/rfc1951.txt
- *
- *      A description of the Rabin and Karp algorithm is given in the book
- *         "Algorithms" by R. Sedgewick, Addison-Wesley, p252.
- *
- *      Fiala,E.R., and Greene,D.H.
- *         Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595
- *
- */
-
-/* @(#) $Id$ */
-
-#include "deflate.h"
-
-const char deflate_copyright[] =
-   " deflate 1.1.3 Copyright 1995-1998 Jean-loup Gailly ";
-/*
-  If you use the zlib library in a product, an acknowledgment is welcome
-  in the documentation of your product. If for some reason you cannot
-  include such an acknowledgment, I would appreciate that you keep this
-  copyright string in the executable of your product.
- */
-
-/* ===========================================================================
- *  Function prototypes.
- */
-typedef enum {
-    need_more,      /* block not completed, need more input or more output */
-    block_done,     /* block flush performed */
-    finish_started, /* finish started, need only more output at next deflate */
-    finish_done     /* finish done, accept no more input or output */
-} block_state;
-
-typedef block_state (*compress_func) OF((deflate_state *s, int flush));
-/* Compression function. Returns the block state after the call. */
-
-local void fill_window    OF((deflate_state *s));
-local block_state deflate_stored OF((deflate_state *s, int flush));
-local block_state deflate_fast   OF((deflate_state *s, int flush));
-local block_state deflate_slow   OF((deflate_state *s, int flush));
-local void lm_init        OF((deflate_state *s));
-local void putShortMSB    OF((deflate_state *s, uInt b));
-local void flush_pending  OF((z_streamp strm));
-local int read_buf        OF((z_streamp strm, Bytef *buf, unsigned size));
-#ifdef ASMV
-      void match_init OF((void)); /* asm code initialization */
-      uInt longest_match  OF((deflate_state *s, IPos cur_match));
-#else
-local uInt longest_match  OF((deflate_state *s, IPos cur_match));
-#endif
-
-#ifdef DEBUG
-local  void check_match OF((deflate_state *s, IPos start, IPos match,
-                            int length));
-#endif
-
-/* ===========================================================================
- * Local data
- */
-
-#define NIL 0
-/* Tail of hash chains */
-
-#ifndef TOO_FAR
-#  define TOO_FAR 4096
-#endif
-/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */
-
-#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
-/* Minimum amount of lookahead, except at the end of the input file.
- * See deflate.c for comments about the MIN_MATCH+1.
- */
-
-/* Values for max_lazy_match, good_match and max_chain_length, depending on
- * the desired pack level (0..9). The values given below have been tuned to
- * exclude worst case performance for pathological files. Better values may be
- * found for specific files.
- */
-typedef struct config_s {
-   ush good_length; /* reduce lazy search above this match length */
-   ush max_lazy;    /* do not perform lazy search above this match length */
-   ush nice_length; /* quit search above this match length */
-   ush max_chain;
-   compress_func func;
-} config;
-
-local const config configuration_table[10] = {
-/*      good lazy nice chain */
-/* 0 */ {0,    0,  0,    0, deflate_stored},  /* store only */
-/* 1 */ {4,    4,  8,    4, deflate_fast}, /* maximum speed, no lazy matches */
-/* 2 */ {4,    5, 16,    8, deflate_fast},
-/* 3 */ {4,    6, 32,   32, deflate_fast},
-
-/* 4 */ {4,    4, 16,   16, deflate_slow},  /* lazy matches */
-/* 5 */ {8,   16, 32,   32, deflate_slow},
-/* 6 */ {8,   16, 128, 128, deflate_slow},
-/* 7 */ {8,   32, 128, 256, deflate_slow},
-/* 8 */ {32, 128, 258, 1024, deflate_slow},
-/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* maximum compression */
-
-/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4
- * For deflate_fast() (levels <= 3) good is ignored and lazy has a different
- * meaning.
- */
-
-#define EQUAL 0
-/* result of memcmp for equal strings */
-
-struct static_tree_desc_s {int dummy;}; /* for buggy compilers */
-
-/* ===========================================================================
- * Update a hash value with the given input byte
- * IN  assertion: all calls to to UPDATE_HASH are made with consecutive
- *    input characters, so that a running hash key can be computed from the
- *    previous key instead of complete recalculation each time.
- */
-#define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask)
-
-
-/* ===========================================================================
- * Insert string str in the dictionary and set match_head to the previous head
- * of the hash chain (the most recent string with same hash key). Return
- * the previous length of the hash chain.
- * If this file is compiled with -DFASTEST, the compression level is forced
- * to 1, and no hash chains are maintained.
- * IN  assertion: all calls to to INSERT_STRING are made with consecutive
- *    input characters and the first MIN_MATCH bytes of str are valid
- *    (except for the last MIN_MATCH-1 bytes of the input file).
- */
-#ifdef FASTEST
-#define INSERT_STRING(s, str, match_head) \
-   (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
-    match_head = s->head[s->ins_h], \
-    s->head[s->ins_h] = (Pos)(str))
-#else
-#define INSERT_STRING(s, str, match_head) \
-   (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
-    s->prev[(str) & s->w_mask] = match_head = s->head[s->ins_h], \
-    s->head[s->ins_h] = (Pos)(str))
-#endif
-
-/* ===========================================================================
- * Initialize the hash table (avoiding 64K overflow for 16 bit systems).
- * prev[] will be initialized on the fly.
- */
-#define CLEAR_HASH(s) \
-    s->head[s->hash_size-1] = NIL; \
-    zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head));
-
-/* ========================================================================= */
-int ZEXPORT deflateInit_(strm, level, version, stream_size)
-    z_streamp strm;
-    int level;
-    const char *version;
-    int stream_size;
-{
-    return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL,
-			 Z_DEFAULT_STRATEGY, version, stream_size);
-    /* To do: ignore strm->next_in if we use it as window */
-}
-
-/* ========================================================================= */
-int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
-		  version, stream_size)
-    z_streamp strm;
-    int  level;
-    int  method;
-    int  windowBits;
-    int  memLevel;
-    int  strategy;
-    const char *version;
-    int stream_size;
-{
-    deflate_state *s;
-    int noheader = 0;
-    static const char* my_version = ZLIB_VERSION;
-
-    ushf *overlay;
-    /* We overlay pending_buf and d_buf+l_buf. This works since the average
-     * output size for (length,distance) codes is <= 24 bits.
-     */
-
-    if (version == Z_NULL || version[0] != my_version[0] ||
-        stream_size != sizeof(z_stream)) {
-	return Z_VERSION_ERROR;
-    }
-    if (strm == Z_NULL) return Z_STREAM_ERROR;
-
-    strm->msg = Z_NULL;
-    if (strm->zalloc == Z_NULL) {
-	strm->zalloc = zcalloc;
-	strm->opaque = (voidpf)0;
-    }
-    if (strm->zfree == Z_NULL) strm->zfree = zcfree;
-
-    if (level == Z_DEFAULT_COMPRESSION) level = 6;
-#ifdef FASTEST
-    level = 1;
-#endif
-
-    if (windowBits < 0) { /* undocumented feature: suppress zlib header */
-        noheader = 1;
-        windowBits = -windowBits;
-    }
-    if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED ||
-        windowBits < 8 || windowBits > 15 || level < 0 || level > 9 ||
-	strategy < 0 || strategy > Z_HUFFMAN_ONLY) {
-        return Z_STREAM_ERROR;
-    }
-    s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state));
-    if (s == Z_NULL) return Z_MEM_ERROR;
-    strm->state = (struct internal_state FAR *)s;
-    s->strm = strm;
-
-    s->noheader = noheader;
-    s->w_bits = windowBits;
-    s->w_size = 1 << s->w_bits;
-    s->w_mask = s->w_size - 1;
-
-    s->hash_bits = memLevel + 7;
-    s->hash_size = 1 << s->hash_bits;
-    s->hash_mask = s->hash_size - 1;
-    s->hash_shift =  ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH);
-
-    s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte));
-    s->prev   = (Posf *)  ZALLOC(strm, s->w_size, sizeof(Pos));
-    s->head   = (Posf *)  ZALLOC(strm, s->hash_size, sizeof(Pos));
-
-    s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
-
-    overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2);
-    s->pending_buf = (uchf *) overlay;
-    s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L);
-
-    if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
-        s->pending_buf == Z_NULL) {
-        strm->msg = (char*)ERR_MSG(Z_MEM_ERROR);
-        deflateEnd (strm);
-        return Z_MEM_ERROR;
-    }
-    s->d_buf = overlay + s->lit_bufsize/sizeof(ush);
-    s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize;
-
-    s->level = level;
-    s->strategy = strategy;
-    s->method = (Byte)method;
-
-    return deflateReset(strm);
-}
-
-/* ========================================================================= */
-int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength)
-    z_streamp strm;
-    const Bytef *dictionary;
-    uInt  dictLength;
-{
-    deflate_state *s;
-    uInt length = dictLength;
-    uInt n;
-    IPos hash_head = 0;
-
-    if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL ||
-        strm->state->status != INIT_STATE) return Z_STREAM_ERROR;
-
-    s = strm->state;
-    strm->adler = adler32(strm->adler, dictionary, dictLength);
-
-    if (length < MIN_MATCH) return Z_OK;
-    if (length > MAX_DIST(s)) {
-	length = MAX_DIST(s);
-#ifndef USE_DICT_HEAD
-	dictionary += dictLength - length; /* use the tail of the dictionary */
-#endif
-    }
-    zmemcpy(s->window, dictionary, length);
-    s->strstart = length;
-    s->block_start = (long)length;
-
-    /* Insert all strings in the hash table (except for the last two bytes).
-     * s->lookahead stays null, so s->ins_h will be recomputed at the next
-     * call of fill_window.
-     */
-    s->ins_h = s->window[0];
-    UPDATE_HASH(s, s->ins_h, s->window[1]);
-    for (n = 0; n <= length - MIN_MATCH; n++) {
-	INSERT_STRING(s, n, hash_head);
-    }
-    if (hash_head) hash_head = 0;  /* to make compiler happy */
-    return Z_OK;
-}
-
-/* ========================================================================= */
-int ZEXPORT deflateReset (strm)
-    z_streamp strm;
-{
-    deflate_state *s;
-    
-    if (strm == Z_NULL || strm->state == Z_NULL ||
-        strm->zalloc == Z_NULL || strm->zfree == Z_NULL) return Z_STREAM_ERROR;
-
-    strm->total_in = strm->total_out = 0;
-    strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */
-    strm->data_type = Z_UNKNOWN;
-
-    s = (deflate_state *)strm->state;
-    s->pending = 0;
-    s->pending_out = s->pending_buf;
-
-    if (s->noheader < 0) {
-        s->noheader = 0; /* was set to -1 by deflate(..., Z_FINISH); */
-    }
-    s->status = s->noheader ? BUSY_STATE : INIT_STATE;
-    strm->adler = 1;
-    s->last_flush = Z_NO_FLUSH;
-
-    _tr_init(s);
-    lm_init(s);
-
-    return Z_OK;
-}
-
-/* ========================================================================= */
-int ZEXPORT deflateParams(strm, level, strategy)
-    z_streamp strm;
-    int level;
-    int strategy;
-{
-    deflate_state *s;
-    compress_func func;
-    int err = Z_OK;
-
-    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
-    s = strm->state;
-
-    if (level == Z_DEFAULT_COMPRESSION) {
-	level = 6;
-    }
-    if (level < 0 || level > 9 || strategy < 0 || strategy > Z_HUFFMAN_ONLY) {
-	return Z_STREAM_ERROR;
-    }
-    func = configuration_table[s->level].func;
-
-    if (func != configuration_table[level].func && strm->total_in != 0) {
-	/* Flush the last buffer: */
-	err = deflate(strm, Z_PARTIAL_FLUSH);
-    }
-    if (s->level != level) {
-	s->level = level;
-	s->max_lazy_match   = configuration_table[level].max_lazy;
-	s->good_match       = configuration_table[level].good_length;
-	s->nice_match       = configuration_table[level].nice_length;
-	s->max_chain_length = configuration_table[level].max_chain;
-    }
-    s->strategy = strategy;
-    return err;
-}
-
-/* =========================================================================
- * Put a short in the pending buffer. The 16-bit value is put in MSB order.
- * IN assertion: the stream state is correct and there is enough room in
- * pending_buf.
- */
-local void putShortMSB (s, b)
-    deflate_state *s;
-    uInt b;
-{
-    put_byte(s, (Byte)(b >> 8));
-    put_byte(s, (Byte)(b & 0xff));
-}   
-
-/* =========================================================================
- * Flush as much pending output as possible. All deflate() output goes
- * through this function so some applications may wish to modify it
- * to avoid allocating a large strm->next_out buffer and copying into it.
- * (See also read_buf()).
- */
-local void flush_pending(strm)
-    z_streamp strm;
-{
-    unsigned len = strm->state->pending;
-
-    if (len > strm->avail_out) len = strm->avail_out;
-    if (len == 0) return;
-
-    zmemcpy(strm->next_out, strm->state->pending_out, len);
-    strm->next_out  += len;
-    strm->state->pending_out  += len;
-    strm->total_out += len;
-    strm->avail_out  -= len;
-    strm->state->pending -= len;
-    if (strm->state->pending == 0) {
-        strm->state->pending_out = strm->state->pending_buf;
-    }
-}
-
-/* ========================================================================= */
-int ZEXPORT deflate (strm, flush)
-    z_streamp strm;
-    int flush;
-{
-    int old_flush; /* value of flush param for previous deflate call */
-    deflate_state *s;
-
-    if (strm == Z_NULL || strm->state == Z_NULL ||
-	flush > Z_FINISH || flush < 0) {
-        return Z_STREAM_ERROR;
-    }
-    s = strm->state;
-
-    if (strm->next_out == Z_NULL ||
-        (strm->next_in == Z_NULL && strm->avail_in != 0) ||
-	(s->status == FINISH_STATE && flush != Z_FINISH)) {
-        ERR_RETURN(strm, Z_STREAM_ERROR);
-    }
-    if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR);
-
-    s->strm = strm; /* just in case */
-    old_flush = s->last_flush;
-    s->last_flush = flush;
-
-    /* Write the zlib header */
-    if (s->status == INIT_STATE) {
-
-        uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8;
-        uInt level_flags = (s->level-1) >> 1;
-
-        if (level_flags > 3) level_flags = 3;
-        header |= (level_flags << 6);
-	if (s->strstart != 0) header |= PRESET_DICT;
-        header += 31 - (header % 31);
-
-        s->status = BUSY_STATE;
-        putShortMSB(s, header);
-
-	/* Save the adler32 of the preset dictionary: */
-	if (s->strstart != 0) {
-	    putShortMSB(s, (uInt)(strm->adler >> 16));
-	    putShortMSB(s, (uInt)(strm->adler & 0xffff));
-	}
-	strm->adler = 1L;
-    }
-
-    /* Flush as much pending output as possible */
-    if (s->pending != 0) {
-        flush_pending(strm);
-        if (strm->avail_out == 0) {
-	    /* Since avail_out is 0, deflate will be called again with
-	     * more output space, but possibly with both pending and
-	     * avail_in equal to zero. There won't be anything to do,
-	     * but this is not an error situation so make sure we
-	     * return OK instead of BUF_ERROR at next call of deflate:
-             */
-	    s->last_flush = -1;
-	    return Z_OK;
-	}
-
-    /* Make sure there is something to do and avoid duplicate consecutive
-     * flushes. For repeated and useless calls with Z_FINISH, we keep
-     * returning Z_STREAM_END instead of Z_BUFF_ERROR.
-     */
-    } else if (strm->avail_in == 0 && flush <= old_flush &&
-	       flush != Z_FINISH) {
-        ERR_RETURN(strm, Z_BUF_ERROR);
-    }
-
-    /* User must not provide more input after the first FINISH: */
-    if (s->status == FINISH_STATE && strm->avail_in != 0) {
-        ERR_RETURN(strm, Z_BUF_ERROR);
-    }
-
-    /* Start a new block or continue the current one.
-     */
-    if (strm->avail_in != 0 || s->lookahead != 0 ||
-        (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) {
-        block_state bstate;
-
-	bstate = (*(configuration_table[s->level].func))(s, flush);
-
-        if (bstate == finish_started || bstate == finish_done) {
-            s->status = FINISH_STATE;
-        }
-        if (bstate == need_more || bstate == finish_started) {
-	    if (strm->avail_out == 0) {
-	        s->last_flush = -1; /* avoid BUF_ERROR next call, see above */
-	    }
-	    return Z_OK;
-	    /* If flush != Z_NO_FLUSH && avail_out == 0, the next call
-	     * of deflate should use the same flush parameter to make sure
-	     * that the flush is complete. So we don't have to output an
-	     * empty block here, this will be done at next call. This also
-	     * ensures that for a very small output buffer, we emit at most
-	     * one empty block.
-	     */
-	}
-        if (bstate == block_done) {
-            if (flush == Z_PARTIAL_FLUSH) {
-                _tr_align(s);
-            } else { /* FULL_FLUSH or SYNC_FLUSH */
-                _tr_stored_block(s, (char*)0, 0L, 0);
-                /* For a full flush, this empty block will be recognized
-                 * as a special marker by inflate_sync().
-                 */
-                if (flush == Z_FULL_FLUSH) {
-                    CLEAR_HASH(s);             /* forget history */
-                }
-            }
-            flush_pending(strm);
-	    if (strm->avail_out == 0) {
-	      s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */
-	      return Z_OK;
-	    }
-        }
-    }
-    Assert(strm->avail_out > 0, "bug2");
-
-    if (flush != Z_FINISH) return Z_OK;
-    if (s->noheader) return Z_STREAM_END;
-
-    /* Write the zlib trailer (adler32) */
-    putShortMSB(s, (uInt)(strm->adler >> 16));
-    putShortMSB(s, (uInt)(strm->adler & 0xffff));
-    flush_pending(strm);
-    /* If avail_out is zero, the application will call deflate again
-     * to flush the rest.
-     */
-    s->noheader = -1; /* write the trailer only once! */
-    return s->pending != 0 ? Z_OK : Z_STREAM_END;
-}
-
-/* ========================================================================= */
-int ZEXPORT deflateEnd (strm)
-    z_streamp strm;
-{
-    int status;
-
-    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
-
-    status = strm->state->status;
-    if (status != INIT_STATE && status != BUSY_STATE &&
-	status != FINISH_STATE) {
-      return Z_STREAM_ERROR;
-    }
-
-    /* Deallocate in reverse order of allocations: */
-    TRY_FREE(strm, strm->state->pending_buf);
-    TRY_FREE(strm, strm->state->head);
-    TRY_FREE(strm, strm->state->prev);
-    TRY_FREE(strm, strm->state->window);
-
-    ZFREE(strm, strm->state);
-    strm->state = Z_NULL;
-
-    return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;
-}
-
-/* =========================================================================
- * Copy the source state to the destination state.
- * To simplify the source, this is not supported for 16-bit MSDOS (which
- * doesn't have enough memory anyway to duplicate compression states).
- */
-int ZEXPORT deflateCopy (dest, source)
-    z_streamp dest;
-    z_streamp source;
-{
-#ifdef MAXSEG_64K
-    return Z_STREAM_ERROR;
-#else
-    deflate_state *ds;
-    deflate_state *ss;
-    ushf *overlay;
-
-
-    if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) {
-        return Z_STREAM_ERROR;
-    }
-
-    ss = source->state;
-
-    *dest = *source;
-
-    ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state));
-    if (ds == Z_NULL) return Z_MEM_ERROR;
-    dest->state = (struct internal_state FAR *) ds;
-    *ds = *ss;
-    ds->strm = dest;
-
-    ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
-    ds->prev   = (Posf *)  ZALLOC(dest, ds->w_size, sizeof(Pos));
-    ds->head   = (Posf *)  ZALLOC(dest, ds->hash_size, sizeof(Pos));
-    overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2);
-    ds->pending_buf = (uchf *) overlay;
-
-    if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL ||
-        ds->pending_buf == Z_NULL) {
-        deflateEnd (dest);
-        return Z_MEM_ERROR;
-    }
-    /* following zmemcpy do not work for 16-bit MSDOS */
-    zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte));
-    zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos));
-    zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos));
-    zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);
-
-    ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
-    ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush);
-    ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize;
-
-    ds->l_desc.dyn_tree = ds->dyn_ltree;
-    ds->d_desc.dyn_tree = ds->dyn_dtree;
-    ds->bl_desc.dyn_tree = ds->bl_tree;
-
-    return Z_OK;
-#endif
-}
-
-/* ===========================================================================
- * Read a new buffer from the current input stream, update the adler32
- * and total number of bytes read.  All deflate() input goes through
- * this function so some applications may wish to modify it to avoid
- * allocating a large strm->next_in buffer and copying from it.
- * (See also flush_pending()).
- */
-local int read_buf(strm, buf, size)
-    z_streamp strm;
-    Bytef *buf;
-    unsigned size;
-{
-    unsigned len = strm->avail_in;
-
-    if (len > size) len = size;
-    if (len == 0) return 0;
-
-    strm->avail_in  -= len;
-
-    if (!strm->state->noheader) {
-        strm->adler = adler32(strm->adler, strm->next_in, len);
-    }
-    zmemcpy(buf, strm->next_in, len);
-    strm->next_in  += len;
-    strm->total_in += len;
-
-    return (int)len;
-}
-
-/* ===========================================================================
- * Initialize the "longest match" routines for a new zlib stream
- */
-local void lm_init (s)
-    deflate_state *s;
-{
-    s->window_size = (ulg)2L*s->w_size;
-
-    CLEAR_HASH(s);
-
-    /* Set the default configuration parameters:
-     */
-    s->max_lazy_match   = configuration_table[s->level].max_lazy;
-    s->good_match       = configuration_table[s->level].good_length;
-    s->nice_match       = configuration_table[s->level].nice_length;
-    s->max_chain_length = configuration_table[s->level].max_chain;
-
-    s->strstart = 0;
-    s->block_start = 0L;
-    s->lookahead = 0;
-    s->match_length = s->prev_length = MIN_MATCH-1;
-    s->match_available = 0;
-    s->ins_h = 0;
-#ifdef ASMV
-    match_init(); /* initialize the asm code */
-#endif
-}
-
-/* ===========================================================================
- * Set match_start to the longest match starting at the given string and
- * return its length. Matches shorter or equal to prev_length are discarded,
- * in which case the result is equal to prev_length and match_start is
- * garbage.
- * IN assertions: cur_match is the head of the hash chain for the current
- *   string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
- * OUT assertion: the match length is not greater than s->lookahead.
- */
-#ifndef ASMV
-/* For 80x86 and 680x0, an optimized version will be provided in match.asm or
- * match.S. The code will be functionally equivalent.
- */
-#ifndef FASTEST
-local uInt longest_match(s, cur_match)
-    deflate_state *s;
-    IPos cur_match;                             /* current match */
-{
-    unsigned chain_length = s->max_chain_length;/* max hash chain length */
-    register Bytef *scan = s->window + s->strstart; /* current string */
-    register Bytef *match;                       /* matched string */
-    register int len;                           /* length of current match */
-    int best_len = s->prev_length;              /* best match length so far */
-    int nice_match = s->nice_match;             /* stop if match long enough */
-    IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
-        s->strstart - (IPos)MAX_DIST(s) : NIL;
-    /* Stop when cur_match becomes <= limit. To simplify the code,
-     * we prevent matches with the string of window index 0.
-     */
-    Posf *prev = s->prev;
-    uInt wmask = s->w_mask;
-
-#ifdef UNALIGNED_OK
-    /* Compare two bytes at a time. Note: this is not always beneficial.
-     * Try with and without -DUNALIGNED_OK to check.
-     */
-    register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1;
-    register ush scan_start = *(ushf*)scan;
-    register ush scan_end   = *(ushf*)(scan+best_len-1);
-#else
-    register Bytef *strend = s->window + s->strstart + MAX_MATCH;
-    register Byte scan_end1  = scan[best_len-1];
-    register Byte scan_end   = scan[best_len];
-#endif
-
-    /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
-     * It is easy to get rid of this optimization if necessary.
-     */
-    Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
-
-    /* Do not waste too much time if we already have a good match: */
-    if (s->prev_length >= s->good_match) {
-        chain_length >>= 2;
-    }
-    /* Do not look for matches beyond the end of the input. This is necessary
-     * to make deflate deterministic.
-     */
-    if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
-
-    Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
-
-    do {
-        Assert(cur_match < s->strstart, "no future");
-        match = s->window + cur_match;
-
-        /* Skip to next match if the match length cannot increase
-         * or if the match length is less than 2:
-         */
-#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
-        /* This code assumes sizeof(unsigned short) == 2. Do not use
-         * UNALIGNED_OK if your compiler uses a different size.
-         */
-        if (*(ushf*)(match+best_len-1) != scan_end ||
-            *(ushf*)match != scan_start) continue;
-
-        /* It is not necessary to compare scan[2] and match[2] since they are
-         * always equal when the other bytes match, given that the hash keys
-         * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at
-         * strstart+3, +5, ... up to strstart+257. We check for insufficient
-         * lookahead only every 4th comparison; the 128th check will be made
-         * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is
-         * necessary to put more guard bytes at the end of the window, or
-         * to check more often for insufficient lookahead.
-         */
-        Assert(scan[2] == match[2], "scan[2]?");
-        scan++, match++;
-        do {
-        } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
-                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
-                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
-                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
-                 scan < strend);
-        /* The funny "do {}" generates better code on most compilers */
-
-        /* Here, scan <= window+strstart+257 */
-        Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
-        if (*scan == *match) scan++;
-
-        len = (MAX_MATCH - 1) - (int)(strend-scan);
-        scan = strend - (MAX_MATCH-1);
-
-#else /* UNALIGNED_OK */
-
-        if (match[best_len]   != scan_end  ||
-            match[best_len-1] != scan_end1 ||
-            *match            != *scan     ||
-            *++match          != scan[1])      continue;
-
-        /* The check at best_len-1 can be removed because it will be made
-         * again later. (This heuristic is not always a win.)
-         * It is not necessary to compare scan[2] and match[2] since they
-         * are always equal when the other bytes match, given that
-         * the hash keys are equal and that HASH_BITS >= 8.
-         */
-        scan += 2, match++;
-        Assert(*scan == *match, "match[2]?");
-
-        /* We check for insufficient lookahead only every 8th comparison;
-         * the 256th check will be made at strstart+258.
-         */
-        do {
-        } while (*++scan == *++match && *++scan == *++match &&
-                 *++scan == *++match && *++scan == *++match &&
-                 *++scan == *++match && *++scan == *++match &&
-                 *++scan == *++match && *++scan == *++match &&
-                 scan < strend);
-
-        Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
-
-        len = MAX_MATCH - (int)(strend - scan);
-        scan = strend - MAX_MATCH;
-
-#endif /* UNALIGNED_OK */
-
-        if (len > best_len) {
-            s->match_start = cur_match;
-            best_len = len;
-            if (len >= nice_match) break;
-#ifdef UNALIGNED_OK
-            scan_end = *(ushf*)(scan+best_len-1);
-#else
-            scan_end1  = scan[best_len-1];
-            scan_end   = scan[best_len];
-#endif
-        }
-    } while ((cur_match = prev[cur_match & wmask]) > limit
-             && --chain_length != 0);
-
-    if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
-    return s->lookahead;
-}
-
-#else /* FASTEST */
-/* ---------------------------------------------------------------------------
- * Optimized version for level == 1 only
- */
-local uInt longest_match(s, cur_match)
-    deflate_state *s;
-    IPos cur_match;                             /* current match */
-{
-    register Bytef *scan = s->window + s->strstart; /* current string */
-    register Bytef *match;                       /* matched string */
-    register int len;                           /* length of current match */
-    register Bytef *strend = s->window + s->strstart + MAX_MATCH;
-
-    /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
-     * It is easy to get rid of this optimization if necessary.
-     */
-    Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
-
-    Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
-
-    Assert(cur_match < s->strstart, "no future");
-
-    match = s->window + cur_match;
-
-    /* Return failure if the match length is less than 2:
-     */
-    if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1;
-
-    /* The check at best_len-1 can be removed because it will be made
-     * again later. (This heuristic is not always a win.)
-     * It is not necessary to compare scan[2] and match[2] since they
-     * are always equal when the other bytes match, given that
-     * the hash keys are equal and that HASH_BITS >= 8.
-     */
-    scan += 2, match += 2;
-    Assert(*scan == *match, "match[2]?");
-
-    /* We check for insufficient lookahead only every 8th comparison;
-     * the 256th check will be made at strstart+258.
-     */
-    do {
-    } while (*++scan == *++match && *++scan == *++match &&
-	     *++scan == *++match && *++scan == *++match &&
-	     *++scan == *++match && *++scan == *++match &&
-	     *++scan == *++match && *++scan == *++match &&
-	     scan < strend);
-
-    Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
-
-    len = MAX_MATCH - (int)(strend - scan);
-
-    if (len < MIN_MATCH) return MIN_MATCH - 1;
-
-    s->match_start = cur_match;
-    return len <= s->lookahead ? len : s->lookahead;
-}
-#endif /* FASTEST */
-#endif /* ASMV */
-
-#ifdef DEBUG
-/* ===========================================================================
- * Check that the match at match_start is indeed a match.
- */
-local void check_match(s, start, match, length)
-    deflate_state *s;
-    IPos start, match;
-    int length;
-{
-    /* check that the match is indeed a match */
-    if (zmemcmp(s->window + match,
-                s->window + start, length) != EQUAL) {
-        fprintf(stderr, " start %u, match %u, length %d\n",
-		start, match, length);
-        do {
-	    fprintf(stderr, "%c%c", s->window[match++], s->window[start++]);
-	} while (--length != 0);
-        z_error("invalid match");
-    }
-    if (z_verbose > 1) {
-        fprintf(stderr,"\\[%d,%d]", start-match, length);
-        do { putc(s->window[start++], stderr); } while (--length != 0);
-    }
-}
-#else
-#  define check_match(s, start, match, length)
-#endif
-
-/* ===========================================================================
- * Fill the window when the lookahead becomes insufficient.
- * Updates strstart and lookahead.
- *
- * IN assertion: lookahead < MIN_LOOKAHEAD
- * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
- *    At least one byte has been read, or avail_in == 0; reads are
- *    performed for at least two bytes (required for the zip translate_eol
- *    option -- not supported here).
- */
-local void fill_window(s)
-    deflate_state *s;
-{
-    register unsigned n, m;
-    register Posf *p;
-    unsigned more;    /* Amount of free space at the end of the window. */
-    uInt wsize = s->w_size;
-
-    do {
-        more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart);
-
-        /* Deal with !@#$% 64K limit: */
-        if (more == 0 && s->strstart == 0 && s->lookahead == 0) {
-            more = wsize;
-
-        } else if (more == (unsigned)(-1)) {
-            /* Very unlikely, but possible on 16 bit machine if strstart == 0
-             * and lookahead == 1 (input done one byte at time)
-             */
-            more--;
-
-        /* If the window is almost full and there is insufficient lookahead,
-         * move the upper half to the lower one to make room in the upper half.
-         */
-        } else if (s->strstart >= wsize+MAX_DIST(s)) {
-
-            zmemcpy(s->window, s->window+wsize, (unsigned)wsize);
-            s->match_start -= wsize;
-            s->strstart    -= wsize; /* we now have strstart >= MAX_DIST */
-            s->block_start -= (long) wsize;
-
-            /* Slide the hash table (could be avoided with 32 bit values
-               at the expense of memory usage). We slide even when level == 0
-               to keep the hash table consistent if we switch back to level > 0
-               later. (Using level 0 permanently is not an optimal usage of
-               zlib, so we don't care about this pathological case.)
-             */
-	    n = s->hash_size;
-	    p = &s->head[n];
-	    do {
-		m = *--p;
-		*p = (Pos)(m >= wsize ? m-wsize : NIL);
-	    } while (--n);
-
-	    n = wsize;
-#ifndef FASTEST
-	    p = &s->prev[n];
-	    do {
-		m = *--p;
-		*p = (Pos)(m >= wsize ? m-wsize : NIL);
-		/* If n is not on any hash chain, prev[n] is garbage but
-		 * its value will never be used.
-		 */
-	    } while (--n);
-#endif
-            more += wsize;
-        }
-        if (s->strm->avail_in == 0) return;
-
-        /* If there was no sliding:
-         *    strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
-         *    more == window_size - lookahead - strstart
-         * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
-         * => more >= window_size - 2*WSIZE + 2
-         * In the BIG_MEM or MMAP case (not yet supported),
-         *   window_size == input_size + MIN_LOOKAHEAD  &&
-         *   strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
-         * Otherwise, window_size == 2*WSIZE so more >= 2.
-         * If there was sliding, more >= WSIZE. So in all cases, more >= 2.
-         */
-        Assert(more >= 2, "more < 2");
-
-        n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more);
-        s->lookahead += n;
-
-        /* Initialize the hash value now that we have some input: */
-        if (s->lookahead >= MIN_MATCH) {
-            s->ins_h = s->window[s->strstart];
-            UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
-#if MIN_MATCH != 3
-            Call UPDATE_HASH() MIN_MATCH-3 more times
-#endif
-        }
-        /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
-         * but this is not important since only literal bytes will be emitted.
-         */
-
-    } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0);
-}
-
-/* ===========================================================================
- * Flush the current block, with given end-of-file flag.
- * IN assertion: strstart is set to the end of the current match.
- */
-#define FLUSH_BLOCK_ONLY(s, eof) { \
-   _tr_flush_block(s, (s->block_start >= 0L ? \
-                   (charf *)&s->window[(unsigned)s->block_start] : \
-                   (charf *)Z_NULL), \
-		(ulg)((long)s->strstart - s->block_start), \
-		(eof)); \
-   s->block_start = s->strstart; \
-   flush_pending(s->strm); \
-   Tracev((stderr,"[FLUSH]")); \
-}
-
-/* Same but force premature exit if necessary. */
-#define FLUSH_BLOCK(s, eof) { \
-   FLUSH_BLOCK_ONLY(s, eof); \
-   if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \
-}
-
-/* ===========================================================================
- * Copy without compression as much as possible from the input stream, return
- * the current block state.
- * This function does not insert new strings in the dictionary since
- * uncompressible data is probably not useful. This function is used
- * only for the level=0 compression option.
- * NOTE: this function should be optimized to avoid extra copying from
- * window to pending_buf.
- */
-local block_state deflate_stored(s, flush)
-    deflate_state *s;
-    int flush;
-{
-    /* Stored blocks are limited to 0xffff bytes, pending_buf is limited
-     * to pending_buf_size, and each stored block has a 5 byte header:
-     */
-    ulg max_block_size = 0xffff;
-    ulg max_start;
-
-    if (max_block_size > s->pending_buf_size - 5) {
-        max_block_size = s->pending_buf_size - 5;
-    }
-
-    /* Copy as much as possible from input to output: */
-    for (;;) {
-        /* Fill the window as much as possible: */
-        if (s->lookahead <= 1) {
-
-            Assert(s->strstart < s->w_size+MAX_DIST(s) ||
-		   s->block_start >= (long)s->w_size, "slide too late");
-
-            fill_window(s);
-            if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more;
-
-            if (s->lookahead == 0) break; /* flush the current block */
-        }
-	Assert(s->block_start >= 0L, "block gone");
-
-	s->strstart += s->lookahead;
-	s->lookahead = 0;
-
-	/* Emit a stored block if pending_buf will be full: */
- 	max_start = s->block_start + max_block_size;
-        if (s->strstart == 0 || (ulg)s->strstart >= max_start) {
-	    /* strstart == 0 is possible when wraparound on 16-bit machine */
-	    s->lookahead = (uInt)(s->strstart - max_start);
-	    s->strstart = (uInt)max_start;
-            FLUSH_BLOCK(s, 0);
-	}
-	/* Flush if we may have to slide, otherwise block_start may become
-         * negative and the data will be gone:
-         */
-        if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) {
-            FLUSH_BLOCK(s, 0);
-	}
-    }
-    FLUSH_BLOCK(s, flush == Z_FINISH);
-    return flush == Z_FINISH ? finish_done : block_done;
-}
-
-/* ===========================================================================
- * Compress as much as possible from the input stream, return the current
- * block state.
- * This function does not perform lazy evaluation of matches and inserts
- * new strings in the dictionary only for unmatched strings or for short
- * matches. It is used only for the fast compression options.
- */
-local block_state deflate_fast(s, flush)
-    deflate_state *s;
-    int flush;
-{
-    IPos hash_head = NIL; /* head of the hash chain */
-    int bflush;           /* set if current block must be flushed */
-
-    for (;;) {
-        /* Make sure that we always have enough lookahead, except
-         * at the end of the input file. We need MAX_MATCH bytes
-         * for the next match, plus MIN_MATCH bytes to insert the
-         * string following the next match.
-         */
-        if (s->lookahead < MIN_LOOKAHEAD) {
-            fill_window(s);
-            if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
-	        return need_more;
-	    }
-            if (s->lookahead == 0) break; /* flush the current block */
-        }
-
-        /* Insert the string window[strstart .. strstart+2] in the
-         * dictionary, and set hash_head to the head of the hash chain:
-         */
-        if (s->lookahead >= MIN_MATCH) {
-            INSERT_STRING(s, s->strstart, hash_head);
-        }
-
-        /* Find the longest match, discarding those <= prev_length.
-         * At this point we have always match_length < MIN_MATCH
-         */
-        if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) {
-            /* To simplify the code, we prevent matches with the string
-             * of window index 0 (in particular we have to avoid a match
-             * of the string with itself at the start of the input file).
-             */
-            if (s->strategy != Z_HUFFMAN_ONLY) {
-                s->match_length = longest_match (s, hash_head);
-            }
-            /* longest_match() sets match_start */
-        }
-        if (s->match_length >= MIN_MATCH) {
-            check_match(s, s->strstart, s->match_start, s->match_length);
-
-            _tr_tally_dist(s, s->strstart - s->match_start,
-                           s->match_length - MIN_MATCH, bflush);
-
-            s->lookahead -= s->match_length;
-
-            /* Insert new strings in the hash table only if the match length
-             * is not too large. This saves time but degrades compression.
-             */
-#ifndef FASTEST
-            if (s->match_length <= s->max_insert_length &&
-                s->lookahead >= MIN_MATCH) {
-                s->match_length--; /* string at strstart already in hash table */
-                do {
-                    s->strstart++;
-                    INSERT_STRING(s, s->strstart, hash_head);
-                    /* strstart never exceeds WSIZE-MAX_MATCH, so there are
-                     * always MIN_MATCH bytes ahead.
-                     */
-                } while (--s->match_length != 0);
-                s->strstart++; 
-            } else
-#endif
-	    {
-                s->strstart += s->match_length;
-                s->match_length = 0;
-                s->ins_h = s->window[s->strstart];
-                UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
-#if MIN_MATCH != 3
-                Call UPDATE_HASH() MIN_MATCH-3 more times
-#endif
-                /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not
-                 * matter since it will be recomputed at next deflate call.
-                 */
-            }
-        } else {
-            /* No match, output a literal byte */
-            Tracevv((stderr,"%c", s->window[s->strstart]));
-            _tr_tally_lit (s, s->window[s->strstart], bflush);
-            s->lookahead--;
-            s->strstart++; 
-        }
-        if (bflush) FLUSH_BLOCK(s, 0);
-    }
-    FLUSH_BLOCK(s, flush == Z_FINISH);
-    return flush == Z_FINISH ? finish_done : block_done;
-}
-
-/* ===========================================================================
- * Same as above, but achieves better compression. We use a lazy
- * evaluation for matches: a match is finally adopted only if there is
- * no better match at the next window position.
- */
-local block_state deflate_slow(s, flush)
-    deflate_state *s;
-    int flush;
-{
-    IPos hash_head = NIL;    /* head of hash chain */
-    int bflush;              /* set if current block must be flushed */
-
-    /* Process the input block. */
-    for (;;) {
-        /* Make sure that we always have enough lookahead, except
-         * at the end of the input file. We need MAX_MATCH bytes
-         * for the next match, plus MIN_MATCH bytes to insert the
-         * string following the next match.
-         */
-        if (s->lookahead < MIN_LOOKAHEAD) {
-            fill_window(s);
-            if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
-	        return need_more;
-	    }
-            if (s->lookahead == 0) break; /* flush the current block */
-        }
-
-        /* Insert the string window[strstart .. strstart+2] in the
-         * dictionary, and set hash_head to the head of the hash chain:
-         */
-        if (s->lookahead >= MIN_MATCH) {
-            INSERT_STRING(s, s->strstart, hash_head);
-        }
-
-        /* Find the longest match, discarding those <= prev_length.
-         */
-        s->prev_length = s->match_length, s->prev_match = s->match_start;
-        s->match_length = MIN_MATCH-1;
-
-        if (hash_head != NIL && s->prev_length < s->max_lazy_match &&
-            s->strstart - hash_head <= MAX_DIST(s)) {
-            /* To simplify the code, we prevent matches with the string
-             * of window index 0 (in particular we have to avoid a match
-             * of the string with itself at the start of the input file).
-             */
-            if (s->strategy != Z_HUFFMAN_ONLY) {
-                s->match_length = longest_match (s, hash_head);
-            }
-            /* longest_match() sets match_start */
-
-            if (s->match_length <= 5 && (s->strategy == Z_FILTERED ||
-                 (s->match_length == MIN_MATCH &&
-                  s->strstart - s->match_start > TOO_FAR))) {
-
-                /* If prev_match is also MIN_MATCH, match_start is garbage
-                 * but we will ignore the current match anyway.
-                 */
-                s->match_length = MIN_MATCH-1;
-            }
-        }
-        /* If there was a match at the previous step and the current
-         * match is not better, output the previous match:
-         */
-        if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) {
-            uInt max_insert = s->strstart + s->lookahead - MIN_MATCH;
-            /* Do not insert strings in hash table beyond this. */
-
-            check_match(s, s->strstart-1, s->prev_match, s->prev_length);
-
-            _tr_tally_dist(s, s->strstart -1 - s->prev_match,
-			   s->prev_length - MIN_MATCH, bflush);
-
-            /* Insert in hash table all strings up to the end of the match.
-             * strstart-1 and strstart are already inserted. If there is not
-             * enough lookahead, the last two strings are not inserted in
-             * the hash table.
-             */
-            s->lookahead -= s->prev_length-1;
-            s->prev_length -= 2;
-            do {
-                if (++s->strstart <= max_insert) {
-                    INSERT_STRING(s, s->strstart, hash_head);
-                }
-            } while (--s->prev_length != 0);
-            s->match_available = 0;
-            s->match_length = MIN_MATCH-1;
-            s->strstart++;
-
-            if (bflush) FLUSH_BLOCK(s, 0);
-
-        } else if (s->match_available) {
-            /* If there was no match at the previous position, output a
-             * single literal. If there was a match but the current match
-             * is longer, truncate the previous match to a single literal.
-             */
-            Tracevv((stderr,"%c", s->window[s->strstart-1]));
-	    _tr_tally_lit(s, s->window[s->strstart-1], bflush);
-	    if (bflush) {
-                FLUSH_BLOCK_ONLY(s, 0);
-            }
-            s->strstart++;
-            s->lookahead--;
-            if (s->strm->avail_out == 0) return need_more;
-        } else {
-            /* There is no previous match to compare with, wait for
-             * the next step to decide.
-             */
-            s->match_available = 1;
-            s->strstart++;
-            s->lookahead--;
-        }
-    }
-    Assert (flush != Z_NO_FLUSH, "no flush?");
-    if (s->match_available) {
-        Tracevv((stderr,"%c", s->window[s->strstart-1]));
-        _tr_tally_lit(s, s->window[s->strstart-1], bflush);
-        s->match_available = 0;
-    }
-    FLUSH_BLOCK(s, flush == Z_FINISH);
-    return flush == Z_FINISH ? finish_done : block_done;
-}
diff --git a/Lib/zlib/deflate.h b/Lib/zlib/deflate.h
deleted file mode 100644
index 962676da8..000000000
--- a/Lib/zlib/deflate.h
+++ /dev/null
@@ -1,318 +0,0 @@
-/* deflate.h -- internal compression state
- * Copyright (C) 1995-1998 Jean-loup Gailly
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-/* @(#) $Id$ */
-
-#ifndef _DEFLATE_H
-#define _DEFLATE_H
-
-#include "zutil.h"
-
-/* ===========================================================================
- * Internal compression state.
- */
-
-#define LENGTH_CODES 29
-/* number of length codes, not counting the special END_BLOCK code */
-
-#define LITERALS  256
-/* number of literal bytes 0..255 */
-
-#define L_CODES (LITERALS+1+LENGTH_CODES)
-/* number of Literal or Length codes, including the END_BLOCK code */
-
-#define D_CODES   30
-/* number of distance codes */
-
-#define BL_CODES  19
-/* number of codes used to transfer the bit lengths */
-
-#define HEAP_SIZE (2*L_CODES+1)
-/* maximum heap size */
-
-#define MAX_BITS 15
-/* All codes must not exceed MAX_BITS bits */
-
-#define INIT_STATE    42
-#define BUSY_STATE   113
-#define FINISH_STATE 666
-/* Stream status */
-
-
-/* Data structure describing a single value and its code string. */
-typedef struct ct_data_s {
-    union {
-        ush  freq;       /* frequency count */
-        ush  code;       /* bit string */
-    } fc;
-    union {
-        ush  dad;        /* father node in Huffman tree */
-        ush  len;        /* length of bit string */
-    } dl;
-} FAR ct_data;
-
-#define Freq fc.freq
-#define Code fc.code
-#define Dad  dl.dad
-#define Len  dl.len
-
-typedef struct static_tree_desc_s  static_tree_desc;
-
-typedef struct tree_desc_s {
-    ct_data *dyn_tree;           /* the dynamic tree */
-    int     max_code;            /* largest code with non zero frequency */
-    static_tree_desc *stat_desc; /* the corresponding static tree */
-} FAR tree_desc;
-
-typedef ush Pos;
-typedef Pos FAR Posf;
-typedef unsigned IPos;
-
-/* A Pos is an index in the character window. We use short instead of int to
- * save space in the various tables. IPos is used only for parameter passing.
- */
-
-typedef struct internal_state {
-    z_streamp strm;      /* pointer back to this zlib stream */
-    int   status;        /* as the name implies */
-    Bytef *pending_buf;  /* output still pending */
-    ulg   pending_buf_size; /* size of pending_buf */
-    Bytef *pending_out;  /* next pending byte to output to the stream */
-    int   pending;       /* nb of bytes in the pending buffer */
-    int   noheader;      /* suppress zlib header and adler32 */
-    Byte  data_type;     /* UNKNOWN, BINARY or ASCII */
-    Byte  method;        /* STORED (for zip only) or DEFLATED */
-    int   last_flush;    /* value of flush param for previous deflate call */
-
-                /* used by deflate.c: */
-
-    uInt  w_size;        /* LZ77 window size (32K by default) */
-    uInt  w_bits;        /* log2(w_size)  (8..16) */
-    uInt  w_mask;        /* w_size - 1 */
-
-    Bytef *window;
-    /* Sliding window. Input bytes are read into the second half of the window,
-     * and move to the first half later to keep a dictionary of at least wSize
-     * bytes. With this organization, matches are limited to a distance of
-     * wSize-MAX_MATCH bytes, but this ensures that IO is always
-     * performed with a length multiple of the block size. Also, it limits
-     * the window size to 64K, which is quite useful on MSDOS.
-     * To do: use the user input buffer as sliding window.
-     */
-
-    ulg window_size;
-    /* Actual size of window: 2*wSize, except when the user input buffer
-     * is directly used as sliding window.
-     */
-
-    Posf *prev;
-    /* Link to older string with same hash index. To limit the size of this
-     * array to 64K, this link is maintained only for the last 32K strings.
-     * An index in this array is thus a window index modulo 32K.
-     */
-
-    Posf *head; /* Heads of the hash chains or NIL. */
-
-    uInt  ins_h;          /* hash index of string to be inserted */
-    uInt  hash_size;      /* number of elements in hash table */
-    uInt  hash_bits;      /* log2(hash_size) */
-    uInt  hash_mask;      /* hash_size-1 */
-
-    uInt  hash_shift;
-    /* Number of bits by which ins_h must be shifted at each input
-     * step. It must be such that after MIN_MATCH steps, the oldest
-     * byte no longer takes part in the hash key, that is:
-     *   hash_shift * MIN_MATCH >= hash_bits
-     */
-
-    long block_start;
-    /* Window position at the beginning of the current output block. Gets
-     * negative when the window is moved backwards.
-     */
-
-    uInt match_length;           /* length of best match */
-    IPos prev_match;             /* previous match */
-    int match_available;         /* set if previous match exists */
-    uInt strstart;               /* start of string to insert */
-    uInt match_start;            /* start of matching string */
-    uInt lookahead;              /* number of valid bytes ahead in window */
-
-    uInt prev_length;
-    /* Length of the best match at previous step. Matches not greater than this
-     * are discarded. This is used in the lazy match evaluation.
-     */
-
-    uInt max_chain_length;
-    /* To speed up deflation, hash chains are never searched beyond this
-     * length.  A higher limit improves compression ratio but degrades the
-     * speed.
-     */
-
-    uInt max_lazy_match;
-    /* Attempt to find a better match only when the current match is strictly
-     * smaller than this value. This mechanism is used only for compression
-     * levels >= 4.
-     */
-#   define max_insert_length  max_lazy_match
-    /* Insert new strings in the hash table only if the match length is not
-     * greater than this length. This saves time but degrades compression.
-     * max_insert_length is used only for compression levels <= 3.
-     */
-
-    int level;    /* compression level (1..9) */
-    int strategy; /* favor or force Huffman coding*/
-
-    uInt good_match;
-    /* Use a faster search when the previous match is longer than this */
-
-    int nice_match; /* Stop searching when current match exceeds this */
-
-                /* used by trees.c: */
-    /* Didn't use ct_data typedef below to supress compiler warning */
-    struct ct_data_s dyn_ltree[HEAP_SIZE];   /* literal and length tree */
-    struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
-    struct ct_data_s bl_tree[2*BL_CODES+1];  /* Huffman tree for bit lengths */
-
-    struct tree_desc_s l_desc;               /* desc. for literal tree */
-    struct tree_desc_s d_desc;               /* desc. for distance tree */
-    struct tree_desc_s bl_desc;              /* desc. for bit length tree */
-
-    ush bl_count[MAX_BITS+1];
-    /* number of codes at each bit length for an optimal tree */
-
-    int heap[2*L_CODES+1];      /* heap used to build the Huffman trees */
-    int heap_len;               /* number of elements in the heap */
-    int heap_max;               /* element of largest frequency */
-    /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
-     * The same heap array is used to build all trees.
-     */
-
-    uch depth[2*L_CODES+1];
-    /* Depth of each subtree used as tie breaker for trees of equal frequency
-     */
-
-    uchf *l_buf;          /* buffer for literals or lengths */
-
-    uInt  lit_bufsize;
-    /* Size of match buffer for literals/lengths.  There are 4 reasons for
-     * limiting lit_bufsize to 64K:
-     *   - frequencies can be kept in 16 bit counters
-     *   - if compression is not successful for the first block, all input
-     *     data is still in the window so we can still emit a stored block even
-     *     when input comes from standard input.  (This can also be done for
-     *     all blocks if lit_bufsize is not greater than 32K.)
-     *   - if compression is not successful for a file smaller than 64K, we can
-     *     even emit a stored file instead of a stored block (saving 5 bytes).
-     *     This is applicable only for zip (not gzip or zlib).
-     *   - creating new Huffman trees less frequently may not provide fast
-     *     adaptation to changes in the input data statistics. (Take for
-     *     example a binary file with poorly compressible code followed by
-     *     a highly compressible string table.) Smaller buffer sizes give
-     *     fast adaptation but have of course the overhead of transmitting
-     *     trees more frequently.
-     *   - I can't count above 4
-     */
-
-    uInt last_lit;      /* running index in l_buf */
-
-    ushf *d_buf;
-    /* Buffer for distances. To simplify the code, d_buf and l_buf have
-     * the same number of elements. To use different lengths, an extra flag
-     * array would be necessary.
-     */
-
-    ulg opt_len;        /* bit length of current block with optimal trees */
-    ulg static_len;     /* bit length of current block with static trees */
-    uInt matches;       /* number of string matches in current block */
-    int last_eob_len;   /* bit length of EOB code for last block */
-
-#ifdef DEBUG
-    ulg compressed_len; /* total bit length of compressed file mod 2^32 */
-    ulg bits_sent;      /* bit length of compressed data sent mod 2^32 */
-#endif
-
-    ush bi_buf;
-    /* Output buffer. bits are inserted starting at the bottom (least
-     * significant bits).
-     */
-    int bi_valid;
-    /* Number of valid bits in bi_buf.  All bits above the last valid bit
-     * are always zero.
-     */
-
-} FAR deflate_state;
-
-/* Output a byte on the stream.
- * IN assertion: there is enough room in pending_buf.
- */
-#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);}
-
-
-#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
-/* Minimum amount of lookahead, except at the end of the input file.
- * See deflate.c for comments about the MIN_MATCH+1.
- */
-
-#define MAX_DIST(s)  ((s)->w_size-MIN_LOOKAHEAD)
-/* In order to simplify the code, particularly on 16 bit machines, match
- * distances are limited to MAX_DIST instead of WSIZE.
- */
-
-        /* in trees.c */
-void _tr_init         OF((deflate_state *s));
-int  _tr_tally        OF((deflate_state *s, unsigned dist, unsigned lc));
-void _tr_flush_block  OF((deflate_state *s, charf *buf, ulg stored_len,
-			  int eof));
-void _tr_align        OF((deflate_state *s));
-void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len,
-                          int eof));
-
-#define d_code(dist) \
-   ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)])
-/* Mapping from a distance to a distance code. dist is the distance - 1 and
- * must not have side effects. _dist_code[256] and _dist_code[257] are never
- * used.
- */
-
-#ifndef DEBUG
-/* Inline versions of _tr_tally for speed: */
-
-#if defined(GEN_TREES_H) || !defined(STDC)
-  extern uch _length_code[];
-  extern uch _dist_code[];
-#else
-  extern const uch _length_code[];
-  extern const uch _dist_code[];
-#endif
-
-# define _tr_tally_lit(s, c, flush) \
-  { uch cc = (c); \
-    s->d_buf[s->last_lit] = 0; \
-    s->l_buf[s->last_lit++] = cc; \
-    s->dyn_ltree[cc].Freq++; \
-    flush = (s->last_lit == s->lit_bufsize-1); \
-   }
-# define _tr_tally_dist(s, distance, length, flush) \
-  { uch len = (length); \
-    ush dist = (distance); \
-    s->d_buf[s->last_lit] = dist; \
-    s->l_buf[s->last_lit++] = len; \
-    dist--; \
-    s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
-    s->dyn_dtree[d_code(dist)].Freq++; \
-    flush = (s->last_lit == s->lit_bufsize-1); \
-  }
-#else
-# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
-# define _tr_tally_dist(s, distance, length, flush) \
-              flush = _tr_tally(s, distance, length) 
-#endif
-
-#endif
diff --git a/Lib/zlib/descrip.mms b/Lib/zlib/descrip.mms
deleted file mode 100644
index 9d364598a..000000000
--- a/Lib/zlib/descrip.mms
+++ /dev/null
@@ -1,48 +0,0 @@
-# descrip.mms: MMS description file for building zlib on VMS
-# written by Martin P.J. Zinser 
-
-cc_defs = 
-c_deb = 
-
-.ifdef __DECC__
-pref = /prefix=all
-.endif
-
-OBJS = adler32.obj, compress.obj, crc32.obj, gzio.obj, uncompr.obj,\
-       deflate.obj, trees.obj, zutil.obj, inflate.obj, infblock.obj,\
-       inftrees.obj, infcodes.obj, infutil.obj, inffast.obj
-
-CFLAGS= $(C_DEB) $(CC_DEFS) $(PREF)
-
-all : example.exe minigzip.exe
-        @ write sys$output " Example applications available"
-libz.olb : libz.olb($(OBJS))
-	@ write sys$output " libz available"
-
-example.exe : example.obj libz.olb
-              link example,libz.olb/lib
-
-minigzip.exe : minigzip.obj libz.olb
-              link minigzip,libz.olb/lib,x11vms:xvmsutils.olb/lib
-
-clean : 
-	delete *.obj;*,libz.olb;*
-
-
-# Other dependencies.
-adler32.obj : zutil.h zlib.h zconf.h
-compress.obj : zlib.h zconf.h
-crc32.obj : zutil.h zlib.h zconf.h
-deflate.obj : deflate.h zutil.h zlib.h zconf.h
-example.obj : zlib.h zconf.h
-gzio.obj : zutil.h zlib.h zconf.h
-infblock.obj : zutil.h zlib.h zconf.h infblock.h inftrees.h infcodes.h infutil.h
-infcodes.obj : zutil.h zlib.h zconf.h inftrees.h infutil.h infcodes.h inffast.h
-inffast.obj : zutil.h zlib.h zconf.h inftrees.h infutil.h inffast.h
-inflate.obj : zutil.h zlib.h zconf.h infblock.h
-inftrees.obj : zutil.h zlib.h zconf.h inftrees.h
-infutil.obj : zutil.h zlib.h zconf.h inftrees.h infutil.h
-minigzip.obj : zlib.h zconf.h
-trees.obj : deflate.h zutil.h zlib.h zconf.h
-uncompr.obj : zlib.h zconf.h
-zutil.obj : zutil.h zlib.h zconf.h
diff --git a/Lib/zlib/example.c b/Lib/zlib/example.c
deleted file mode 100644
index 8307c841e..000000000
--- a/Lib/zlib/example.c
+++ /dev/null
@@ -1,556 +0,0 @@
-/* example.c -- usage example of the zlib compression library
- * Copyright (C) 1995-1998 Jean-loup Gailly.
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* @(#) $Id$ */
-
-#include 
-#include "zlib.h"
-
-#ifdef STDC
-#  include 
-#  include 
-#else
-   extern void exit  OF((int));
-#endif
-
-#if defined(VMS) || defined(RISCOS)
-#  define TESTFILE "foo-gz"
-#else
-#  define TESTFILE "foo.gz"
-#endif
-
-#define CHECK_ERR(err, msg) { \
-    if (err != Z_OK) { \
-        fprintf(stderr, "%s error: %d\n", msg, err); \
-        exit(1); \
-    } \
-}
-
-const char hello[] = "hello, hello!";
-/* "hello world" would be more standard, but the repeated "hello"
- * stresses the compression code better, sorry...
- */
-
-const char dictionary[] = "hello";
-uLong dictId; /* Adler32 value of the dictionary */
-
-void test_compress      OF((Byte *compr, uLong comprLen,
-		            Byte *uncompr, uLong uncomprLen));
-void test_gzio          OF((const char *out, const char *in, 
-		            Byte *uncompr, int uncomprLen));
-void test_deflate       OF((Byte *compr, uLong comprLen));
-void test_inflate       OF((Byte *compr, uLong comprLen,
-		            Byte *uncompr, uLong uncomprLen));
-void test_large_deflate OF((Byte *compr, uLong comprLen,
-		            Byte *uncompr, uLong uncomprLen));
-void test_large_inflate OF((Byte *compr, uLong comprLen,
-		            Byte *uncompr, uLong uncomprLen));
-void test_flush         OF((Byte *compr, uLong *comprLen));
-void test_sync          OF((Byte *compr, uLong comprLen,
-		            Byte *uncompr, uLong uncomprLen));
-void test_dict_deflate  OF((Byte *compr, uLong comprLen));
-void test_dict_inflate  OF((Byte *compr, uLong comprLen,
-		            Byte *uncompr, uLong uncomprLen));
-int  main               OF((int argc, char *argv[]));
-
-/* ===========================================================================
- * Test compress() and uncompress()
- */
-void test_compress(compr, comprLen, uncompr, uncomprLen)
-    Byte *compr, *uncompr;
-    uLong comprLen, uncomprLen;
-{
-    int err;
-    uLong len = strlen(hello)+1;
-
-    err = compress(compr, &comprLen, (const Bytef*)hello, len);
-    CHECK_ERR(err, "compress");
-
-    strcpy((char*)uncompr, "garbage");
-
-    err = uncompress(uncompr, &uncomprLen, compr, comprLen);
-    CHECK_ERR(err, "uncompress");
-
-    if (strcmp((char*)uncompr, hello)) {
-        fprintf(stderr, "bad uncompress\n");
-	exit(1);
-    } else {
-        printf("uncompress(): %s\n", (char *)uncompr);
-    }
-}
-
-/* ===========================================================================
- * Test read/write of .gz files
- */
-void test_gzio(out, in, uncompr, uncomprLen)
-    const char *out; /* compressed output file */
-    const char *in;  /* compressed input file */
-    Byte *uncompr;
-    int  uncomprLen;
-{
-    int err;
-    int len = strlen(hello)+1;
-    gzFile file;
-    z_off_t pos;
-
-    file = gzopen(out, "wb");
-    if (file == NULL) {
-        fprintf(stderr, "gzopen error\n");
-        exit(1);
-    }
-    gzputc(file, 'h');
-    if (gzputs(file, "ello") != 4) {
-        fprintf(stderr, "gzputs err: %s\n", gzerror(file, &err));
-	exit(1);
-    }
-    if (gzprintf(file, ", %s!", "hello") != 8) {
-        fprintf(stderr, "gzprintf err: %s\n", gzerror(file, &err));
-	exit(1);
-    }
-    gzseek(file, 1L, SEEK_CUR); /* add one zero byte */
-    gzclose(file);
-
-    file = gzopen(in, "rb");
-    if (file == NULL) {
-        fprintf(stderr, "gzopen error\n");
-    }
-    strcpy((char*)uncompr, "garbage");
-
-    uncomprLen = gzread(file, uncompr, (unsigned)uncomprLen);
-    if (uncomprLen != len) {
-        fprintf(stderr, "gzread err: %s\n", gzerror(file, &err));
-	exit(1);
-    }
-    if (strcmp((char*)uncompr, hello)) {
-        fprintf(stderr, "bad gzread: %s\n", (char*)uncompr);
-	exit(1);
-    } else {
-        printf("gzread(): %s\n", (char *)uncompr);
-    }
-
-    pos = gzseek(file, -8L, SEEK_CUR);
-    if (pos != 6 || gztell(file) != pos) {
-	fprintf(stderr, "gzseek error, pos=%ld, gztell=%ld\n",
-		(long)pos, (long)gztell(file));
-	exit(1);
-    }
-
-    if (gzgetc(file) != ' ') {
-	fprintf(stderr, "gzgetc error\n");
-	exit(1);
-    }
-
-    gzgets(file, (char*)uncompr, uncomprLen);
-    uncomprLen = strlen((char*)uncompr);
-    if (uncomprLen != 6) { /* "hello!" */
-        fprintf(stderr, "gzgets err after gzseek: %s\n", gzerror(file, &err));
-	exit(1);
-    }
-    if (strcmp((char*)uncompr, hello+7)) {
-        fprintf(stderr, "bad gzgets after gzseek\n");
-	exit(1);
-    } else {
-        printf("gzgets() after gzseek: %s\n", (char *)uncompr);
-    }
-
-    gzclose(file);
-}
-
-/* ===========================================================================
- * Test deflate() with small buffers
- */
-void test_deflate(compr, comprLen)
-    Byte *compr;
-    uLong comprLen;
-{
-    z_stream c_stream; /* compression stream */
-    int err;
-    int len = strlen(hello)+1;
-
-    c_stream.zalloc = (alloc_func)0;
-    c_stream.zfree = (free_func)0;
-    c_stream.opaque = (voidpf)0;
-
-    err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);
-    CHECK_ERR(err, "deflateInit");
-
-    c_stream.next_in  = (Bytef*)hello;
-    c_stream.next_out = compr;
-
-    while (c_stream.total_in != (uLong)len && c_stream.total_out < comprLen) {
-        c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */
-        err = deflate(&c_stream, Z_NO_FLUSH);
-        CHECK_ERR(err, "deflate");
-    }
-    /* Finish the stream, still forcing small buffers: */
-    for (;;) {
-        c_stream.avail_out = 1;
-        err = deflate(&c_stream, Z_FINISH);
-        if (err == Z_STREAM_END) break;
-        CHECK_ERR(err, "deflate");
-    }
-
-    err = deflateEnd(&c_stream);
-    CHECK_ERR(err, "deflateEnd");
-}
-
-/* ===========================================================================
- * Test inflate() with small buffers
- */
-void test_inflate(compr, comprLen, uncompr, uncomprLen)
-    Byte *compr, *uncompr;
-    uLong comprLen, uncomprLen;
-{
-    int err;
-    z_stream d_stream; /* decompression stream */
-
-    strcpy((char*)uncompr, "garbage");
-
-    d_stream.zalloc = (alloc_func)0;
-    d_stream.zfree = (free_func)0;
-    d_stream.opaque = (voidpf)0;
-
-    d_stream.next_in  = compr;
-    d_stream.avail_in = 0;
-    d_stream.next_out = uncompr;
-
-    err = inflateInit(&d_stream);
-    CHECK_ERR(err, "inflateInit");
-
-    while (d_stream.total_out < uncomprLen && d_stream.total_in < comprLen) {
-        d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */
-        err = inflate(&d_stream, Z_NO_FLUSH);
-        if (err == Z_STREAM_END) break;
-        CHECK_ERR(err, "inflate");
-    }
-
-    err = inflateEnd(&d_stream);
-    CHECK_ERR(err, "inflateEnd");
-
-    if (strcmp((char*)uncompr, hello)) {
-        fprintf(stderr, "bad inflate\n");
-	exit(1);
-    } else {
-        printf("inflate(): %s\n", (char *)uncompr);
-    }
-}
-
-/* ===========================================================================
- * Test deflate() with large buffers and dynamic change of compression level
- */
-void test_large_deflate(compr, comprLen, uncompr, uncomprLen)
-    Byte *compr, *uncompr;
-    uLong comprLen, uncomprLen;
-{
-    z_stream c_stream; /* compression stream */
-    int err;
-
-    c_stream.zalloc = (alloc_func)0;
-    c_stream.zfree = (free_func)0;
-    c_stream.opaque = (voidpf)0;
-
-    err = deflateInit(&c_stream, Z_BEST_SPEED);
-    CHECK_ERR(err, "deflateInit");
-
-    c_stream.next_out = compr;
-    c_stream.avail_out = (uInt)comprLen;
-
-    /* At this point, uncompr is still mostly zeroes, so it should compress
-     * very well:
-     */
-    c_stream.next_in = uncompr;
-    c_stream.avail_in = (uInt)uncomprLen;
-    err = deflate(&c_stream, Z_NO_FLUSH);
-    CHECK_ERR(err, "deflate");
-    if (c_stream.avail_in != 0) {
-        fprintf(stderr, "deflate not greedy\n");
-	exit(1);
-    }
-
-    /* Feed in already compressed data and switch to no compression: */
-    deflateParams(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY);
-    c_stream.next_in = compr;
-    c_stream.avail_in = (uInt)comprLen/2;
-    err = deflate(&c_stream, Z_NO_FLUSH);
-    CHECK_ERR(err, "deflate");
-
-    /* Switch back to compressing mode: */
-    deflateParams(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED);
-    c_stream.next_in = uncompr;
-    c_stream.avail_in = (uInt)uncomprLen;
-    err = deflate(&c_stream, Z_NO_FLUSH);
-    CHECK_ERR(err, "deflate");
-
-    err = deflate(&c_stream, Z_FINISH);
-    if (err != Z_STREAM_END) {
-        fprintf(stderr, "deflate should report Z_STREAM_END\n");
-	exit(1);
-    }
-    err = deflateEnd(&c_stream);
-    CHECK_ERR(err, "deflateEnd");
-}
-
-/* ===========================================================================
- * Test inflate() with large buffers
- */
-void test_large_inflate(compr, comprLen, uncompr, uncomprLen)
-    Byte *compr, *uncompr;
-    uLong comprLen, uncomprLen;
-{
-    int err;
-    z_stream d_stream; /* decompression stream */
-
-    strcpy((char*)uncompr, "garbage");
-
-    d_stream.zalloc = (alloc_func)0;
-    d_stream.zfree = (free_func)0;
-    d_stream.opaque = (voidpf)0;
-
-    d_stream.next_in  = compr;
-    d_stream.avail_in = (uInt)comprLen;
-
-    err = inflateInit(&d_stream);
-    CHECK_ERR(err, "inflateInit");
-
-    for (;;) {
-        d_stream.next_out = uncompr;            /* discard the output */
-	d_stream.avail_out = (uInt)uncomprLen;
-        err = inflate(&d_stream, Z_NO_FLUSH);
-        if (err == Z_STREAM_END) break;
-        CHECK_ERR(err, "large inflate");
-    }
-
-    err = inflateEnd(&d_stream);
-    CHECK_ERR(err, "inflateEnd");
-
-    if (d_stream.total_out != 2*uncomprLen + comprLen/2) {
-        fprintf(stderr, "bad large inflate: %ld\n", d_stream.total_out);
-	exit(1);
-    } else {
-        printf("large_inflate(): OK\n");
-    }
-}
-
-/* ===========================================================================
- * Test deflate() with full flush
- */
-void test_flush(compr, comprLen)
-    Byte *compr;
-    uLong *comprLen;
-{
-    z_stream c_stream; /* compression stream */
-    int err;
-    int len = strlen(hello)+1;
-
-    c_stream.zalloc = (alloc_func)0;
-    c_stream.zfree = (free_func)0;
-    c_stream.opaque = (voidpf)0;
-
-    err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);
-    CHECK_ERR(err, "deflateInit");
-
-    c_stream.next_in  = (Bytef*)hello;
-    c_stream.next_out = compr;
-    c_stream.avail_in = 3;
-    c_stream.avail_out = (uInt)*comprLen;
-    err = deflate(&c_stream, Z_FULL_FLUSH);
-    CHECK_ERR(err, "deflate");
-
-    compr[3]++; /* force an error in first compressed block */
-    c_stream.avail_in = len - 3;
-
-    err = deflate(&c_stream, Z_FINISH);
-    if (err != Z_STREAM_END) {
-        CHECK_ERR(err, "deflate");
-    }
-    err = deflateEnd(&c_stream);
-    CHECK_ERR(err, "deflateEnd");
-
-    *comprLen = c_stream.total_out;
-}
-
-/* ===========================================================================
- * Test inflateSync()
- */
-void test_sync(compr, comprLen, uncompr, uncomprLen)
-    Byte *compr, *uncompr;
-    uLong comprLen, uncomprLen;
-{
-    int err;
-    z_stream d_stream; /* decompression stream */
-
-    strcpy((char*)uncompr, "garbage");
-
-    d_stream.zalloc = (alloc_func)0;
-    d_stream.zfree = (free_func)0;
-    d_stream.opaque = (voidpf)0;
-
-    d_stream.next_in  = compr;
-    d_stream.avail_in = 2; /* just read the zlib header */
-
-    err = inflateInit(&d_stream);
-    CHECK_ERR(err, "inflateInit");
-
-    d_stream.next_out = uncompr;
-    d_stream.avail_out = (uInt)uncomprLen;
-
-    inflate(&d_stream, Z_NO_FLUSH);
-    CHECK_ERR(err, "inflate");
-
-    d_stream.avail_in = (uInt)comprLen-2;   /* read all compressed data */
-    err = inflateSync(&d_stream);           /* but skip the damaged part */
-    CHECK_ERR(err, "inflateSync");
-
-    err = inflate(&d_stream, Z_FINISH);
-    if (err != Z_DATA_ERROR) {
-        fprintf(stderr, "inflate should report DATA_ERROR\n");
-        /* Because of incorrect adler32 */
-	exit(1);
-    }
-    err = inflateEnd(&d_stream);
-    CHECK_ERR(err, "inflateEnd");
-
-    printf("after inflateSync(): hel%s\n", (char *)uncompr);
-}
-
-/* ===========================================================================
- * Test deflate() with preset dictionary
- */
-void test_dict_deflate(compr, comprLen)
-    Byte *compr;
-    uLong comprLen;
-{
-    z_stream c_stream; /* compression stream */
-    int err;
-
-    c_stream.zalloc = (alloc_func)0;
-    c_stream.zfree = (free_func)0;
-    c_stream.opaque = (voidpf)0;
-
-    err = deflateInit(&c_stream, Z_BEST_COMPRESSION);
-    CHECK_ERR(err, "deflateInit");
-
-    err = deflateSetDictionary(&c_stream,
-			       (const Bytef*)dictionary, sizeof(dictionary));
-    CHECK_ERR(err, "deflateSetDictionary");
-
-    dictId = c_stream.adler;
-    c_stream.next_out = compr;
-    c_stream.avail_out = (uInt)comprLen;
-
-    c_stream.next_in = (Bytef*)hello;
-    c_stream.avail_in = (uInt)strlen(hello)+1;
-
-    err = deflate(&c_stream, Z_FINISH);
-    if (err != Z_STREAM_END) {
-        fprintf(stderr, "deflate should report Z_STREAM_END\n");
-	exit(1);
-    }
-    err = deflateEnd(&c_stream);
-    CHECK_ERR(err, "deflateEnd");
-}
-
-/* ===========================================================================
- * Test inflate() with a preset dictionary
- */
-void test_dict_inflate(compr, comprLen, uncompr, uncomprLen)
-    Byte *compr, *uncompr;
-    uLong comprLen, uncomprLen;
-{
-    int err;
-    z_stream d_stream; /* decompression stream */
-
-    strcpy((char*)uncompr, "garbage");
-
-    d_stream.zalloc = (alloc_func)0;
-    d_stream.zfree = (free_func)0;
-    d_stream.opaque = (voidpf)0;
-
-    d_stream.next_in  = compr;
-    d_stream.avail_in = (uInt)comprLen;
-
-    err = inflateInit(&d_stream);
-    CHECK_ERR(err, "inflateInit");
-
-    d_stream.next_out = uncompr;
-    d_stream.avail_out = (uInt)uncomprLen;
-
-    for (;;) {
-        err = inflate(&d_stream, Z_NO_FLUSH);
-        if (err == Z_STREAM_END) break;
-	if (err == Z_NEED_DICT) {
-	    if (d_stream.adler != dictId) {
-		fprintf(stderr, "unexpected dictionary");
-		exit(1);
-	    }
-	    err = inflateSetDictionary(&d_stream, (const Bytef*)dictionary,
-				       sizeof(dictionary));
-	}
-        CHECK_ERR(err, "inflate with dict");
-    }
-
-    err = inflateEnd(&d_stream);
-    CHECK_ERR(err, "inflateEnd");
-
-    if (strcmp((char*)uncompr, hello)) {
-        fprintf(stderr, "bad inflate with dict\n");
-	exit(1);
-    } else {
-        printf("inflate with dictionary: %s\n", (char *)uncompr);
-    }
-}
-
-/* ===========================================================================
- * Usage:  example [output.gz  [input.gz]]
- */
-
-int main(argc, argv)
-    int argc;
-    char *argv[];
-{
-    Byte *compr, *uncompr;
-    uLong comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */
-    uLong uncomprLen = comprLen;
-    static const char* myVersion = ZLIB_VERSION;
-
-    if (zlibVersion()[0] != myVersion[0]) {
-        fprintf(stderr, "incompatible zlib version\n");
-        exit(1);
-
-    } else if (strcmp(zlibVersion(), ZLIB_VERSION) != 0) {
-        fprintf(stderr, "warning: different zlib version\n");
-    }
-
-    compr    = (Byte*)calloc((uInt)comprLen, 1);
-    uncompr  = (Byte*)calloc((uInt)uncomprLen, 1);
-    /* compr and uncompr are cleared to avoid reading uninitialized
-     * data and to ensure that uncompr compresses well.
-     */
-    if (compr == Z_NULL || uncompr == Z_NULL) {
-        printf("out of memory\n");
-	exit(1);
-    }
-    test_compress(compr, comprLen, uncompr, uncomprLen);
-
-    test_gzio((argc > 1 ? argv[1] : TESTFILE),
-              (argc > 2 ? argv[2] : TESTFILE),
-	      uncompr, (int)uncomprLen);
-
-    test_deflate(compr, comprLen);
-    test_inflate(compr, comprLen, uncompr, uncomprLen);
-
-    test_large_deflate(compr, comprLen, uncompr, uncomprLen);
-    test_large_inflate(compr, comprLen, uncompr, uncomprLen);
-
-    test_flush(compr, &comprLen);
-    test_sync(compr, comprLen, uncompr, uncomprLen);
-    comprLen = uncomprLen;
-
-    test_dict_deflate(compr, comprLen);
-    test_dict_inflate(compr, comprLen, uncompr, uncomprLen);
-
-    exit(0);
-    return 0; /* to avoid warning */
-}
diff --git a/Lib/zlib/gzio.c b/Lib/zlib/gzio.c
deleted file mode 100644
index f7c336a55..000000000
--- a/Lib/zlib/gzio.c
+++ /dev/null
@@ -1,875 +0,0 @@
-/* gzio.c -- IO on .gz files
- * Copyright (C) 1995-1998 Jean-loup Gailly.
- * For conditions of distribution and use, see copyright notice in zlib.h
- *
- * Compile this file with -DNO_DEFLATE to avoid the compression code.
- */
-
-/* @(#) $Id$ */
-
-#include 
-
-#include "zutil.h"
-
-struct internal_state {int dummy;}; /* for buggy compilers */
-
-#ifndef Z_BUFSIZE
-#  ifdef MAXSEG_64K
-#    define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */
-#  else
-#    define Z_BUFSIZE 16384
-#  endif
-#endif
-#ifndef Z_PRINTF_BUFSIZE
-#  define Z_PRINTF_BUFSIZE 4096
-#endif
-
-#define ALLOC(size) malloc(size)
-#define TRYFREE(p) {if (p) free(p);}
-
-static int gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
-
-/* gzip flag byte */
-#define ASCII_FLAG   0x01 /* bit 0 set: file probably ascii text */
-#define HEAD_CRC     0x02 /* bit 1 set: header CRC present */
-#define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
-#define ORIG_NAME    0x08 /* bit 3 set: original file name present */
-#define COMMENT      0x10 /* bit 4 set: file comment present */
-#define RESERVED     0xE0 /* bits 5..7: reserved */
-
-typedef struct gz_stream {
-    z_stream stream;
-    int      z_err;   /* error code for last stream operation */
-    int      z_eof;   /* set if end of input file */
-    FILE     *file;   /* .gz file */
-    Byte     *inbuf;  /* input buffer */
-    Byte     *outbuf; /* output buffer */
-    uLong    crc;     /* crc32 of uncompressed data */
-    char     *msg;    /* error message */
-    char     *path;   /* path name for debugging only */
-    int      transparent; /* 1 if input file is not a .gz file */
-    char     mode;    /* 'w' or 'r' */
-    long     startpos; /* start of compressed data in file (header skipped) */
-} gz_stream;
-
-
-local gzFile gz_open      OF((const char *path, const char *mode, int  fd));
-local int do_flush        OF((gzFile file, int flush));
-local int    get_byte     OF((gz_stream *s));
-local void   check_header OF((gz_stream *s));
-local int    destroy      OF((gz_stream *s));
-local void   putLong      OF((FILE *file, uLong x));
-local uLong  getLong      OF((gz_stream *s));
-
-/* ===========================================================================
-     Opens a gzip (.gz) file for reading or writing. The mode parameter
-   is as in fopen ("rb" or "wb"). The file is given either by file descriptor
-   or path name (if fd == -1).
-     gz_open return NULL if the file could not be opened or if there was
-   insufficient memory to allocate the (de)compression state; errno
-   can be checked to distinguish the two cases (if errno is zero, the
-   zlib error is Z_MEM_ERROR).
-*/
-local gzFile gz_open (path, mode, fd)
-    const char *path;
-    const char *mode;
-    int  fd;
-{
-    int err;
-    int level = Z_DEFAULT_COMPRESSION; /* compression level */
-    int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */
-    char *p = (char*)mode;
-    gz_stream *s;
-    char fmode[80]; /* copy of mode, without the compression level */
-    char *m = fmode;
-
-    if (!path || !mode) return Z_NULL;
-
-    s = (gz_stream *)ALLOC(sizeof(gz_stream));
-    if (!s) return Z_NULL;
-
-    s->stream.zalloc = (alloc_func)0;
-    s->stream.zfree = (free_func)0;
-    s->stream.opaque = (voidpf)0;
-    s->stream.next_in = s->inbuf = Z_NULL;
-    s->stream.next_out = s->outbuf = Z_NULL;
-    s->stream.avail_in = s->stream.avail_out = 0;
-    s->file = NULL;
-    s->z_err = Z_OK;
-    s->z_eof = 0;
-    s->crc = crc32(0L, Z_NULL, 0);
-    s->msg = NULL;
-    s->transparent = 0;
-
-    s->path = (char*)ALLOC(strlen(path)+1);
-    if (s->path == NULL) {
-        return destroy(s), (gzFile)Z_NULL;
-    }
-    strcpy(s->path, path); /* do this early for debugging */
-
-    s->mode = '\0';
-    do {
-        if (*p == 'r') s->mode = 'r';
-        if (*p == 'w' || *p == 'a') s->mode = 'w';
-        if (*p >= '0' && *p <= '9') {
-	    level = *p - '0';
-	} else if (*p == 'f') {
-	  strategy = Z_FILTERED;
-	} else if (*p == 'h') {
-	  strategy = Z_HUFFMAN_ONLY;
-	} else {
-	    *m++ = *p; /* copy the mode */
-	}
-    } while (*p++ && m != fmode + sizeof(fmode));
-    if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL;
-    
-    if (s->mode == 'w') {
-#ifdef NO_DEFLATE
-        err = Z_STREAM_ERROR;
-#else
-        err = deflateInit2(&(s->stream), level,
-                           Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy);
-        /* windowBits is passed < 0 to suppress zlib header */
-
-        s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE);
-#endif
-        if (err != Z_OK || s->outbuf == Z_NULL) {
-            return destroy(s), (gzFile)Z_NULL;
-        }
-    } else {
-        s->stream.next_in  = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE);
-
-        err = inflateInit2(&(s->stream), -MAX_WBITS);
-        /* windowBits is passed < 0 to tell that there is no zlib header.
-         * Note that in this case inflate *requires* an extra "dummy" byte
-         * after the compressed stream in order to complete decompression and
-         * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are
-         * present after the compressed stream.
-         */
-        if (err != Z_OK || s->inbuf == Z_NULL) {
-            return destroy(s), (gzFile)Z_NULL;
-        }
-    }
-    s->stream.avail_out = Z_BUFSIZE;
-
-    errno = 0;
-    s->file = fd < 0 ? F_OPEN(path, fmode) : (FILE*)fdopen(fd, fmode);
-
-    if (s->file == NULL) {
-        return destroy(s), (gzFile)Z_NULL;
-    }
-    if (s->mode == 'w') {
-        /* Write a very simple .gz header:
-         */
-        fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1],
-             Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE);
-	s->startpos = 10L;
-	/* We use 10L instead of ftell(s->file) to because ftell causes an
-         * fflush on some systems. This version of the library doesn't use
-         * startpos anyway in write mode, so this initialization is not
-         * necessary.
-         */
-    } else {
-	check_header(s); /* skip the .gz header */
-	s->startpos = (ftell(s->file) - s->stream.avail_in);
-    }
-    
-    return (gzFile)s;
-}
-
-/* ===========================================================================
-     Opens a gzip (.gz) file for reading or writing.
-*/
-gzFile ZEXPORT gzopen (path, mode)
-    const char *path;
-    const char *mode;
-{
-    return gz_open (path, mode, -1);
-}
-
-/* ===========================================================================
-     Associate a gzFile with the file descriptor fd. fd is not dup'ed here
-   to mimic the behavio(u)r of fdopen.
-*/
-gzFile ZEXPORT gzdopen (fd, mode)
-    int fd;
-    const char *mode;
-{
-    char name[20];
-
-    if (fd < 0) return (gzFile)Z_NULL;
-    sprintf(name, "", fd); /* for debugging */
-
-    return gz_open (name, mode, fd);
-}
-
-/* ===========================================================================
- * Update the compression level and strategy
- */
-int ZEXPORT gzsetparams (file, level, strategy)
-    gzFile file;
-    int level;
-    int strategy;
-{
-    gz_stream *s = (gz_stream*)file;
-
-    if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
-
-    /* Make room to allow flushing */
-    if (s->stream.avail_out == 0) {
-
-	s->stream.next_out = s->outbuf;
-	if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) {
-	    s->z_err = Z_ERRNO;
-	}
-	s->stream.avail_out = Z_BUFSIZE;
-    }
-
-    return deflateParams (&(s->stream), level, strategy);
-}
-
-/* ===========================================================================
-     Read a byte from a gz_stream; update next_in and avail_in. Return EOF
-   for end of file.
-   IN assertion: the stream s has been sucessfully opened for reading.
-*/
-local int get_byte(s)
-    gz_stream *s;
-{
-    if (s->z_eof) return EOF;
-    if (s->stream.avail_in == 0) {
-	errno = 0;
-	s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file);
-	if (s->stream.avail_in == 0) {
-	    s->z_eof = 1;
-	    if (ferror(s->file)) s->z_err = Z_ERRNO;
-	    return EOF;
-	}
-	s->stream.next_in = s->inbuf;
-    }
-    s->stream.avail_in--;
-    return *(s->stream.next_in)++;
-}
-
-/* ===========================================================================
-      Check the gzip header of a gz_stream opened for reading. Set the stream
-    mode to transparent if the gzip magic header is not present; set s->err
-    to Z_DATA_ERROR if the magic header is present but the rest of the header
-    is incorrect.
-    IN assertion: the stream s has already been created sucessfully;
-       s->stream.avail_in is zero for the first time, but may be non-zero
-       for concatenated .gz files.
-*/
-local void check_header(s)
-    gz_stream *s;
-{
-    int method; /* method byte */
-    int flags;  /* flags byte */
-    uInt len;
-    int c;
-
-    /* Check the gzip magic header */
-    for (len = 0; len < 2; len++) {
-	c = get_byte(s);
-	if (c != gz_magic[len]) {
-	    if (len != 0) s->stream.avail_in++, s->stream.next_in--;
-	    if (c != EOF) {
-		s->stream.avail_in++, s->stream.next_in--;
-		s->transparent = 1;
-	    }
-	    s->z_err = s->stream.avail_in != 0 ? Z_OK : Z_STREAM_END;
-	    return;
-	}
-    }
-    method = get_byte(s);
-    flags = get_byte(s);
-    if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
-	s->z_err = Z_DATA_ERROR;
-	return;
-    }
-
-    /* Discard time, xflags and OS code: */
-    for (len = 0; len < 6; len++) (void)get_byte(s);
-
-    if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */
-	len  =  (uInt)get_byte(s);
-	len += ((uInt)get_byte(s))<<8;
-	/* len is garbage if EOF but the loop below will quit anyway */
-	while (len-- != 0 && get_byte(s) != EOF) ;
-    }
-    if ((flags & ORIG_NAME) != 0) { /* skip the original file name */
-	while ((c = get_byte(s)) != 0 && c != EOF) ;
-    }
-    if ((flags & COMMENT) != 0) {   /* skip the .gz file comment */
-	while ((c = get_byte(s)) != 0 && c != EOF) ;
-    }
-    if ((flags & HEAD_CRC) != 0) {  /* skip the header crc */
-	for (len = 0; len < 2; len++) (void)get_byte(s);
-    }
-    s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK;
-}
-
- /* ===========================================================================
- * Cleanup then free the given gz_stream. Return a zlib error code.
-   Try freeing in the reverse order of allocations.
- */
-local int destroy (s)
-    gz_stream *s;
-{
-    int err = Z_OK;
-
-    if (!s) return Z_STREAM_ERROR;
-
-    TRYFREE(s->msg);
-
-    if (s->stream.state != NULL) {
-	if (s->mode == 'w') {
-#ifdef NO_DEFLATE
-	    err = Z_STREAM_ERROR;
-#else
-	    err = deflateEnd(&(s->stream));
-#endif
-	} else if (s->mode == 'r') {
-	    err = inflateEnd(&(s->stream));
-	}
-    }
-    if (s->file != NULL && fclose(s->file)) {
-#ifdef ESPIPE
-	if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */
-#endif
-	    err = Z_ERRNO;
-    }
-    if (s->z_err < 0) err = s->z_err;
-
-    TRYFREE(s->inbuf);
-    TRYFREE(s->outbuf);
-    TRYFREE(s->path);
-    TRYFREE(s);
-    return err;
-}
-
-/* ===========================================================================
-     Reads the given number of uncompressed bytes from the compressed file.
-   gzread returns the number of bytes actually read (0 for end of file).
-*/
-int ZEXPORT gzread (file, buf, len)
-    gzFile file;
-    voidp buf;
-    unsigned len;
-{
-    gz_stream *s = (gz_stream*)file;
-    Bytef *start = (Bytef*)buf; /* starting point for crc computation */
-    Byte  *next_out; /* == stream.next_out but not forced far (for MSDOS) */
-
-    if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR;
-
-    if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1;
-    if (s->z_err == Z_STREAM_END) return 0;  /* EOF */
-
-    next_out = (Byte*)buf;
-    s->stream.next_out = (Bytef*)buf;
-    s->stream.avail_out = len;
-
-    while (s->stream.avail_out != 0) {
-
-	if (s->transparent) {
-	    /* Copy first the lookahead bytes: */
-	    uInt n = s->stream.avail_in;
-	    if (n > s->stream.avail_out) n = s->stream.avail_out;
-	    if (n > 0) {
-		zmemcpy(s->stream.next_out, s->stream.next_in, n);
-		next_out += n;
-		s->stream.next_out = next_out;
-		s->stream.next_in   += n;
-		s->stream.avail_out -= n;
-		s->stream.avail_in  -= n;
-	    }
-	    if (s->stream.avail_out > 0) {
-		s->stream.avail_out -= fread(next_out, 1, s->stream.avail_out,
-					     s->file);
-	    }
-	    len -= s->stream.avail_out;
-	    s->stream.total_in  += (uLong)len;
-	    s->stream.total_out += (uLong)len;
-            if (len == 0) s->z_eof = 1;
-	    return (int)len;
-	}
-        if (s->stream.avail_in == 0 && !s->z_eof) {
-
-            errno = 0;
-            s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file);
-            if (s->stream.avail_in == 0) {
-                s->z_eof = 1;
-		if (ferror(s->file)) {
-		    s->z_err = Z_ERRNO;
-		    break;
-		}
-            }
-            s->stream.next_in = s->inbuf;
-        }
-        s->z_err = inflate(&(s->stream), Z_NO_FLUSH);
-
-	if (s->z_err == Z_STREAM_END) {
-	    /* Check CRC and original size */
-	    s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
-	    start = s->stream.next_out;
-
-	    if (getLong(s) != s->crc) {
-		s->z_err = Z_DATA_ERROR;
-	    } else {
-	        (void)getLong(s);
-                /* The uncompressed length returned by above getlong() may
-                 * be different from s->stream.total_out) in case of
-		 * concatenated .gz files. Check for such files:
-		 */
-		check_header(s);
-		if (s->z_err == Z_OK) {
-		    uLong total_in = s->stream.total_in;
-		    uLong total_out = s->stream.total_out;
-
-		    inflateReset(&(s->stream));
-		    s->stream.total_in = total_in;
-		    s->stream.total_out = total_out;
-		    s->crc = crc32(0L, Z_NULL, 0);
-		}
-	    }
-	}
-	if (s->z_err != Z_OK || s->z_eof) break;
-    }
-    s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
-
-    return (int)(len - s->stream.avail_out);
-}
-
-
-/* ===========================================================================
-      Reads one byte from the compressed file. gzgetc returns this byte
-   or -1 in case of end of file or error.
-*/
-int ZEXPORT gzgetc(file)
-    gzFile file;
-{
-    unsigned char c;
-
-    return gzread(file, &c, 1) == 1 ? c : -1;
-}
-
-
-/* ===========================================================================
-      Reads bytes from the compressed file until len-1 characters are
-   read, or a newline character is read and transferred to buf, or an
-   end-of-file condition is encountered.  The string is then terminated
-   with a null character.
-      gzgets returns buf, or Z_NULL in case of error.
-
-      The current implementation is not optimized at all.
-*/
-char * ZEXPORT gzgets(file, buf, len)
-    gzFile file;
-    char *buf;
-    int len;
-{
-    char *b = buf;
-    if (buf == Z_NULL || len <= 0) return Z_NULL;
-
-    while (--len > 0 && gzread(file, buf, 1) == 1 && *buf++ != '\n') ;
-    *buf = '\0';
-    return b == buf && len > 0 ? Z_NULL : b;
-}
-
-
-#ifndef NO_DEFLATE
-/* ===========================================================================
-     Writes the given number of uncompressed bytes into the compressed file.
-   gzwrite returns the number of bytes actually written (0 in case of error).
-*/
-int ZEXPORT gzwrite (file, buf, len)
-    gzFile file;
-    const voidp buf;
-    unsigned len;
-{
-    gz_stream *s = (gz_stream*)file;
-
-    if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
-
-    s->stream.next_in = (Bytef*)buf;
-    s->stream.avail_in = len;
-
-    while (s->stream.avail_in != 0) {
-
-        if (s->stream.avail_out == 0) {
-
-            s->stream.next_out = s->outbuf;
-            if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) {
-                s->z_err = Z_ERRNO;
-                break;
-            }
-            s->stream.avail_out = Z_BUFSIZE;
-        }
-        s->z_err = deflate(&(s->stream), Z_NO_FLUSH);
-        if (s->z_err != Z_OK) break;
-    }
-    s->crc = crc32(s->crc, (const Bytef *)buf, len);
-
-    return (int)(len - s->stream.avail_in);
-}
-
-/* ===========================================================================
-     Converts, formats, and writes the args to the compressed file under
-   control of the format string, as in fprintf. gzprintf returns the number of
-   uncompressed bytes actually written (0 in case of error).
-*/
-#ifdef STDC
-#include 
-
-int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...)
-{
-    char buf[Z_PRINTF_BUFSIZE];
-    va_list va;
-    int len;
-
-    va_start(va, format);
-#ifdef HAS_vsnprintf
-    (void)vsnprintf(buf, sizeof(buf), format, va);
-#else
-    (void)vsprintf(buf, format, va);
-#endif
-    va_end(va);
-    len = strlen(buf); /* some *sprintf don't return the nb of bytes written */
-    if (len <= 0) return 0;
-
-    return gzwrite(file, buf, (unsigned)len);
-}
-#else /* not ANSI C */
-
-int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
-	               a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
-    gzFile file;
-    const char *format;
-    int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
-	a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
-{
-    char buf[Z_PRINTF_BUFSIZE];
-    int len;
-
-#ifdef HAS_snprintf
-    snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8,
-	     a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
-#else
-    sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8,
-	    a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
-#endif
-    len = strlen(buf); /* old sprintf doesn't return the nb of bytes written */
-    if (len <= 0) return 0;
-
-    return gzwrite(file, buf, len);
-}
-#endif
-
-/* ===========================================================================
-      Writes c, converted to an unsigned char, into the compressed file.
-   gzputc returns the value that was written, or -1 in case of error.
-*/
-int ZEXPORT gzputc(file, c)
-    gzFile file;
-    int c;
-{
-    unsigned char cc = (unsigned char) c; /* required for big endian systems */
-
-    return gzwrite(file, &cc, 1) == 1 ? (int)cc : -1;
-}
-
-
-/* ===========================================================================
-      Writes the given null-terminated string to the compressed file, excluding
-   the terminating null character.
-      gzputs returns the number of characters written, or -1 in case of error.
-*/
-int ZEXPORT gzputs(file, s)
-    gzFile file;
-    const char *s;
-{
-    return gzwrite(file, (char*)s, (unsigned)strlen(s));
-}
-
-
-/* ===========================================================================
-     Flushes all pending output into the compressed file. The parameter
-   flush is as in the deflate() function.
-*/
-local int do_flush (file, flush)
-    gzFile file;
-    int flush;
-{
-    uInt len;
-    int done = 0;
-    gz_stream *s = (gz_stream*)file;
-
-    if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
-
-    s->stream.avail_in = 0; /* should be zero already anyway */
-
-    for (;;) {
-        len = Z_BUFSIZE - s->stream.avail_out;
-
-        if (len != 0) {
-            if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) {
-                s->z_err = Z_ERRNO;
-                return Z_ERRNO;
-            }
-            s->stream.next_out = s->outbuf;
-            s->stream.avail_out = Z_BUFSIZE;
-        }
-        if (done) break;
-        s->z_err = deflate(&(s->stream), flush);
-
-	/* Ignore the second of two consecutive flushes: */
-	if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK;
-
-        /* deflate has finished flushing only when it hasn't used up
-         * all the available space in the output buffer: 
-         */
-        done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END);
- 
-        if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break;
-    }
-    return  s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
-}
-
-int ZEXPORT gzflush (file, flush)
-     gzFile file;
-     int flush;
-{
-    gz_stream *s = (gz_stream*)file;
-    int err = do_flush (file, flush);
-
-    if (err) return err;
-    fflush(s->file);
-    return  s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
-}
-#endif /* NO_DEFLATE */
-
-/* ===========================================================================
-      Sets the starting position for the next gzread or gzwrite on the given
-   compressed file. The offset represents a number of bytes in the
-      gzseek returns the resulting offset location as measured in bytes from
-   the beginning of the uncompressed stream, or -1 in case of error.
-      SEEK_END is not implemented, returns error.
-      In this version of the library, gzseek can be extremely slow.
-*/
-z_off_t ZEXPORT gzseek (file, offset, whence)
-    gzFile file;
-    z_off_t offset;
-    int whence;
-{
-    gz_stream *s = (gz_stream*)file;
-
-    if (s == NULL || whence == SEEK_END ||
-	s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) {
-	return -1L;
-    }
-    
-    if (s->mode == 'w') {
-#ifdef NO_DEFLATE
-	return -1L;
-#else
-	if (whence == SEEK_SET) {
-	    offset -= s->stream.total_in;
-	}
-	if (offset < 0) return -1L;
-
-	/* At this point, offset is the number of zero bytes to write. */
-	if (s->inbuf == Z_NULL) {
-	    s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */
-	    zmemzero(s->inbuf, Z_BUFSIZE);
-	}
-	while (offset > 0)  {
-	    uInt size = Z_BUFSIZE;
-	    if (offset < Z_BUFSIZE) size = (uInt)offset;
-
-	    size = gzwrite(file, s->inbuf, size);
-	    if (size == 0) return -1L;
-
-	    offset -= size;
-	}
-	return (z_off_t)s->stream.total_in;
-#endif
-    }
-    /* Rest of function is for reading only */
-
-    /* compute absolute position */
-    if (whence == SEEK_CUR) {
-	offset += s->stream.total_out;
-    }
-    if (offset < 0) return -1L;
-
-    if (s->transparent) {
-	/* map to fseek */
-	s->stream.avail_in = 0;
-	s->stream.next_in = s->inbuf;
-        if (fseek(s->file, offset, SEEK_SET) < 0) return -1L;
-
-	s->stream.total_in = s->stream.total_out = (uLong)offset;
-	return offset;
-    }
-
-    /* For a negative seek, rewind and use positive seek */
-    if ((uLong)offset >= s->stream.total_out) {
-	offset -= s->stream.total_out;
-    } else if (gzrewind(file) < 0) {
-	return -1L;
-    }
-    /* offset is now the number of bytes to skip. */
-
-    if (offset != 0 && s->outbuf == Z_NULL) {
-	s->outbuf = (Byte*)ALLOC(Z_BUFSIZE);
-    }
-    while (offset > 0)  {
-	int size = Z_BUFSIZE;
-	if (offset < Z_BUFSIZE) size = (int)offset;
-
-	size = gzread(file, s->outbuf, (uInt)size);
-	if (size <= 0) return -1L;
-	offset -= size;
-    }
-    return (z_off_t)s->stream.total_out;
-}
-
-/* ===========================================================================
-     Rewinds input file. 
-*/
-int ZEXPORT gzrewind (file)
-    gzFile file;
-{
-    gz_stream *s = (gz_stream*)file;
-    
-    if (s == NULL || s->mode != 'r') return -1;
-
-    s->z_err = Z_OK;
-    s->z_eof = 0;
-    s->stream.avail_in = 0;
-    s->stream.next_in = s->inbuf;
-    s->crc = crc32(0L, Z_NULL, 0);
-	
-    if (s->startpos == 0) { /* not a compressed file */
-	rewind(s->file);
-	return 0;
-    }
-
-    (void) inflateReset(&s->stream);
-    return fseek(s->file, s->startpos, SEEK_SET);
-}
-
-/* ===========================================================================
-     Returns the starting position for the next gzread or gzwrite on the
-   given compressed file. This position represents a number of bytes in the
-   uncompressed data stream.
-*/
-z_off_t ZEXPORT gztell (file)
-    gzFile file;
-{
-    return gzseek(file, 0L, SEEK_CUR);
-}
-
-/* ===========================================================================
-     Returns 1 when EOF has previously been detected reading the given
-   input stream, otherwise zero.
-*/
-int ZEXPORT gzeof (file)
-    gzFile file;
-{
-    gz_stream *s = (gz_stream*)file;
-    
-    return (s == NULL || s->mode != 'r') ? 0 : s->z_eof;
-}
-
-/* ===========================================================================
-   Outputs a long in LSB order to the given file
-*/
-local void putLong (file, x)
-    FILE *file;
-    uLong x;
-{
-    int n;
-    for (n = 0; n < 4; n++) {
-        fputc((int)(x & 0xff), file);
-        x >>= 8;
-    }
-}
-
-/* ===========================================================================
-   Reads a long in LSB order from the given gz_stream. Sets z_err in case
-   of error.
-*/
-local uLong getLong (s)
-    gz_stream *s;
-{
-    uLong x = (uLong)get_byte(s);
-    int c;
-
-    x += ((uLong)get_byte(s))<<8;
-    x += ((uLong)get_byte(s))<<16;
-    c = get_byte(s);
-    if (c == EOF) s->z_err = Z_DATA_ERROR;
-    x += ((uLong)c)<<24;
-    return x;
-}
-
-/* ===========================================================================
-     Flushes all pending output if necessary, closes the compressed file
-   and deallocates all the (de)compression state.
-*/
-int ZEXPORT gzclose (file)
-    gzFile file;
-{
-    int err;
-    gz_stream *s = (gz_stream*)file;
-
-    if (s == NULL) return Z_STREAM_ERROR;
-
-    if (s->mode == 'w') {
-#ifdef NO_DEFLATE
-	return Z_STREAM_ERROR;
-#else
-        err = do_flush (file, Z_FINISH);
-        if (err != Z_OK) return destroy((gz_stream*)file);
-
-        putLong (s->file, s->crc);
-        putLong (s->file, s->stream.total_in);
-#endif
-    }
-    return destroy((gz_stream*)file);
-}
-
-/* ===========================================================================
-     Returns the error message for the last error which occured on the
-   given compressed file. errnum is set to zlib error number. If an
-   error occured in the file system and not in the compression library,
-   errnum is set to Z_ERRNO and the application may consult errno
-   to get the exact error code.
-*/
-const char*  ZEXPORT gzerror (file, errnum)
-    gzFile file;
-    int *errnum;
-{
-    char *m;
-    gz_stream *s = (gz_stream*)file;
-
-    if (s == NULL) {
-        *errnum = Z_STREAM_ERROR;
-        return (const char*)ERR_MSG(Z_STREAM_ERROR);
-    }
-    *errnum = s->z_err;
-    if (*errnum == Z_OK) return (const char*)"";
-
-    m =  (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg);
-
-    if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err);
-
-    TRYFREE(s->msg);
-    s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3);
-    strcpy(s->msg, s->path);
-    strcat(s->msg, ": ");
-    strcat(s->msg, m);
-    return (const char*)s->msg;
-}
diff --git a/Lib/zlib/infblock.c b/Lib/zlib/infblock.c
deleted file mode 100644
index f4920faa5..000000000
--- a/Lib/zlib/infblock.c
+++ /dev/null
@@ -1,398 +0,0 @@
-/* infblock.c -- interpret and process block types to last block
- * Copyright (C) 1995-1998 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-#include "zutil.h"
-#include "infblock.h"
-#include "inftrees.h"
-#include "infcodes.h"
-#include "infutil.h"
-
-struct inflate_codes_state {int dummy;}; /* for buggy compilers */
-
-/* simplify the use of the inflate_huft type with some defines */
-#define exop word.what.Exop
-#define bits word.what.Bits
-
-/* Table for deflate from PKZIP's appnote.txt. */
-local const uInt border[] = { /* Order of the bit length code lengths */
-        16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
-
-/*
-   Notes beyond the 1.93a appnote.txt:
-
-   1. Distance pointers never point before the beginning of the output
-      stream.
-   2. Distance pointers can point back across blocks, up to 32k away.
-   3. There is an implied maximum of 7 bits for the bit length table and
-      15 bits for the actual data.
-   4. If only one code exists, then it is encoded using one bit.  (Zero
-      would be more efficient, but perhaps a little confusing.)  If two
-      codes exist, they are coded using one bit each (0 and 1).
-   5. There is no way of sending zero distance codes--a dummy must be
-      sent if there are none.  (History: a pre 2.0 version of PKZIP would
-      store blocks with no distance codes, but this was discovered to be
-      too harsh a criterion.)  Valid only for 1.93a.  2.04c does allow
-      zero distance codes, which is sent as one code of zero bits in
-      length.
-   6. There are up to 286 literal/length codes.  Code 256 represents the
-      end-of-block.  Note however that the static length tree defines
-      288 codes just to fill out the Huffman codes.  Codes 286 and 287
-      cannot be used though, since there is no length base or extra bits
-      defined for them.  Similarily, there are up to 30 distance codes.
-      However, static trees define 32 codes (all 5 bits) to fill out the
-      Huffman codes, but the last two had better not show up in the data.
-   7. Unzip can check dynamic Huffman blocks for complete code sets.
-      The exception is that a single code would not be complete (see #4).
-   8. The five bits following the block type is really the number of
-      literal codes sent minus 257.
-   9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
-      (1+6+6).  Therefore, to output three times the length, you output
-      three codes (1+1+1), whereas to output four times the same length,
-      you only need two codes (1+3).  Hmm.
-  10. In the tree reconstruction algorithm, Code = Code + Increment
-      only if BitLength(i) is not zero.  (Pretty obvious.)
-  11. Correction: 4 Bits: # of Bit Length codes - 4     (4 - 19)
-  12. Note: length code 284 can represent 227-258, but length code 285
-      really is 258.  The last length deserves its own, short code
-      since it gets used a lot in very redundant files.  The length
-      258 is special since 258 - 3 (the min match length) is 255.
-  13. The literal/length and distance code bit lengths are read as a
-      single stream of lengths.  It is possible (and advantageous) for
-      a repeat code (16, 17, or 18) to go across the boundary between
-      the two sets of lengths.
- */
-
-
-void inflate_blocks_reset(s, z, c)
-inflate_blocks_statef *s;
-z_streamp z;
-uLongf *c;
-{
-  if (c != Z_NULL)
-    *c = s->check;
-  if (s->mode == BTREE || s->mode == DTREE)
-    ZFREE(z, s->sub.trees.blens);
-  if (s->mode == CODES)
-    inflate_codes_free(s->sub.decode.codes, z);
-  s->mode = TYPE;
-  s->bitk = 0;
-  s->bitb = 0;
-  s->read = s->write = s->window;
-  if (s->checkfn != Z_NULL)
-    z->adler = s->check = (*s->checkfn)(0L, (const Bytef *)Z_NULL, 0);
-  Tracev((stderr, "inflate:   blocks reset\n"));
-}
-
-
-inflate_blocks_statef *inflate_blocks_new(z, c, w)
-z_streamp z;
-check_func c;
-uInt w;
-{
-  inflate_blocks_statef *s;
-
-  if ((s = (inflate_blocks_statef *)ZALLOC
-       (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL)
-    return s;
-  if ((s->hufts =
-       (inflate_huft *)ZALLOC(z, sizeof(inflate_huft), MANY)) == Z_NULL)
-  {
-    ZFREE(z, s);
-    return Z_NULL;
-  }
-  if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL)
-  {
-    ZFREE(z, s->hufts);
-    ZFREE(z, s);
-    return Z_NULL;
-  }
-  s->end = s->window + w;
-  s->checkfn = c;
-  s->mode = TYPE;
-  Tracev((stderr, "inflate:   blocks allocated\n"));
-  inflate_blocks_reset(s, z, Z_NULL);
-  return s;
-}
-
-
-int inflate_blocks(s, z, r)
-inflate_blocks_statef *s;
-z_streamp z;
-int r;
-{
-  uInt t;               /* temporary storage */
-  uLong b;              /* bit buffer */
-  uInt k;               /* bits in bit buffer */
-  Bytef *p;             /* input data pointer */
-  uInt n;               /* bytes available there */
-  Bytef *q;             /* output window write pointer */
-  uInt m;               /* bytes to end of window or read pointer */
-
-  /* copy input/output information to locals (UPDATE macro restores) */
-  LOAD
-
-  /* process input based on current state */
-  while (1) switch (s->mode)
-  {
-    case TYPE:
-      NEEDBITS(3)
-      t = (uInt)b & 7;
-      s->last = t & 1;
-      switch (t >> 1)
-      {
-        case 0:                         /* stored */
-          Tracev((stderr, "inflate:     stored block%s\n",
-                 s->last ? " (last)" : ""));
-          DUMPBITS(3)
-          t = k & 7;                    /* go to byte boundary */
-          DUMPBITS(t)
-          s->mode = LENS;               /* get length of stored block */
-          break;
-        case 1:                         /* fixed */
-          Tracev((stderr, "inflate:     fixed codes block%s\n",
-                 s->last ? " (last)" : ""));
-          {
-            uInt bl, bd;
-            inflate_huft *tl, *td;
-
-            inflate_trees_fixed(&bl, &bd, &tl, &td, z);
-            s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z);
-            if (s->sub.decode.codes == Z_NULL)
-            {
-              r = Z_MEM_ERROR;
-              LEAVE
-            }
-          }
-          DUMPBITS(3)
-          s->mode = CODES;
-          break;
-        case 2:                         /* dynamic */
-          Tracev((stderr, "inflate:     dynamic codes block%s\n",
-                 s->last ? " (last)" : ""));
-          DUMPBITS(3)
-          s->mode = TABLE;
-          break;
-        case 3:                         /* illegal */
-          DUMPBITS(3)
-          s->mode = BAD;
-          z->msg = (char*)"invalid block type";
-          r = Z_DATA_ERROR;
-          LEAVE
-      }
-      break;
-    case LENS:
-      NEEDBITS(32)
-      if ((((~b) >> 16) & 0xffff) != (b & 0xffff))
-      {
-        s->mode = BAD;
-        z->msg = (char*)"invalid stored block lengths";
-        r = Z_DATA_ERROR;
-        LEAVE
-      }
-      s->sub.left = (uInt)b & 0xffff;
-      b = k = 0;                      /* dump bits */
-      Tracev((stderr, "inflate:       stored length %u\n", s->sub.left));
-      s->mode = s->sub.left ? STORED : (s->last ? DRY : TYPE);
-      break;
-    case STORED:
-      if (n == 0)
-        LEAVE
-      NEEDOUT
-      t = s->sub.left;
-      if (t > n) t = n;
-      if (t > m) t = m;
-      zmemcpy(q, p, t);
-      p += t;  n -= t;
-      q += t;  m -= t;
-      if ((s->sub.left -= t) != 0)
-        break;
-      Tracev((stderr, "inflate:       stored end, %lu total out\n",
-              z->total_out + (q >= s->read ? q - s->read :
-              (s->end - s->read) + (q - s->window))));
-      s->mode = s->last ? DRY : TYPE;
-      break;
-    case TABLE:
-      NEEDBITS(14)
-      s->sub.trees.table = t = (uInt)b & 0x3fff;
-#ifndef PKZIP_BUG_WORKAROUND
-      if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
-      {
-        s->mode = BAD;
-        z->msg = (char*)"too many length or distance symbols";
-        r = Z_DATA_ERROR;
-        LEAVE
-      }
-#endif
-      t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
-      if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL)
-      {
-        r = Z_MEM_ERROR;
-        LEAVE
-      }
-      DUMPBITS(14)
-      s->sub.trees.index = 0;
-      Tracev((stderr, "inflate:       table sizes ok\n"));
-      s->mode = BTREE;
-    case BTREE:
-      while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10))
-      {
-        NEEDBITS(3)
-        s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7;
-        DUMPBITS(3)
-      }
-      while (s->sub.trees.index < 19)
-        s->sub.trees.blens[border[s->sub.trees.index++]] = 0;
-      s->sub.trees.bb = 7;
-      t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb,
-                             &s->sub.trees.tb, s->hufts, z);
-      if (t != Z_OK)
-      {
-        ZFREE(z, s->sub.trees.blens);
-        r = t;
-        if (r == Z_DATA_ERROR)
-          s->mode = BAD;
-        LEAVE
-      }
-      s->sub.trees.index = 0;
-      Tracev((stderr, "inflate:       bits tree ok\n"));
-      s->mode = DTREE;
-    case DTREE:
-      while (t = s->sub.trees.table,
-             s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))
-      {
-        inflate_huft *h;
-        uInt i, j, c;
-
-        t = s->sub.trees.bb;
-        NEEDBITS(t)
-        h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]);
-        t = h->bits;
-        c = h->base;
-        if (c < 16)
-        {
-          DUMPBITS(t)
-          s->sub.trees.blens[s->sub.trees.index++] = c;
-        }
-        else /* c == 16..18 */
-        {
-          i = c == 18 ? 7 : c - 14;
-          j = c == 18 ? 11 : 3;
-          NEEDBITS(t + i)
-          DUMPBITS(t)
-          j += (uInt)b & inflate_mask[i];
-          DUMPBITS(i)
-          i = s->sub.trees.index;
-          t = s->sub.trees.table;
-          if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
-              (c == 16 && i < 1))
-          {
-            ZFREE(z, s->sub.trees.blens);
-            s->mode = BAD;
-            z->msg = (char*)"invalid bit length repeat";
-            r = Z_DATA_ERROR;
-            LEAVE
-          }
-          c = c == 16 ? s->sub.trees.blens[i - 1] : 0;
-          do {
-            s->sub.trees.blens[i++] = c;
-          } while (--j);
-          s->sub.trees.index = i;
-        }
-      }
-      s->sub.trees.tb = Z_NULL;
-      {
-        uInt bl, bd;
-        inflate_huft *tl, *td;
-        inflate_codes_statef *c;
-
-        bl = 9;         /* must be <= 9 for lookahead assumptions */
-        bd = 6;         /* must be <= 9 for lookahead assumptions */
-        t = s->sub.trees.table;
-        t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f),
-                                  s->sub.trees.blens, &bl, &bd, &tl, &td,
-                                  s->hufts, z);
-        ZFREE(z, s->sub.trees.blens);
-        if (t != Z_OK)
-        {
-          if (t == (uInt)Z_DATA_ERROR)
-            s->mode = BAD;
-          r = t;
-          LEAVE
-        }
-        Tracev((stderr, "inflate:       trees ok\n"));
-        if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL)
-        {
-          r = Z_MEM_ERROR;
-          LEAVE
-        }
-        s->sub.decode.codes = c;
-      }
-      s->mode = CODES;
-    case CODES:
-      UPDATE
-      if ((r = inflate_codes(s, z, r)) != Z_STREAM_END)
-        return inflate_flush(s, z, r);
-      r = Z_OK;
-      inflate_codes_free(s->sub.decode.codes, z);
-      LOAD
-      Tracev((stderr, "inflate:       codes end, %lu total out\n",
-              z->total_out + (q >= s->read ? q - s->read :
-              (s->end - s->read) + (q - s->window))));
-      if (!s->last)
-      {
-        s->mode = TYPE;
-        break;
-      }
-      s->mode = DRY;
-    case DRY:
-      FLUSH
-      if (s->read != s->write)
-        LEAVE
-      s->mode = DONE;
-    case DONE:
-      r = Z_STREAM_END;
-      LEAVE
-    case BAD:
-      r = Z_DATA_ERROR;
-      LEAVE
-    default:
-      r = Z_STREAM_ERROR;
-      LEAVE
-  }
-}
-
-
-int inflate_blocks_free(s, z)
-inflate_blocks_statef *s;
-z_streamp z;
-{
-  inflate_blocks_reset(s, z, Z_NULL);
-  ZFREE(z, s->window);
-  ZFREE(z, s->hufts);
-  ZFREE(z, s);
-  Tracev((stderr, "inflate:   blocks freed\n"));
-  return Z_OK;
-}
-
-
-void inflate_set_dictionary(s, d, n)
-inflate_blocks_statef *s;
-const Bytef *d;
-uInt  n;
-{
-  zmemcpy(s->window, d, n);
-  s->read = s->write = s->window + n;
-}
-
-
-/* Returns true if inflate is currently at the end of a block generated
- * by Z_SYNC_FLUSH or Z_FULL_FLUSH. 
- * IN assertion: s != Z_NULL
- */
-int inflate_blocks_sync_point(s)
-inflate_blocks_statef *s;
-{
-  return s->mode == LENS;
-}
diff --git a/Lib/zlib/infblock.h b/Lib/zlib/infblock.h
deleted file mode 100644
index bd25c8075..000000000
--- a/Lib/zlib/infblock.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* infblock.h -- header to use infblock.c
- * Copyright (C) 1995-1998 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-struct inflate_blocks_state;
-typedef struct inflate_blocks_state FAR inflate_blocks_statef;
-
-extern inflate_blocks_statef * inflate_blocks_new OF((
-    z_streamp z,
-    check_func c,               /* check function */
-    uInt w));                   /* window size */
-
-extern int inflate_blocks OF((
-    inflate_blocks_statef *,
-    z_streamp ,
-    int));                      /* initial return code */
-
-extern void inflate_blocks_reset OF((
-    inflate_blocks_statef *,
-    z_streamp ,
-    uLongf *));                  /* check value on output */
-
-extern int inflate_blocks_free OF((
-    inflate_blocks_statef *,
-    z_streamp));
-
-extern void inflate_set_dictionary OF((
-    inflate_blocks_statef *s,
-    const Bytef *d,  /* dictionary */
-    uInt  n));       /* dictionary length */
-
-extern int inflate_blocks_sync_point OF((
-    inflate_blocks_statef *s));
diff --git a/Lib/zlib/infcodes.c b/Lib/zlib/infcodes.c
deleted file mode 100644
index d4e5ee9a5..000000000
--- a/Lib/zlib/infcodes.c
+++ /dev/null
@@ -1,257 +0,0 @@
-/* infcodes.c -- process literals and length/distance pairs
- * Copyright (C) 1995-1998 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-#include "zutil.h"
-#include "inftrees.h"
-#include "infblock.h"
-#include "infcodes.h"
-#include "infutil.h"
-#include "inffast.h"
-
-/* simplify the use of the inflate_huft type with some defines */
-#define exop word.what.Exop
-#define bits word.what.Bits
-
-typedef enum {        /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
-      START,    /* x: set up for LEN */
-      LEN,      /* i: get length/literal/eob next */
-      LENEXT,   /* i: getting length extra (have base) */
-      DIST,     /* i: get distance next */
-      DISTEXT,  /* i: getting distance extra */
-      COPY,     /* o: copying bytes in window, waiting for space */
-      LIT,      /* o: got literal, waiting for output space */
-      WASH,     /* o: got eob, possibly still output waiting */
-      END,      /* x: got eob and all data flushed */
-      BADCODE}  /* x: got error */
-inflate_codes_mode;
-
-/* inflate codes private state */
-struct inflate_codes_state {
-
-  /* mode */
-  inflate_codes_mode mode;      /* current inflate_codes mode */
-
-  /* mode dependent information */
-  uInt len;
-  union {
-    struct {
-      inflate_huft *tree;       /* pointer into tree */
-      uInt need;                /* bits needed */
-    } code;             /* if LEN or DIST, where in tree */
-    uInt lit;           /* if LIT, literal */
-    struct {
-      uInt get;                 /* bits to get for extra */
-      uInt dist;                /* distance back to copy from */
-    } copy;             /* if EXT or COPY, where and how much */
-  } sub;                /* submode */
-
-  /* mode independent information */
-  Byte lbits;           /* ltree bits decoded per branch */
-  Byte dbits;           /* dtree bits decoder per branch */
-  inflate_huft *ltree;          /* literal/length/eob tree */
-  inflate_huft *dtree;          /* distance tree */
-
-};
-
-
-inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z)
-uInt bl, bd;
-inflate_huft *tl;
-inflate_huft *td; /* need separate declaration for Borland C++ */
-z_streamp z;
-{
-  inflate_codes_statef *c;
-
-  if ((c = (inflate_codes_statef *)
-       ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL)
-  {
-    c->mode = START;
-    c->lbits = (Byte)bl;
-    c->dbits = (Byte)bd;
-    c->ltree = tl;
-    c->dtree = td;
-    Tracev((stderr, "inflate:       codes new\n"));
-  }
-  return c;
-}
-
-
-int inflate_codes(s, z, r)
-inflate_blocks_statef *s;
-z_streamp z;
-int r;
-{
-  uInt j;               /* temporary storage */
-  inflate_huft *t;      /* temporary pointer */
-  uInt e;               /* extra bits or operation */
-  uLong b;              /* bit buffer */
-  uInt k;               /* bits in bit buffer */
-  Bytef *p;             /* input data pointer */
-  uInt n;               /* bytes available there */
-  Bytef *q;             /* output window write pointer */
-  uInt m;               /* bytes to end of window or read pointer */
-  Bytef *f;             /* pointer to copy strings from */
-  inflate_codes_statef *c = s->sub.decode.codes;  /* codes state */
-
-  /* copy input/output information to locals (UPDATE macro restores) */
-  LOAD
-
-  /* process input and output based on current state */
-  while (1) switch (c->mode)
-  {             /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
-    case START:         /* x: set up for LEN */
-#ifndef SLOW
-      if (m >= 258 && n >= 10)
-      {
-        UPDATE
-        r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z);
-        LOAD
-        if (r != Z_OK)
-        {
-          c->mode = r == Z_STREAM_END ? WASH : BADCODE;
-          break;
-        }
-      }
-#endif /* !SLOW */
-      c->sub.code.need = c->lbits;
-      c->sub.code.tree = c->ltree;
-      c->mode = LEN;
-    case LEN:           /* i: get length/literal/eob next */
-      j = c->sub.code.need;
-      NEEDBITS(j)
-      t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
-      DUMPBITS(t->bits)
-      e = (uInt)(t->exop);
-      if (e == 0)               /* literal */
-      {
-        c->sub.lit = t->base;
-        Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
-                 "inflate:         literal '%c'\n" :
-                 "inflate:         literal 0x%02x\n", t->base));
-        c->mode = LIT;
-        break;
-      }
-      if (e & 16)               /* length */
-      {
-        c->sub.copy.get = e & 15;
-        c->len = t->base;
-        c->mode = LENEXT;
-        break;
-      }
-      if ((e & 64) == 0)        /* next table */
-      {
-        c->sub.code.need = e;
-        c->sub.code.tree = t + t->base;
-        break;
-      }
-      if (e & 32)               /* end of block */
-      {
-        Tracevv((stderr, "inflate:         end of block\n"));
-        c->mode = WASH;
-        break;
-      }
-      c->mode = BADCODE;        /* invalid code */
-      z->msg = (char*)"invalid literal/length code";
-      r = Z_DATA_ERROR;
-      LEAVE
-    case LENEXT:        /* i: getting length extra (have base) */
-      j = c->sub.copy.get;
-      NEEDBITS(j)
-      c->len += (uInt)b & inflate_mask[j];
-      DUMPBITS(j)
-      c->sub.code.need = c->dbits;
-      c->sub.code.tree = c->dtree;
-      Tracevv((stderr, "inflate:         length %u\n", c->len));
-      c->mode = DIST;
-    case DIST:          /* i: get distance next */
-      j = c->sub.code.need;
-      NEEDBITS(j)
-      t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
-      DUMPBITS(t->bits)
-      e = (uInt)(t->exop);
-      if (e & 16)               /* distance */
-      {
-        c->sub.copy.get = e & 15;
-        c->sub.copy.dist = t->base;
-        c->mode = DISTEXT;
-        break;
-      }
-      if ((e & 64) == 0)        /* next table */
-      {
-        c->sub.code.need = e;
-        c->sub.code.tree = t + t->base;
-        break;
-      }
-      c->mode = BADCODE;        /* invalid code */
-      z->msg = (char*)"invalid distance code";
-      r = Z_DATA_ERROR;
-      LEAVE
-    case DISTEXT:       /* i: getting distance extra */
-      j = c->sub.copy.get;
-      NEEDBITS(j)
-      c->sub.copy.dist += (uInt)b & inflate_mask[j];
-      DUMPBITS(j)
-      Tracevv((stderr, "inflate:         distance %u\n", c->sub.copy.dist));
-      c->mode = COPY;
-    case COPY:          /* o: copying bytes in window, waiting for space */
-#ifndef __TURBOC__ /* Turbo C bug for following expression */
-      f = (uInt)(q - s->window) < c->sub.copy.dist ?
-          s->end - (c->sub.copy.dist - (q - s->window)) :
-          q - c->sub.copy.dist;
-#else
-      f = q - c->sub.copy.dist;
-      if ((uInt)(q - s->window) < c->sub.copy.dist)
-        f = s->end - (c->sub.copy.dist - (uInt)(q - s->window));
-#endif
-      while (c->len)
-      {
-        NEEDOUT
-        OUTBYTE(*f++)
-        if (f == s->end)
-          f = s->window;
-        c->len--;
-      }
-      c->mode = START;
-      break;
-    case LIT:           /* o: got literal, waiting for output space */
-      NEEDOUT
-      OUTBYTE(c->sub.lit)
-      c->mode = START;
-      break;
-    case WASH:          /* o: got eob, possibly more output */
-      if (k > 7)        /* return unused byte, if any */
-      {
-        Assert(k < 16, "inflate_codes grabbed too many bytes")
-        k -= 8;
-        n++;
-        p--;            /* can always return one */
-      }
-      FLUSH
-      if (s->read != s->write)
-        LEAVE
-      c->mode = END;
-    case END:
-      r = Z_STREAM_END;
-      LEAVE
-    case BADCODE:       /* x: got error */
-      r = Z_DATA_ERROR;
-      LEAVE
-    default:
-      r = Z_STREAM_ERROR;
-      LEAVE
-  }
-#ifdef NEED_DUMMY_RETURN
-  return Z_STREAM_ERROR;  /* Some dumb compilers complain without this */
-#endif
-}
-
-
-void inflate_codes_free(c, z)
-inflate_codes_statef *c;
-z_streamp z;
-{
-  ZFREE(z, c);
-  Tracev((stderr, "inflate:       codes free\n"));
-}
diff --git a/Lib/zlib/infcodes.h b/Lib/zlib/infcodes.h
deleted file mode 100644
index 6c750d896..000000000
--- a/Lib/zlib/infcodes.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* infcodes.h -- header to use infcodes.c
- * Copyright (C) 1995-1998 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-struct inflate_codes_state;
-typedef struct inflate_codes_state FAR inflate_codes_statef;
-
-extern inflate_codes_statef *inflate_codes_new OF((
-    uInt, uInt,
-    inflate_huft *, inflate_huft *,
-    z_streamp ));
-
-extern int inflate_codes OF((
-    inflate_blocks_statef *,
-    z_streamp ,
-    int));
-
-extern void inflate_codes_free OF((
-    inflate_codes_statef *,
-    z_streamp ));
-
diff --git a/Lib/zlib/inffast.c b/Lib/zlib/inffast.c
deleted file mode 100644
index 61a78ee93..000000000
--- a/Lib/zlib/inffast.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/* inffast.c -- process literals and length/distance pairs fast
- * Copyright (C) 1995-1998 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-#include "zutil.h"
-#include "inftrees.h"
-#include "infblock.h"
-#include "infcodes.h"
-#include "infutil.h"
-#include "inffast.h"
-
-struct inflate_codes_state {int dummy;}; /* for buggy compilers */
-
-/* simplify the use of the inflate_huft type with some defines */
-#define exop word.what.Exop
-#define bits word.what.Bits
-
-/* macros for bit input with no checking and for returning unused bytes */
-#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<avail_in-n;c=(k>>3)>3:c;n+=c;p-=c;k-=c<<3;}
-
-/* Called with number of bytes left to write in window at least 258
-   (the maximum string length) and number of input bytes available
-   at least ten.  The ten bytes are six bytes for the longest length/
-   distance pair plus four bytes for overloading the bit buffer. */
-
-int inflate_fast(bl, bd, tl, td, s, z)
-uInt bl, bd;
-inflate_huft *tl;
-inflate_huft *td; /* need separate declaration for Borland C++ */
-inflate_blocks_statef *s;
-z_streamp z;
-{
-  inflate_huft *t;      /* temporary pointer */
-  uInt e;               /* extra bits or operation */
-  uLong b;              /* bit buffer */
-  uInt k;               /* bits in bit buffer */
-  Bytef *p;             /* input data pointer */
-  uInt n;               /* bytes available there */
-  Bytef *q;             /* output window write pointer */
-  uInt m;               /* bytes to end of window or read pointer */
-  uInt ml;              /* mask for literal/length tree */
-  uInt md;              /* mask for distance tree */
-  uInt c;               /* bytes to copy */
-  uInt d;               /* distance back to copy from */
-  Bytef *r;             /* copy source pointer */
-
-  /* load input, output, bit values */
-  LOAD
-
-  /* initialize masks */
-  ml = inflate_mask[bl];
-  md = inflate_mask[bd];
-
-  /* do until not enough input or output space for fast loop */
-  do {                          /* assume called with m >= 258 && n >= 10 */
-    /* get literal/length code */
-    GRABBITS(20)                /* max bits for literal/length code */
-    if ((e = (t = tl + ((uInt)b & ml))->exop) == 0)
-    {
-      DUMPBITS(t->bits)
-      Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
-                "inflate:         * literal '%c'\n" :
-                "inflate:         * literal 0x%02x\n", t->base));
-      *q++ = (Byte)t->base;
-      m--;
-      continue;
-    }
-    do {
-      DUMPBITS(t->bits)
-      if (e & 16)
-      {
-        /* get extra bits for length */
-        e &= 15;
-        c = t->base + ((uInt)b & inflate_mask[e]);
-        DUMPBITS(e)
-        Tracevv((stderr, "inflate:         * length %u\n", c));
-
-        /* decode distance base of block to copy */
-        GRABBITS(15);           /* max bits for distance code */
-        e = (t = td + ((uInt)b & md))->exop;
-        do {
-          DUMPBITS(t->bits)
-          if (e & 16)
-          {
-            /* get extra bits to add to distance base */
-            e &= 15;
-            GRABBITS(e)         /* get extra bits (up to 13) */
-            d = t->base + ((uInt)b & inflate_mask[e]);
-            DUMPBITS(e)
-            Tracevv((stderr, "inflate:         * distance %u\n", d));
-
-            /* do the copy */
-            m -= c;
-            if ((uInt)(q - s->window) >= d)     /* offset before dest */
-            {                                   /*  just copy */
-              r = q - d;
-              *q++ = *r++;  c--;        /* minimum count is three, */
-              *q++ = *r++;  c--;        /*  so unroll loop a little */
-            }
-            else                        /* else offset after destination */
-            {
-              e = d - (uInt)(q - s->window); /* bytes from offset to end */
-              r = s->end - e;           /* pointer to offset */
-              if (c > e)                /* if source crosses, */
-              {
-                c -= e;                 /* copy to end of window */
-                do {
-                  *q++ = *r++;
-                } while (--e);
-                r = s->window;          /* copy rest from start of window */
-              }
-            }
-            do {                        /* copy all or what's left */
-              *q++ = *r++;
-            } while (--c);
-            break;
-          }
-          else if ((e & 64) == 0)
-          {
-            t += t->base;
-            e = (t += ((uInt)b & inflate_mask[e]))->exop;
-          }
-          else
-          {
-            z->msg = (char*)"invalid distance code";
-            UNGRAB
-            UPDATE
-            return Z_DATA_ERROR;
-          }
-        } while (1);
-        break;
-      }
-      if ((e & 64) == 0)
-      {
-        t += t->base;
-        if ((e = (t += ((uInt)b & inflate_mask[e]))->exop) == 0)
-        {
-          DUMPBITS(t->bits)
-          Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
-                    "inflate:         * literal '%c'\n" :
-                    "inflate:         * literal 0x%02x\n", t->base));
-          *q++ = (Byte)t->base;
-          m--;
-          break;
-        }
-      }
-      else if (e & 32)
-      {
-        Tracevv((stderr, "inflate:         * end of block\n"));
-        UNGRAB
-        UPDATE
-        return Z_STREAM_END;
-      }
-      else
-      {
-        z->msg = (char*)"invalid literal/length code";
-        UNGRAB
-        UPDATE
-        return Z_DATA_ERROR;
-      }
-    } while (1);
-  } while (m >= 258 && n >= 10);
-
-  /* not enough input or output--restore pointers and return */
-  UNGRAB
-  UPDATE
-  return Z_OK;
-}
diff --git a/Lib/zlib/inffast.h b/Lib/zlib/inffast.h
deleted file mode 100644
index 8facec553..000000000
--- a/Lib/zlib/inffast.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* inffast.h -- header to use inffast.c
- * Copyright (C) 1995-1998 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-extern int inflate_fast OF((
-    uInt,
-    uInt,
-    inflate_huft *,
-    inflate_huft *,
-    inflate_blocks_statef *,
-    z_streamp ));
diff --git a/Lib/zlib/inffixed.h b/Lib/zlib/inffixed.h
deleted file mode 100644
index 77f7e7631..000000000
--- a/Lib/zlib/inffixed.h
+++ /dev/null
@@ -1,151 +0,0 @@
-/* inffixed.h -- table for decoding fixed codes
- * Generated automatically by the maketree.c program
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-local uInt fixed_bl = 9;
-local uInt fixed_bd = 5;
-local inflate_huft fixed_tl[] = {
-    {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115},
-    {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},192},
-    {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},160},
-    {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},224},
-    {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},144},
-    {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},208},
-    {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},176},
-    {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},240},
-    {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227},
-    {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},200},
-    {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},168},
-    {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},232},
-    {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},152},
-    {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},216},
-    {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},184},
-    {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},248},
-    {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163},
-    {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},196},
-    {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},164},
-    {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},228},
-    {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},148},
-    {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},212},
-    {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},180},
-    {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},244},
-    {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0},
-    {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},204},
-    {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},172},
-    {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},236},
-    {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},156},
-    {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},220},
-    {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},188},
-    {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},252},
-    {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131},
-    {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},194},
-    {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},162},
-    {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},226},
-    {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},146},
-    {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},210},
-    {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},178},
-    {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},242},
-    {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258},
-    {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},202},
-    {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},170},
-    {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},234},
-    {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},154},
-    {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},218},
-    {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},186},
-    {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},250},
-    {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195},
-    {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},198},
-    {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},166},
-    {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},230},
-    {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},150},
-    {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},214},
-    {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},182},
-    {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},246},
-    {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0},
-    {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},206},
-    {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},174},
-    {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},238},
-    {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},158},
-    {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},222},
-    {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},190},
-    {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},254},
-    {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115},
-    {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},193},
-    {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},161},
-    {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},225},
-    {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},145},
-    {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},209},
-    {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},177},
-    {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},241},
-    {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227},
-    {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},201},
-    {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},169},
-    {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},233},
-    {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},153},
-    {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},217},
-    {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},185},
-    {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},249},
-    {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163},
-    {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},197},
-    {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},165},
-    {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},229},
-    {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},149},
-    {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},213},
-    {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},181},
-    {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},245},
-    {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0},
-    {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},205},
-    {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},173},
-    {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},237},
-    {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},157},
-    {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},221},
-    {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},189},
-    {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},253},
-    {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131},
-    {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},195},
-    {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},163},
-    {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},227},
-    {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},147},
-    {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},211},
-    {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},179},
-    {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},243},
-    {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258},
-    {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},203},
-    {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},171},
-    {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},235},
-    {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},155},
-    {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},219},
-    {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},187},
-    {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},251},
-    {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195},
-    {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},199},
-    {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},167},
-    {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},231},
-    {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},151},
-    {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},215},
-    {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},183},
-    {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},247},
-    {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0},
-    {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},207},
-    {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},175},
-    {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},239},
-    {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},159},
-    {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},223},
-    {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},191},
-    {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},255}
-  };
-local inflate_huft fixed_td[] = {
-    {{{80,5}},1}, {{{87,5}},257}, {{{83,5}},17}, {{{91,5}},4097},
-    {{{81,5}},5}, {{{89,5}},1025}, {{{85,5}},65}, {{{93,5}},16385},
-    {{{80,5}},3}, {{{88,5}},513}, {{{84,5}},33}, {{{92,5}},8193},
-    {{{82,5}},9}, {{{90,5}},2049}, {{{86,5}},129}, {{{192,5}},24577},
-    {{{80,5}},2}, {{{87,5}},385}, {{{83,5}},25}, {{{91,5}},6145},
-    {{{81,5}},7}, {{{89,5}},1537}, {{{85,5}},97}, {{{93,5}},24577},
-    {{{80,5}},4}, {{{88,5}},769}, {{{84,5}},49}, {{{92,5}},12289},
-    {{{82,5}},13}, {{{90,5}},3073}, {{{86,5}},193}, {{{192,5}},24577}
-  };
diff --git a/Lib/zlib/inflate.c b/Lib/zlib/inflate.c
deleted file mode 100644
index 32e9b8de6..000000000
--- a/Lib/zlib/inflate.c
+++ /dev/null
@@ -1,366 +0,0 @@
-/* inflate.c -- zlib interface to inflate modules
- * Copyright (C) 1995-1998 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-#include "zutil.h"
-#include "infblock.h"
-
-struct inflate_blocks_state {int dummy;}; /* for buggy compilers */
-
-typedef enum {
-      METHOD,   /* waiting for method byte */
-      FLAG,     /* waiting for flag byte */
-      DICT4,    /* four dictionary check bytes to go */
-      DICT3,    /* three dictionary check bytes to go */
-      DICT2,    /* two dictionary check bytes to go */
-      DICT1,    /* one dictionary check byte to go */
-      DICT0,    /* waiting for inflateSetDictionary */
-      BLOCKS,   /* decompressing blocks */
-      CHECK4,   /* four check bytes to go */
-      CHECK3,   /* three check bytes to go */
-      CHECK2,   /* two check bytes to go */
-      CHECK1,   /* one check byte to go */
-      DONE,     /* finished check, done */
-      BAD}      /* got an error--stay here */
-inflate_mode;
-
-/* inflate private state */
-struct internal_state {
-
-  /* mode */
-  inflate_mode  mode;   /* current inflate mode */
-
-  /* mode dependent information */
-  union {
-    uInt method;        /* if FLAGS, method byte */
-    struct {
-      uLong was;                /* computed check value */
-      uLong need;               /* stream check value */
-    } check;            /* if CHECK, check values to compare */
-    uInt marker;        /* if BAD, inflateSync's marker bytes count */
-  } sub;        /* submode */
-
-  /* mode independent information */
-  int  nowrap;          /* flag for no wrapper */
-  uInt wbits;           /* log2(window size)  (8..15, defaults to 15) */
-  inflate_blocks_statef 
-    *blocks;            /* current inflate_blocks state */
-
-};
-
-
-int ZEXPORT inflateReset(z)
-z_streamp z;
-{
-  if (z == Z_NULL || z->state == Z_NULL)
-    return Z_STREAM_ERROR;
-  z->total_in = z->total_out = 0;
-  z->msg = Z_NULL;
-  z->state->mode = z->state->nowrap ? BLOCKS : METHOD;
-  inflate_blocks_reset(z->state->blocks, z, Z_NULL);
-  Tracev((stderr, "inflate: reset\n"));
-  return Z_OK;
-}
-
-
-int ZEXPORT inflateEnd(z)
-z_streamp z;
-{
-  if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL)
-    return Z_STREAM_ERROR;
-  if (z->state->blocks != Z_NULL)
-    inflate_blocks_free(z->state->blocks, z);
-  ZFREE(z, z->state);
-  z->state = Z_NULL;
-  Tracev((stderr, "inflate: end\n"));
-  return Z_OK;
-}
-
-
-int ZEXPORT inflateInit2_(z, w, version, stream_size)
-z_streamp z;
-int w;
-const char *version;
-int stream_size;
-{
-  if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
-      stream_size != sizeof(z_stream))
-      return Z_VERSION_ERROR;
-
-  /* initialize state */
-  if (z == Z_NULL)
-    return Z_STREAM_ERROR;
-  z->msg = Z_NULL;
-  if (z->zalloc == Z_NULL)
-  {
-    z->zalloc = zcalloc;
-    z->opaque = (voidpf)0;
-  }
-  if (z->zfree == Z_NULL) z->zfree = zcfree;
-  if ((z->state = (struct internal_state FAR *)
-       ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL)
-    return Z_MEM_ERROR;
-  z->state->blocks = Z_NULL;
-
-  /* handle undocumented nowrap option (no zlib header or check) */
-  z->state->nowrap = 0;
-  if (w < 0)
-  {
-    w = - w;
-    z->state->nowrap = 1;
-  }
-
-  /* set window size */
-  if (w < 8 || w > 15)
-  {
-    inflateEnd(z);
-    return Z_STREAM_ERROR;
-  }
-  z->state->wbits = (uInt)w;
-
-  /* create inflate_blocks state */
-  if ((z->state->blocks =
-      inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w))
-      == Z_NULL)
-  {
-    inflateEnd(z);
-    return Z_MEM_ERROR;
-  }
-  Tracev((stderr, "inflate: allocated\n"));
-
-  /* reset state */
-  inflateReset(z);
-  return Z_OK;
-}
-
-
-int ZEXPORT inflateInit_(z, version, stream_size)
-z_streamp z;
-const char *version;
-int stream_size;
-{
-  return inflateInit2_(z, DEF_WBITS, version, stream_size);
-}
-
-
-#define NEEDBYTE {if(z->avail_in==0)return r;r=f;}
-#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
-
-int ZEXPORT inflate(z, f)
-z_streamp z;
-int f;
-{
-  int r;
-  uInt b;
-
-  if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL)
-    return Z_STREAM_ERROR;
-  f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK;
-  r = Z_BUF_ERROR;
-  while (1) switch (z->state->mode)
-  {
-    case METHOD:
-      NEEDBYTE
-      if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED)
-      {
-        z->state->mode = BAD;
-        z->msg = (char*)"unknown compression method";
-        z->state->sub.marker = 5;       /* can't try inflateSync */
-        break;
-      }
-      if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
-      {
-        z->state->mode = BAD;
-        z->msg = (char*)"invalid window size";
-        z->state->sub.marker = 5;       /* can't try inflateSync */
-        break;
-      }
-      z->state->mode = FLAG;
-    case FLAG:
-      NEEDBYTE
-      b = NEXTBYTE;
-      if (((z->state->sub.method << 8) + b) % 31)
-      {
-        z->state->mode = BAD;
-        z->msg = (char*)"incorrect header check";
-        z->state->sub.marker = 5;       /* can't try inflateSync */
-        break;
-      }
-      Tracev((stderr, "inflate: zlib header ok\n"));
-      if (!(b & PRESET_DICT))
-      {
-        z->state->mode = BLOCKS;
-        break;
-      }
-      z->state->mode = DICT4;
-    case DICT4:
-      NEEDBYTE
-      z->state->sub.check.need = (uLong)NEXTBYTE << 24;
-      z->state->mode = DICT3;
-    case DICT3:
-      NEEDBYTE
-      z->state->sub.check.need += (uLong)NEXTBYTE << 16;
-      z->state->mode = DICT2;
-    case DICT2:
-      NEEDBYTE
-      z->state->sub.check.need += (uLong)NEXTBYTE << 8;
-      z->state->mode = DICT1;
-    case DICT1:
-      NEEDBYTE
-      z->state->sub.check.need += (uLong)NEXTBYTE;
-      z->adler = z->state->sub.check.need;
-      z->state->mode = DICT0;
-      return Z_NEED_DICT;
-    case DICT0:
-      z->state->mode = BAD;
-      z->msg = (char*)"need dictionary";
-      z->state->sub.marker = 0;       /* can try inflateSync */
-      return Z_STREAM_ERROR;
-    case BLOCKS:
-      r = inflate_blocks(z->state->blocks, z, r);
-      if (r == Z_DATA_ERROR)
-      {
-        z->state->mode = BAD;
-        z->state->sub.marker = 0;       /* can try inflateSync */
-        break;
-      }
-      if (r == Z_OK)
-        r = f;
-      if (r != Z_STREAM_END)
-        return r;
-      r = f;
-      inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was);
-      if (z->state->nowrap)
-      {
-        z->state->mode = DONE;
-        break;
-      }
-      z->state->mode = CHECK4;
-    case CHECK4:
-      NEEDBYTE
-      z->state->sub.check.need = (uLong)NEXTBYTE << 24;
-      z->state->mode = CHECK3;
-    case CHECK3:
-      NEEDBYTE
-      z->state->sub.check.need += (uLong)NEXTBYTE << 16;
-      z->state->mode = CHECK2;
-    case CHECK2:
-      NEEDBYTE
-      z->state->sub.check.need += (uLong)NEXTBYTE << 8;
-      z->state->mode = CHECK1;
-    case CHECK1:
-      NEEDBYTE
-      z->state->sub.check.need += (uLong)NEXTBYTE;
-
-      if (z->state->sub.check.was != z->state->sub.check.need)
-      {
-        z->state->mode = BAD;
-        z->msg = (char*)"incorrect data check";
-        z->state->sub.marker = 5;       /* can't try inflateSync */
-        break;
-      }
-      Tracev((stderr, "inflate: zlib check ok\n"));
-      z->state->mode = DONE;
-    case DONE:
-      return Z_STREAM_END;
-    case BAD:
-      return Z_DATA_ERROR;
-    default:
-      return Z_STREAM_ERROR;
-  }
-#ifdef NEED_DUMMY_RETURN
-  return Z_STREAM_ERROR;  /* Some dumb compilers complain without this */
-#endif
-}
-
-
-int ZEXPORT inflateSetDictionary(z, dictionary, dictLength)
-z_streamp z;
-const Bytef *dictionary;
-uInt  dictLength;
-{
-  uInt length = dictLength;
-
-  if (z == Z_NULL || z->state == Z_NULL || z->state->mode != DICT0)
-    return Z_STREAM_ERROR;
-
-  if (adler32(1L, dictionary, dictLength) != z->adler) return Z_DATA_ERROR;
-  z->adler = 1L;
-
-  if (length >= ((uInt)1<state->wbits))
-  {
-    length = (1<state->wbits)-1;
-    dictionary += dictLength - length;
-  }
-  inflate_set_dictionary(z->state->blocks, dictionary, length);
-  z->state->mode = BLOCKS;
-  return Z_OK;
-}
-
-
-int ZEXPORT inflateSync(z)
-z_streamp z;
-{
-  uInt n;       /* number of bytes to look at */
-  Bytef *p;     /* pointer to bytes */
-  uInt m;       /* number of marker bytes found in a row */
-  uLong r, w;   /* temporaries to save total_in and total_out */
-
-  /* set up */
-  if (z == Z_NULL || z->state == Z_NULL)
-    return Z_STREAM_ERROR;
-  if (z->state->mode != BAD)
-  {
-    z->state->mode = BAD;
-    z->state->sub.marker = 0;
-  }
-  if ((n = z->avail_in) == 0)
-    return Z_BUF_ERROR;
-  p = z->next_in;
-  m = z->state->sub.marker;
-
-  /* search */
-  while (n && m < 4)
-  {
-    static const Byte mark[4] = {0, 0, 0xff, 0xff};
-    if (*p == mark[m])
-      m++;
-    else if (*p)
-      m = 0;
-    else
-      m = 4 - m;
-    p++, n--;
-  }
-
-  /* restore */
-  z->total_in += p - z->next_in;
-  z->next_in = p;
-  z->avail_in = n;
-  z->state->sub.marker = m;
-
-  /* return no joy or set up to restart on a new block */
-  if (m != 4)
-    return Z_DATA_ERROR;
-  r = z->total_in;  w = z->total_out;
-  inflateReset(z);
-  z->total_in = r;  z->total_out = w;
-  z->state->mode = BLOCKS;
-  return Z_OK;
-}
-
-
-/* Returns true if inflate is currently at the end of a block generated
- * by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
- * implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH
- * but removes the length bytes of the resulting empty stored block. When
- * decompressing, PPP checks that at the end of input packet, inflate is
- * waiting for these length bytes.
- */
-int ZEXPORT inflateSyncPoint(z)
-z_streamp z;
-{
-  if (z == Z_NULL || z->state == Z_NULL || z->state->blocks == Z_NULL)
-    return Z_STREAM_ERROR;
-  return inflate_blocks_sync_point(z->state->blocks);
-}
diff --git a/Lib/zlib/inftrees.c b/Lib/zlib/inftrees.c
deleted file mode 100644
index ef1e0b6b8..000000000
--- a/Lib/zlib/inftrees.c
+++ /dev/null
@@ -1,455 +0,0 @@
-/* inftrees.c -- generate Huffman trees for efficient decoding
- * Copyright (C) 1995-1998 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-#include "zutil.h"
-#include "inftrees.h"
-
-#if !defined(BUILDFIXED) && !defined(STDC)
-#  define BUILDFIXED   /* non ANSI compilers may not accept inffixed.h */
-#endif
-
-const char inflate_copyright[] =
-   " inflate 1.1.3 Copyright 1995-1998 Mark Adler ";
-/*
-  If you use the zlib library in a product, an acknowledgment is welcome
-  in the documentation of your product. If for some reason you cannot
-  include such an acknowledgment, I would appreciate that you keep this
-  copyright string in the executable of your product.
- */
-struct internal_state  {int dummy;}; /* for buggy compilers */
-
-/* simplify the use of the inflate_huft type with some defines */
-#define exop word.what.Exop
-#define bits word.what.Bits
-
-
-local int huft_build OF((
-    uIntf *,            /* code lengths in bits */
-    uInt,               /* number of codes */
-    uInt,               /* number of "simple" codes */
-    const uIntf *,      /* list of base values for non-simple codes */
-    const uIntf *,      /* list of extra bits for non-simple codes */
-    inflate_huft * FAR*,/* result: starting table */
-    uIntf *,            /* maximum lookup bits (returns actual) */
-    inflate_huft *,     /* space for trees */
-    uInt *,             /* hufts used in space */
-    uIntf * ));         /* space for values */
-
-/* Tables for deflate from PKZIP's appnote.txt. */
-local const uInt cplens[31] = { /* Copy lengths for literal codes 257..285 */
-        3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
-        35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
-        /* see note #13 above about 258 */
-local const uInt cplext[31] = { /* Extra bits for literal codes 257..285 */
-        0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
-        3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112}; /* 112==invalid */
-local const uInt cpdist[30] = { /* Copy offsets for distance codes 0..29 */
-        1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
-        257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
-        8193, 12289, 16385, 24577};
-local const uInt cpdext[30] = { /* Extra bits for distance codes */
-        0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
-        7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
-        12, 12, 13, 13};
-
-/*
-   Huffman code decoding is performed using a multi-level table lookup.
-   The fastest way to decode is to simply build a lookup table whose
-   size is determined by the longest code.  However, the time it takes
-   to build this table can also be a factor if the data being decoded
-   is not very long.  The most common codes are necessarily the
-   shortest codes, so those codes dominate the decoding time, and hence
-   the speed.  The idea is you can have a shorter table that decodes the
-   shorter, more probable codes, and then point to subsidiary tables for
-   the longer codes.  The time it costs to decode the longer codes is
-   then traded against the time it takes to make longer tables.
-
-   This results of this trade are in the variables lbits and dbits
-   below.  lbits is the number of bits the first level table for literal/
-   length codes can decode in one step, and dbits is the same thing for
-   the distance codes.  Subsequent tables are also less than or equal to
-   those sizes.  These values may be adjusted either when all of the
-   codes are shorter than that, in which case the longest code length in
-   bits is used, or when the shortest code is *longer* than the requested
-   table size, in which case the length of the shortest code in bits is
-   used.
-
-   There are two different values for the two tables, since they code a
-   different number of possibilities each.  The literal/length table
-   codes 286 possible values, or in a flat code, a little over eight
-   bits.  The distance table codes 30 possible values, or a little less
-   than five bits, flat.  The optimum values for speed end up being
-   about one bit more than those, so lbits is 8+1 and dbits is 5+1.
-   The optimum values may differ though from machine to machine, and
-   possibly even between compilers.  Your mileage may vary.
- */
-
-
-/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */
-#define BMAX 15         /* maximum bit length of any code */
-
-local int huft_build(b, n, s, d, e, t, m, hp, hn, v)
-uIntf *b;               /* code lengths in bits (all assumed <= BMAX) */
-uInt n;                 /* number of codes (assumed <= 288) */
-uInt s;                 /* number of simple-valued codes (0..s-1) */
-const uIntf *d;         /* list of base values for non-simple codes */
-const uIntf *e;         /* list of extra bits for non-simple codes */
-inflate_huft * FAR *t;  /* result: starting table */
-uIntf *m;               /* maximum lookup bits, returns actual */
-inflate_huft *hp;       /* space for trees */
-uInt *hn;               /* hufts used in space */
-uIntf *v;               /* working area: values in order of bit length */
-/* Given a list of code lengths and a maximum table size, make a set of
-   tables to decode that set of codes.  Return Z_OK on success, Z_BUF_ERROR
-   if the given code set is incomplete (the tables are still built in this
-   case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of
-   lengths), or Z_MEM_ERROR if not enough memory. */
-{
-
-  uInt a;                       /* counter for codes of length k */
-  uInt c[BMAX+1];               /* bit length count table */
-  uInt f;                       /* i repeats in table every f entries */
-  int g;                        /* maximum code length */
-  int h;                        /* table level */
-  register uInt i;              /* counter, current code */
-  register uInt j;              /* counter */
-  register int k;               /* number of bits in current code */
-  int l;                        /* bits per table (returned in m) */
-  uInt mask;                    /* (1 << w) - 1, to avoid cc -O bug on HP */
-  register uIntf *p;            /* pointer into c[], b[], or v[] */
-  inflate_huft *q;              /* points to current table */
-  struct inflate_huft_s r;      /* table entry for structure assignment */
-  inflate_huft *u[BMAX];        /* table stack */
-  register int w;               /* bits before this table == (l * h) */
-  uInt x[BMAX+1];               /* bit offsets, then code stack */
-  uIntf *xp;                    /* pointer into x */
-  int y;                        /* number of dummy codes added */
-  uInt z;                       /* number of entries in current table */
-
-
-  /* Generate counts for each bit length */
-  p = c;
-#define C0 *p++ = 0;
-#define C2 C0 C0 C0 C0
-#define C4 C2 C2 C2 C2
-  C4                            /* clear c[]--assume BMAX+1 is 16 */
-  p = b;  i = n;
-  do {
-    c[*p++]++;                  /* assume all entries <= BMAX */
-  } while (--i);
-  if (c[0] == n)                /* null input--all zero length codes */
-  {
-    *t = (inflate_huft *)Z_NULL;
-    *m = 0;
-    return Z_OK;
-  }
-
-
-  /* Find minimum and maximum length, bound *m by those */
-  l = *m;
-  for (j = 1; j <= BMAX; j++)
-    if (c[j])
-      break;
-  k = j;                        /* minimum code length */
-  if ((uInt)l < j)
-    l = j;
-  for (i = BMAX; i; i--)
-    if (c[i])
-      break;
-  g = i;                        /* maximum code length */
-  if ((uInt)l > i)
-    l = i;
-  *m = l;
-
-
-  /* Adjust last length count to fill out codes, if needed */
-  for (y = 1 << j; j < i; j++, y <<= 1)
-    if ((y -= c[j]) < 0)
-      return Z_DATA_ERROR;
-  if ((y -= c[i]) < 0)
-    return Z_DATA_ERROR;
-  c[i] += y;
-
-
-  /* Generate starting offsets into the value table for each length */
-  x[1] = j = 0;
-  p = c + 1;  xp = x + 2;
-  while (--i) {                 /* note that i == g from above */
-    *xp++ = (j += *p++);
-  }
-
-
-  /* Make a table of values in order of bit lengths */
-  p = b;  i = 0;
-  do {
-    if ((j = *p++) != 0)
-      v[x[j]++] = i;
-  } while (++i < n);
-  n = x[g];                     /* set n to length of v */
-
-
-  /* Generate the Huffman codes and for each, make the table entries */
-  x[0] = i = 0;                 /* first Huffman code is zero */
-  p = v;                        /* grab values in bit order */
-  h = -1;                       /* no tables yet--level -1 */
-  w = -l;                       /* bits decoded == (l * h) */
-  u[0] = (inflate_huft *)Z_NULL;        /* just to keep compilers happy */
-  q = (inflate_huft *)Z_NULL;   /* ditto */
-  z = 0;                        /* ditto */
-
-  /* go through the bit lengths (k already is bits in shortest code) */
-  for (; k <= g; k++)
-  {
-    a = c[k];
-    while (a--)
-    {
-      /* here i is the Huffman code of length k bits for value *p */
-      /* make tables up to required level */
-      while (k > w + l)
-      {
-        h++;
-        w += l;                 /* previous table always l bits */
-
-        /* compute minimum size table less than or equal to l bits */
-        z = g - w;
-        z = z > (uInt)l ? l : z;        /* table size upper limit */
-        if ((f = 1 << (j = k - w)) > a + 1)     /* try a k-w bit table */
-        {                       /* too few codes for k-w bit table */
-          f -= a + 1;           /* deduct codes from patterns left */
-          xp = c + k;
-          if (j < z)
-            while (++j < z)     /* try smaller tables up to z bits */
-            {
-              if ((f <<= 1) <= *++xp)
-                break;          /* enough codes to use up j bits */
-              f -= *xp;         /* else deduct codes from patterns */
-            }
-        }
-        z = 1 << j;             /* table entries for j-bit table */
-
-        /* allocate new table */
-        if (*hn + z > MANY)     /* (note: doesn't matter for fixed) */
-          return Z_MEM_ERROR;   /* not enough memory */
-        u[h] = q = hp + *hn;
-        *hn += z;
-
-        /* connect to last table, if there is one */
-        if (h)
-        {
-          x[h] = i;             /* save pattern for backing up */
-          r.bits = (Byte)l;     /* bits to dump before this table */
-          r.exop = (Byte)j;     /* bits in this table */
-          j = i >> (w - l);
-          r.base = (uInt)(q - u[h-1] - j);   /* offset to this table */
-          u[h-1][j] = r;        /* connect to last table */
-        }
-        else
-          *t = q;               /* first table is returned result */
-      }
-
-      /* set up table entry in r */
-      r.bits = (Byte)(k - w);
-      if (p >= v + n)
-        r.exop = 128 + 64;      /* out of values--invalid code */
-      else if (*p < s)
-      {
-        r.exop = (Byte)(*p < 256 ? 0 : 32 + 64);     /* 256 is end-of-block */
-        r.base = *p++;          /* simple code is just the value */
-      }
-      else
-      {
-        r.exop = (Byte)(e[*p - s] + 16 + 64);/* non-simple--look up in lists */
-        r.base = d[*p++ - s];
-      }
-
-      /* fill code-like entries with r */
-      f = 1 << (k - w);
-      for (j = i >> w; j < z; j += f)
-        q[j] = r;
-
-      /* backwards increment the k-bit code i */
-      for (j = 1 << (k - 1); i & j; j >>= 1)
-        i ^= j;
-      i ^= j;
-
-      /* backup over finished tables */
-      mask = (1 << w) - 1;      /* needed on HP, cc -O bug */
-      while ((i & mask) != x[h])
-      {
-        h--;                    /* don't need to update q */
-        w -= l;
-        mask = (1 << w) - 1;
-      }
-    }
-  }
-
-
-  /* Return Z_BUF_ERROR if we were given an incomplete table */
-  return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
-}
-
-
-int inflate_trees_bits(c, bb, tb, hp, z)
-uIntf *c;               /* 19 code lengths */
-uIntf *bb;              /* bits tree desired/actual depth */
-inflate_huft * FAR *tb; /* bits tree result */
-inflate_huft *hp;       /* space for trees */
-z_streamp z;            /* for messages */
-{
-  int r;
-  uInt hn = 0;          /* hufts used in space */
-  uIntf *v;             /* work area for huft_build */
-
-  if ((v = (uIntf*)ZALLOC(z, 19, sizeof(uInt))) == Z_NULL)
-    return Z_MEM_ERROR;
-  r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL,
-                 tb, bb, hp, &hn, v);
-  if (r == Z_DATA_ERROR)
-    z->msg = (char*)"oversubscribed dynamic bit lengths tree";
-  else if (r == Z_BUF_ERROR || *bb == 0)
-  {
-    z->msg = (char*)"incomplete dynamic bit lengths tree";
-    r = Z_DATA_ERROR;
-  }
-  ZFREE(z, v);
-  return r;
-}
-
-
-int inflate_trees_dynamic(nl, nd, c, bl, bd, tl, td, hp, z)
-uInt nl;                /* number of literal/length codes */
-uInt nd;                /* number of distance codes */
-uIntf *c;               /* that many (total) code lengths */
-uIntf *bl;              /* literal desired/actual bit depth */
-uIntf *bd;              /* distance desired/actual bit depth */
-inflate_huft * FAR *tl; /* literal/length tree result */
-inflate_huft * FAR *td; /* distance tree result */
-inflate_huft *hp;       /* space for trees */
-z_streamp z;            /* for messages */
-{
-  int r;
-  uInt hn = 0;          /* hufts used in space */
-  uIntf *v;             /* work area for huft_build */
-
-  /* allocate work area */
-  if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL)
-    return Z_MEM_ERROR;
-
-  /* build literal/length tree */
-  r = huft_build(c, nl, 257, cplens, cplext, tl, bl, hp, &hn, v);
-  if (r != Z_OK || *bl == 0)
-  {
-    if (r == Z_DATA_ERROR)
-      z->msg = (char*)"oversubscribed literal/length tree";
-    else if (r != Z_MEM_ERROR)
-    {
-      z->msg = (char*)"incomplete literal/length tree";
-      r = Z_DATA_ERROR;
-    }
-    ZFREE(z, v);
-    return r;
-  }
-
-  /* build distance tree */
-  r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, hp, &hn, v);
-  if (r != Z_OK || (*bd == 0 && nl > 257))
-  {
-    if (r == Z_DATA_ERROR)
-      z->msg = (char*)"oversubscribed distance tree";
-    else if (r == Z_BUF_ERROR) {
-#ifdef PKZIP_BUG_WORKAROUND
-      r = Z_OK;
-    }
-#else
-      z->msg = (char*)"incomplete distance tree";
-      r = Z_DATA_ERROR;
-    }
-    else if (r != Z_MEM_ERROR)
-    {
-      z->msg = (char*)"empty distance tree with lengths";
-      r = Z_DATA_ERROR;
-    }
-    ZFREE(z, v);
-    return r;
-#endif
-  }
-
-  /* done */
-  ZFREE(z, v);
-  return Z_OK;
-}
-
-
-/* build fixed tables only once--keep them here */
-#ifdef BUILDFIXED
-local int fixed_built = 0;
-#define FIXEDH 544      /* number of hufts used by fixed tables */
-local inflate_huft fixed_mem[FIXEDH];
-local uInt fixed_bl;
-local uInt fixed_bd;
-local inflate_huft *fixed_tl;
-local inflate_huft *fixed_td;
-#else
-#include "inffixed.h"
-#endif
-
-
-int inflate_trees_fixed(bl, bd, tl, td, z)
-uIntf *bl;               /* literal desired/actual bit depth */
-uIntf *bd;               /* distance desired/actual bit depth */
-inflate_huft * FAR *tl;  /* literal/length tree result */
-inflate_huft * FAR *td;  /* distance tree result */
-z_streamp z;             /* for memory allocation */
-{
-#ifdef BUILDFIXED
-  /* build fixed tables if not already */
-  if (!fixed_built)
-  {
-    int k;              /* temporary variable */
-    uInt f = 0;         /* number of hufts used in fixed_mem */
-    uIntf *c;           /* length list for huft_build */
-    uIntf *v;           /* work area for huft_build */
-
-    /* allocate memory */
-    if ((c = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL)
-      return Z_MEM_ERROR;
-    if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL)
-    {
-      ZFREE(z, c);
-      return Z_MEM_ERROR;
-    }
-
-    /* literal table */
-    for (k = 0; k < 144; k++)
-      c[k] = 8;
-    for (; k < 256; k++)
-      c[k] = 9;
-    for (; k < 280; k++)
-      c[k] = 7;
-    for (; k < 288; k++)
-      c[k] = 8;
-    fixed_bl = 9;
-    huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl,
-               fixed_mem, &f, v);
-
-    /* distance table */
-    for (k = 0; k < 30; k++)
-      c[k] = 5;
-    fixed_bd = 5;
-    huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd,
-               fixed_mem, &f, v);
-
-    /* done */
-    ZFREE(z, v);
-    ZFREE(z, c);
-    fixed_built = 1;
-  }
-#endif
-  *bl = fixed_bl;
-  *bd = fixed_bd;
-  *tl = fixed_tl;
-  *td = fixed_td;
-  return Z_OK;
-}
diff --git a/Lib/zlib/inftrees.h b/Lib/zlib/inftrees.h
deleted file mode 100644
index 85853e097..000000000
--- a/Lib/zlib/inftrees.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/* inftrees.h -- header to use inftrees.c
- * Copyright (C) 1995-1998 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-/* Huffman code lookup table entry--this entry is four bytes for machines
-   that have 16-bit pointers (e.g. PC's in the small or medium model). */
-
-typedef struct inflate_huft_s FAR inflate_huft;
-
-struct inflate_huft_s {
-  union {
-    struct {
-      Byte Exop;        /* number of extra bits or operation */
-      Byte Bits;        /* number of bits in this code or subcode */
-    } what;
-    uInt pad;           /* pad structure to a power of 2 (4 bytes for */
-  } word;               /*  16-bit, 8 bytes for 32-bit int's) */
-  uInt base;            /* literal, length base, distance base,
-                           or table offset */
-};
-
-/* Maximum size of dynamic tree.  The maximum found in a long but non-
-   exhaustive search was 1004 huft structures (850 for length/literals
-   and 154 for distances, the latter actually the result of an
-   exhaustive search).  The actual maximum is not known, but the
-   value below is more than safe. */
-#define MANY 1440
-
-extern int inflate_trees_bits OF((
-    uIntf *,                    /* 19 code lengths */
-    uIntf *,                    /* bits tree desired/actual depth */
-    inflate_huft * FAR *,       /* bits tree result */
-    inflate_huft *,             /* space for trees */
-    z_streamp));                /* for messages */
-
-extern int inflate_trees_dynamic OF((
-    uInt,                       /* number of literal/length codes */
-    uInt,                       /* number of distance codes */
-    uIntf *,                    /* that many (total) code lengths */
-    uIntf *,                    /* literal desired/actual bit depth */
-    uIntf *,                    /* distance desired/actual bit depth */
-    inflate_huft * FAR *,       /* literal/length tree result */
-    inflate_huft * FAR *,       /* distance tree result */
-    inflate_huft *,             /* space for trees */
-    z_streamp));                /* for messages */
-
-extern int inflate_trees_fixed OF((
-    uIntf *,                    /* literal desired/actual bit depth */
-    uIntf *,                    /* distance desired/actual bit depth */
-    inflate_huft * FAR *,       /* literal/length tree result */
-    inflate_huft * FAR *,       /* distance tree result */
-    z_streamp));                /* for memory allocation */
diff --git a/Lib/zlib/infutil.c b/Lib/zlib/infutil.c
deleted file mode 100644
index 824dab571..000000000
--- a/Lib/zlib/infutil.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/* inflate_util.c -- data and routines common to blocks and codes
- * Copyright (C) 1995-1998 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-#include "zutil.h"
-#include "infblock.h"
-#include "inftrees.h"
-#include "infcodes.h"
-#include "infutil.h"
-
-struct inflate_codes_state {int dummy;}; /* for buggy compilers */
-
-/* And'ing with mask[n] masks the lower n bits */
-uInt inflate_mask[17] = {
-    0x0000,
-    0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
-    0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
-};
-
-
-/* copy as much as possible from the sliding window to the output area */
-int inflate_flush(s, z, r)
-inflate_blocks_statef *s;
-z_streamp z;
-int r;
-{
-  uInt n;
-  Bytef *p;
-  Bytef *q;
-
-  /* local copies of source and destination pointers */
-  p = z->next_out;
-  q = s->read;
-
-  /* compute number of bytes to copy as far as end of window */
-  n = (uInt)((q <= s->write ? s->write : s->end) - q);
-  if (n > z->avail_out) n = z->avail_out;
-  if (n && r == Z_BUF_ERROR) r = Z_OK;
-
-  /* update counters */
-  z->avail_out -= n;
-  z->total_out += n;
-
-  /* update check information */
-  if (s->checkfn != Z_NULL)
-    z->adler = s->check = (*s->checkfn)(s->check, q, n);
-
-  /* copy as far as end of window */
-  zmemcpy(p, q, n);
-  p += n;
-  q += n;
-
-  /* see if more to copy at beginning of window */
-  if (q == s->end)
-  {
-    /* wrap pointers */
-    q = s->window;
-    if (s->write == s->end)
-      s->write = s->window;
-
-    /* compute bytes to copy */
-    n = (uInt)(s->write - q);
-    if (n > z->avail_out) n = z->avail_out;
-    if (n && r == Z_BUF_ERROR) r = Z_OK;
-
-    /* update counters */
-    z->avail_out -= n;
-    z->total_out += n;
-
-    /* update check information */
-    if (s->checkfn != Z_NULL)
-      z->adler = s->check = (*s->checkfn)(s->check, q, n);
-
-    /* copy */
-    zmemcpy(p, q, n);
-    p += n;
-    q += n;
-  }
-
-  /* update pointers */
-  z->next_out = p;
-  s->read = q;
-
-  /* done */
-  return r;
-}
diff --git a/Lib/zlib/infutil.h b/Lib/zlib/infutil.h
deleted file mode 100644
index 99d1135d0..000000000
--- a/Lib/zlib/infutil.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/* infutil.h -- types and macros common to blocks and codes
- * Copyright (C) 1995-1998 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-#ifndef _INFUTIL_H
-#define _INFUTIL_H
-
-typedef enum {
-      TYPE,     /* get type bits (3, including end bit) */
-      LENS,     /* get lengths for stored */
-      STORED,   /* processing stored block */
-      TABLE,    /* get table lengths */
-      BTREE,    /* get bit lengths tree for a dynamic block */
-      DTREE,    /* get length, distance trees for a dynamic block */
-      CODES,    /* processing fixed or dynamic block */
-      DRY,      /* output remaining window bytes */
-      DONE,     /* finished last block, done */
-      BAD}      /* got a data error--stuck here */
-inflate_block_mode;
-
-/* inflate blocks semi-private state */
-struct inflate_blocks_state {
-
-  /* mode */
-  inflate_block_mode  mode;     /* current inflate_block mode */
-
-  /* mode dependent information */
-  union {
-    uInt left;          /* if STORED, bytes left to copy */
-    struct {
-      uInt table;               /* table lengths (14 bits) */
-      uInt index;               /* index into blens (or border) */
-      uIntf *blens;             /* bit lengths of codes */
-      uInt bb;                  /* bit length tree depth */
-      inflate_huft *tb;         /* bit length decoding tree */
-    } trees;            /* if DTREE, decoding info for trees */
-    struct {
-      inflate_codes_statef 
-         *codes;
-    } decode;           /* if CODES, current state */
-  } sub;                /* submode */
-  uInt last;            /* true if this block is the last block */
-
-  /* mode independent information */
-  uInt bitk;            /* bits in bit buffer */
-  uLong bitb;           /* bit buffer */
-  inflate_huft *hufts;  /* single malloc for tree space */
-  Bytef *window;        /* sliding window */
-  Bytef *end;           /* one byte after sliding window */
-  Bytef *read;          /* window read pointer */
-  Bytef *write;         /* window write pointer */
-  check_func checkfn;   /* check function */
-  uLong check;          /* check on output */
-
-};
-
-
-/* defines for inflate input/output */
-/*   update pointers and return */
-#define UPDBITS {s->bitb=b;s->bitk=k;}
-#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;}
-#define UPDOUT {s->write=q;}
-#define UPDATE {UPDBITS UPDIN UPDOUT}
-#define LEAVE {UPDATE return inflate_flush(s,z,r);}
-/*   get bytes and bits */
-#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;}
-#define NEEDBYTE {if(n)r=Z_OK;else LEAVE}
-#define NEXTBYTE (n--,*p++)
-#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<>=(j);k-=(j);}
-/*   output bytes */
-#define WAVAIL (uInt)(qread?s->read-q-1:s->end-q)
-#define LOADOUT {q=s->write;m=(uInt)WAVAIL;}
-#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}}
-#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT}
-#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;}
-#define OUTBYTE(a) {*q++=(Byte)(a);m--;}
-/*   load local pointers */
-#define LOAD {LOADIN LOADOUT}
-
-/* masks for lower bits (size given to avoid silly warnings with Visual C++) */
-extern uInt inflate_mask[17];
-
-/* copy as much as possible from the sliding window to the output area */
-extern int inflate_flush OF((
-    inflate_blocks_statef *,
-    z_streamp ,
-    int));
-
-struct internal_state      {int dummy;}; /* for buggy compilers */
-
-#endif
diff --git a/Lib/zlib/maketree.c b/Lib/zlib/maketree.c
deleted file mode 100644
index 949d78641..000000000
--- a/Lib/zlib/maketree.c
+++ /dev/null
@@ -1,85 +0,0 @@
-/* maketree.c -- make inffixed.h table for decoding fixed codes
- * Copyright (C) 1998 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-/* This program is included in the distribution for completeness.
-   You do not need to compile or run this program since inffixed.h
-   is already included in the distribution.  To use this program
-   you need to compile zlib with BUILDFIXED defined and then compile
-   and link this program with the zlib library.  Then the output of
-   this program can be piped to inffixed.h. */
-
-#include 
-#include 
-#include "zutil.h"
-#include "inftrees.h"
-
-/* simplify the use of the inflate_huft type with some defines */
-#define exop word.what.Exop
-#define bits word.what.Bits
-
-/* generate initialization table for an inflate_huft structure array */
-void maketree(uInt b, inflate_huft *t)
-{
-  int i, e;
-
-  i = 0;
-  while (1)
-  {
-    e = t[i].exop;
-    if (e && (e & (16+64)) == 0)        /* table pointer */
-    {
-      fprintf(stderr, "maketree: cannot initialize sub-tables!\n");
-      exit(1);
-    }
-    if (i % 4 == 0)
-      printf("\n   ");
-    printf(" {{{%u,%u}},%u}", t[i].exop, t[i].bits, t[i].base);
-    if (++i == (1<
-#include "zlib.h"
-
-#ifdef STDC
-#  include 
-#  include 
-#else
-   extern void exit  OF((int));
-#endif
-
-#ifdef USE_MMAP
-#  include 
-#  include 
-#  include 
-#endif
-
-#if defined(MSDOS) || defined(OS2) || defined(WIN32)
-#  include 
-#  include 
-#  define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
-#else
-#  define SET_BINARY_MODE(file)
-#endif
-
-#ifdef VMS
-#  define unlink delete
-#  define GZ_SUFFIX "-gz"
-#endif
-#ifdef RISCOS
-#  define unlink remove
-#  define GZ_SUFFIX "-gz"
-#  define fileno(file) file->__file
-#endif
-#if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
-#  include  /* for fileno */
-#endif
-
-#ifndef WIN32 /* unlink already in stdio.h for WIN32 */
-  extern int unlink OF((const char *));
-#endif
-
-#ifndef GZ_SUFFIX
-#  define GZ_SUFFIX ".gz"
-#endif
-#define SUFFIX_LEN (sizeof(GZ_SUFFIX)-1)
-
-#define BUFLEN      16384
-#define MAX_NAME_LEN 1024
-
-#ifdef MAXSEG_64K
-#  define local static
-   /* Needed for systems with limitation on stack size. */
-#else
-#  define local
-#endif
-
-char *prog;
-
-void error            OF((const char *msg));
-void gz_compress      OF((FILE   *in, gzFile out));
-#ifdef USE_MMAP
-int  gz_compress_mmap OF((FILE   *in, gzFile out));
-#endif
-void gz_uncompress    OF((gzFile in, FILE   *out));
-void file_compress    OF((char  *file, char *mode));
-void file_uncompress  OF((char  *file));
-int  main             OF((int argc, char *argv[]));
-
-/* ===========================================================================
- * Display error message and exit
- */
-void error(msg)
-    const char *msg;
-{
-    fprintf(stderr, "%s: %s\n", prog, msg);
-    exit(1);
-}
-
-/* ===========================================================================
- * Compress input to output then close both files.
- */
-
-void gz_compress(in, out)
-    FILE   *in;
-    gzFile out;
-{
-    local char buf[BUFLEN];
-    int len;
-    int err;
-
-#ifdef USE_MMAP
-    /* Try first compressing with mmap. If mmap fails (minigzip used in a
-     * pipe), use the normal fread loop.
-     */
-    if (gz_compress_mmap(in, out) == Z_OK) return;
-#endif
-    for (;;) {
-        len = fread(buf, 1, sizeof(buf), in);
-        if (ferror(in)) {
-            perror("fread");
-            exit(1);
-        }
-        if (len == 0) break;
-
-        if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err));
-    }
-    fclose(in);
-    if (gzclose(out) != Z_OK) error("failed gzclose");
-}
-
-#ifdef USE_MMAP /* MMAP version, Miguel Albrecht  */
-
-/* Try compressing the input file at once using mmap. Return Z_OK if
- * if success, Z_ERRNO otherwise.
- */
-int gz_compress_mmap(in, out)
-    FILE   *in;
-    gzFile out;
-{
-    int len;
-    int err;
-    int ifd = fileno(in);
-    caddr_t buf;    /* mmap'ed buffer for the entire input file */
-    off_t buf_len;  /* length of the input file */
-    struct stat sb;
-
-    /* Determine the size of the file, needed for mmap: */
-    if (fstat(ifd, &sb) < 0) return Z_ERRNO;
-    buf_len = sb.st_size;
-    if (buf_len <= 0) return Z_ERRNO;
-
-    /* Now do the actual mmap: */
-    buf = mmap((caddr_t) 0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0); 
-    if (buf == (caddr_t)(-1)) return Z_ERRNO;
-
-    /* Compress the whole file at once: */
-    len = gzwrite(out, (char *)buf, (unsigned)buf_len);
-
-    if (len != (int)buf_len) error(gzerror(out, &err));
-
-    munmap(buf, buf_len);
-    fclose(in);
-    if (gzclose(out) != Z_OK) error("failed gzclose");
-    return Z_OK;
-}
-#endif /* USE_MMAP */
-
-/* ===========================================================================
- * Uncompress input to output then close both files.
- */
-void gz_uncompress(in, out)
-    gzFile in;
-    FILE   *out;
-{
-    local char buf[BUFLEN];
-    int len;
-    int err;
-
-    for (;;) {
-        len = gzread(in, buf, sizeof(buf));
-        if (len < 0) error (gzerror(in, &err));
-        if (len == 0) break;
-
-        if ((int)fwrite(buf, 1, (unsigned)len, out) != len) {
-	    error("failed fwrite");
-	}
-    }
-    if (fclose(out)) error("failed fclose");
-
-    if (gzclose(in) != Z_OK) error("failed gzclose");
-}
-
-
-/* ===========================================================================
- * Compress the given file: create a corresponding .gz file and remove the
- * original.
- */
-void file_compress(file, mode)
-    char  *file;
-    char  *mode;
-{
-    local char outfile[MAX_NAME_LEN];
-    FILE  *in;
-    gzFile out;
-
-    strcpy(outfile, file);
-    strcat(outfile, GZ_SUFFIX);
-
-    in = fopen(file, "rb");
-    if (in == NULL) {
-        perror(file);
-        exit(1);
-    }
-    out = gzopen(outfile, mode);
-    if (out == NULL) {
-        fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile);
-        exit(1);
-    }
-    gz_compress(in, out);
-
-    unlink(file);
-}
-
-
-/* ===========================================================================
- * Uncompress the given file and remove the original.
- */
-void file_uncompress(file)
-    char  *file;
-{
-    local char buf[MAX_NAME_LEN];
-    char *infile, *outfile;
-    FILE  *out;
-    gzFile in;
-    int len = strlen(file);
-
-    strcpy(buf, file);
-
-    if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) {
-        infile = file;
-        outfile = buf;
-        outfile[len-3] = '\0';
-    } else {
-        outfile = file;
-        infile = buf;
-        strcat(infile, GZ_SUFFIX);
-    }
-    in = gzopen(infile, "rb");
-    if (in == NULL) {
-        fprintf(stderr, "%s: can't gzopen %s\n", prog, infile);
-        exit(1);
-    }
-    out = fopen(outfile, "wb");
-    if (out == NULL) {
-        perror(file);
-        exit(1);
-    }
-
-    gz_uncompress(in, out);
-
-    unlink(infile);
-}
-
-
-/* ===========================================================================
- * Usage:  minigzip [-d] [-f] [-h] [-1 to -9] [files...]
- *   -d : decompress
- *   -f : compress with Z_FILTERED
- *   -h : compress with Z_HUFFMAN_ONLY
- *   -1 to -9 : compression level
- */
-
-int main(argc, argv)
-    int argc;
-    char *argv[];
-{
-    int uncompr = 0;
-    gzFile file;
-    char outmode[20];
-
-    strcpy(outmode, "wb6 ");
-
-    prog = argv[0];
-    argc--, argv++;
-
-    while (argc > 0) {
-      if (strcmp(*argv, "-d") == 0)
-	uncompr = 1;
-      else if (strcmp(*argv, "-f") == 0)
-	outmode[3] = 'f';
-      else if (strcmp(*argv, "-h") == 0)
-	outmode[3] = 'h';
-      else if ((*argv)[0] == '-' && (*argv)[1] >= '1' && (*argv)[1] <= '9' &&
-	       (*argv)[2] == 0)
-	outmode[2] = (*argv)[1];
-      else
-	break;
-      argc--, argv++;
-    }
-    if (argc == 0) {
-        SET_BINARY_MODE(stdin);
-        SET_BINARY_MODE(stdout);
-        if (uncompr) {
-            file = gzdopen(fileno(stdin), "rb");
-            if (file == NULL) error("can't gzdopen stdin");
-            gz_uncompress(file, stdout);
-        } else {
-            file = gzdopen(fileno(stdout), outmode);
-            if (file == NULL) error("can't gzdopen stdout");
-            gz_compress(stdin, file);
-        }
-    } else {
-        do {
-            if (uncompr) {
-                file_uncompress(*argv);
-            } else {
-                file_compress(*argv, outmode);
-            }
-        } while (argv++, --argc);
-    }
-    exit(0);
-    return 0; /* to avoid warning */
-}
diff --git a/Lib/zlib/trees.c b/Lib/zlib/trees.c
deleted file mode 100644
index f01fb30d8..000000000
--- a/Lib/zlib/trees.c
+++ /dev/null
@@ -1,1214 +0,0 @@
-/* trees.c -- output deflated data using Huffman coding
- * Copyright (C) 1995-1998 Jean-loup Gailly
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/*
- *  ALGORITHM
- *
- *      The "deflation" process uses several Huffman trees. The more
- *      common source values are represented by shorter bit sequences.
- *
- *      Each code tree is stored in a compressed form which is itself
- * a Huffman encoding of the lengths of all the code strings (in
- * ascending order by source values).  The actual code strings are
- * reconstructed from the lengths in the inflate process, as described
- * in the deflate specification.
- *
- *  REFERENCES
- *
- *      Deutsch, L.P.,"'Deflate' Compressed Data Format Specification".
- *      Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc
- *
- *      Storer, James A.
- *          Data Compression:  Methods and Theory, pp. 49-50.
- *          Computer Science Press, 1988.  ISBN 0-7167-8156-5.
- *
- *      Sedgewick, R.
- *          Algorithms, p290.
- *          Addison-Wesley, 1983. ISBN 0-201-06672-6.
- */
-
-/* @(#) $Id$ */
-
-/* #define GEN_TREES_H */
-
-#include "deflate.h"
-
-#ifdef DEBUG
-#  include 
-#endif
-
-/* ===========================================================================
- * Constants
- */
-
-#define MAX_BL_BITS 7
-/* Bit length codes must not exceed MAX_BL_BITS bits */
-
-#define END_BLOCK 256
-/* end of block literal code */
-
-#define REP_3_6      16
-/* repeat previous bit length 3-6 times (2 bits of repeat count) */
-
-#define REPZ_3_10    17
-/* repeat a zero length 3-10 times  (3 bits of repeat count) */
-
-#define REPZ_11_138  18
-/* repeat a zero length 11-138 times  (7 bits of repeat count) */
-
-local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */
-   = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0};
-
-local const int extra_dbits[D_CODES] /* extra bits for each distance code */
-   = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
-
-local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */
-   = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7};
-
-local const uch bl_order[BL_CODES]
-   = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
-/* The lengths of the bit length codes are sent in order of decreasing
- * probability, to avoid transmitting the lengths for unused bit length codes.
- */
-
-#define Buf_size (8 * 2*sizeof(char))
-/* Number of bits used within bi_buf. (bi_buf might be implemented on
- * more than 16 bits on some systems.)
- */
-
-/* ===========================================================================
- * Local data. These are initialized only once.
- */
-
-#define DIST_CODE_LEN  512 /* see definition of array dist_code below */
-
-#if defined(GEN_TREES_H) || !defined(STDC)
-/* non ANSI compilers may not accept trees.h */
-
-local ct_data static_ltree[L_CODES+2];
-/* The static literal tree. Since the bit lengths are imposed, there is no
- * need for the L_CODES extra codes used during heap construction. However
- * The codes 286 and 287 are needed to build a canonical tree (see _tr_init
- * below).
- */
-
-local ct_data static_dtree[D_CODES];
-/* The static distance tree. (Actually a trivial tree since all codes use
- * 5 bits.)
- */
-
-uch _dist_code[DIST_CODE_LEN];
-/* Distance codes. The first 256 values correspond to the distances
- * 3 .. 258, the last 256 values correspond to the top 8 bits of
- * the 15 bit distances.
- */
-
-uch _length_code[MAX_MATCH-MIN_MATCH+1];
-/* length code for each normalized match length (0 == MIN_MATCH) */
-
-local int base_length[LENGTH_CODES];
-/* First normalized length for each code (0 = MIN_MATCH) */
-
-local int base_dist[D_CODES];
-/* First normalized distance for each code (0 = distance of 1) */
-
-#else
-#  include "trees.h"
-#endif /* GEN_TREES_H */
-
-struct static_tree_desc_s {
-    const ct_data *static_tree;  /* static tree or NULL */
-    const intf *extra_bits;      /* extra bits for each code or NULL */
-    int     extra_base;          /* base index for extra_bits */
-    int     elems;               /* max number of elements in the tree */
-    int     max_length;          /* max bit length for the codes */
-};
-
-local static_tree_desc  static_l_desc =
-{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS};
-
-local static_tree_desc  static_d_desc =
-{static_dtree, extra_dbits, 0,          D_CODES, MAX_BITS};
-
-local static_tree_desc  static_bl_desc =
-{(const ct_data *)0, extra_blbits, 0,   BL_CODES, MAX_BL_BITS};
-
-/* ===========================================================================
- * Local (static) routines in this file.
- */
-
-local void tr_static_init OF((void));
-local void init_block     OF((deflate_state *s));
-local void pqdownheap     OF((deflate_state *s, ct_data *tree, int k));
-local void gen_bitlen     OF((deflate_state *s, tree_desc *desc));
-local void gen_codes      OF((ct_data *tree, int max_code, ushf *bl_count));
-local void build_tree     OF((deflate_state *s, tree_desc *desc));
-local void scan_tree      OF((deflate_state *s, ct_data *tree, int max_code));
-local void send_tree      OF((deflate_state *s, ct_data *tree, int max_code));
-local int  build_bl_tree  OF((deflate_state *s));
-local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes,
-                              int blcodes));
-local void compress_block OF((deflate_state *s, ct_data *ltree,
-                              ct_data *dtree));
-local void set_data_type  OF((deflate_state *s));
-local unsigned bi_reverse OF((unsigned value, int length));
-local void bi_windup      OF((deflate_state *s));
-local void bi_flush       OF((deflate_state *s));
-local void copy_block     OF((deflate_state *s, charf *buf, unsigned len,
-                              int header));
-
-#ifdef GEN_TREES_H
-local void gen_trees_header OF((void));
-#endif
-
-#ifndef DEBUG
-#  define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len)
-   /* Send a code of the given tree. c and tree must not have side effects */
-
-#else /* DEBUG */
-#  define send_code(s, c, tree) \
-     { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \
-       send_bits(s, tree[c].Code, tree[c].Len); }
-#endif
-
-/* ===========================================================================
- * Output a short LSB first on the stream.
- * IN assertion: there is enough room in pendingBuf.
- */
-#define put_short(s, w) { \
-    put_byte(s, (uch)((w) & 0xff)); \
-    put_byte(s, (uch)((ush)(w) >> 8)); \
-}
-
-/* ===========================================================================
- * Send a value on a given number of bits.
- * IN assertion: length <= 16 and value fits in length bits.
- */
-#ifdef DEBUG
-local void send_bits      OF((deflate_state *s, int value, int length));
-
-local void send_bits(s, value, length)
-    deflate_state *s;
-    int value;  /* value to send */
-    int length; /* number of bits */
-{
-    Tracevv((stderr," l %2d v %4x ", length, value));
-    Assert(length > 0 && length <= 15, "invalid length");
-    s->bits_sent += (ulg)length;
-
-    /* If not enough room in bi_buf, use (valid) bits from bi_buf and
-     * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid))
-     * unused bits in value.
-     */
-    if (s->bi_valid > (int)Buf_size - length) {
-        s->bi_buf |= (value << s->bi_valid);
-        put_short(s, s->bi_buf);
-        s->bi_buf = (ush)value >> (Buf_size - s->bi_valid);
-        s->bi_valid += length - Buf_size;
-    } else {
-        s->bi_buf |= value << s->bi_valid;
-        s->bi_valid += length;
-    }
-}
-#else /* !DEBUG */
-
-#define send_bits(s, value, length) \
-{ int len = length;\
-  if (s->bi_valid > (int)Buf_size - len) {\
-    int val = value;\
-    s->bi_buf |= (val << s->bi_valid);\
-    put_short(s, s->bi_buf);\
-    s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\
-    s->bi_valid += len - Buf_size;\
-  } else {\
-    s->bi_buf |= (value) << s->bi_valid;\
-    s->bi_valid += len;\
-  }\
-}
-#endif /* DEBUG */
-
-
-#define MAX(a,b) (a >= b ? a : b)
-/* the arguments must not have side effects */
-
-/* ===========================================================================
- * Initialize the various 'constant' tables.
- */
-local void tr_static_init()
-{
-#if defined(GEN_TREES_H) || !defined(STDC)
-    static int static_init_done = 0;
-    int n;        /* iterates over tree elements */
-    int bits;     /* bit counter */
-    int length;   /* length value */
-    int code;     /* code value */
-    int dist;     /* distance index */
-    ush bl_count[MAX_BITS+1];
-    /* number of codes at each bit length for an optimal tree */
-
-    if (static_init_done) return;
-
-    /* For some embedded targets, global variables are not initialized: */
-    static_l_desc.static_tree = static_ltree;
-    static_l_desc.extra_bits = extra_lbits;
-    static_d_desc.static_tree = static_dtree;
-    static_d_desc.extra_bits = extra_dbits;
-    static_bl_desc.extra_bits = extra_blbits;
-
-    /* Initialize the mapping length (0..255) -> length code (0..28) */
-    length = 0;
-    for (code = 0; code < LENGTH_CODES-1; code++) {
-        base_length[code] = length;
-        for (n = 0; n < (1< dist code (0..29) */
-    dist = 0;
-    for (code = 0 ; code < 16; code++) {
-        base_dist[code] = dist;
-        for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */
-    for ( ; code < D_CODES; code++) {
-        base_dist[code] = dist << 7;
-        for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) {
-            _dist_code[256 + dist++] = (uch)code;
-        }
-    }
-    Assert (dist == 256, "tr_static_init: 256+dist != 512");
-
-    /* Construct the codes of the static literal tree */
-    for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0;
-    n = 0;
-    while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++;
-    while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++;
-    while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++;
-    while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++;
-    /* Codes 286 and 287 do not exist, but we must include them in the
-     * tree construction to get a canonical Huffman tree (longest code
-     * all ones)
-     */
-    gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count);
-
-    /* The static distance tree is trivial: */
-    for (n = 0; n < D_CODES; n++) {
-        static_dtree[n].Len = 5;
-        static_dtree[n].Code = bi_reverse((unsigned)n, 5);
-    }
-    static_init_done = 1;
-
-#  ifdef GEN_TREES_H
-    gen_trees_header();
-#  endif
-#endif /* defined(GEN_TREES_H) || !defined(STDC) */
-}
-
-/* ===========================================================================
- * Genererate the file trees.h describing the static trees.
- */
-#ifdef GEN_TREES_H
-#  ifndef DEBUG
-#    include 
-#  endif
-
-#  define SEPARATOR(i, last, width) \
-      ((i) == (last)? "\n};\n\n" :    \
-       ((i) % (width) == (width)-1 ? ",\n" : ", "))
-
-void gen_trees_header()
-{
-    FILE *header = fopen("trees.h", "w");
-    int i;
-
-    Assert (header != NULL, "Can't open trees.h");
-    fprintf(header,
-	    "/* header created automatically with -DGEN_TREES_H */\n\n");
-
-    fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n");
-    for (i = 0; i < L_CODES+2; i++) {
-	fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code,
-		static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5));
-    }
-
-    fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n");
-    for (i = 0; i < D_CODES; i++) {
-	fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code,
-		static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5));
-    }
-
-    fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n");
-    for (i = 0; i < DIST_CODE_LEN; i++) {
-	fprintf(header, "%2u%s", _dist_code[i],
-		SEPARATOR(i, DIST_CODE_LEN-1, 20));
-    }
-
-    fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n");
-    for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) {
-	fprintf(header, "%2u%s", _length_code[i],
-		SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20));
-    }
-
-    fprintf(header, "local const int base_length[LENGTH_CODES] = {\n");
-    for (i = 0; i < LENGTH_CODES; i++) {
-	fprintf(header, "%1u%s", base_length[i],
-		SEPARATOR(i, LENGTH_CODES-1, 20));
-    }
-
-    fprintf(header, "local const int base_dist[D_CODES] = {\n");
-    for (i = 0; i < D_CODES; i++) {
-	fprintf(header, "%5u%s", base_dist[i],
-		SEPARATOR(i, D_CODES-1, 10));
-    }
-
-    fclose(header);
-}
-#endif /* GEN_TREES_H */
-
-/* ===========================================================================
- * Initialize the tree data structures for a new zlib stream.
- */
-void _tr_init(s)
-    deflate_state *s;
-{
-    tr_static_init();
-
-    s->l_desc.dyn_tree = s->dyn_ltree;
-    s->l_desc.stat_desc = &static_l_desc;
-
-    s->d_desc.dyn_tree = s->dyn_dtree;
-    s->d_desc.stat_desc = &static_d_desc;
-
-    s->bl_desc.dyn_tree = s->bl_tree;
-    s->bl_desc.stat_desc = &static_bl_desc;
-
-    s->bi_buf = 0;
-    s->bi_valid = 0;
-    s->last_eob_len = 8; /* enough lookahead for inflate */
-#ifdef DEBUG
-    s->compressed_len = 0L;
-    s->bits_sent = 0L;
-#endif
-
-    /* Initialize the first block of the first file: */
-    init_block(s);
-}
-
-/* ===========================================================================
- * Initialize a new block.
- */
-local void init_block(s)
-    deflate_state *s;
-{
-    int n; /* iterates over tree elements */
-
-    /* Initialize the trees. */
-    for (n = 0; n < L_CODES;  n++) s->dyn_ltree[n].Freq = 0;
-    for (n = 0; n < D_CODES;  n++) s->dyn_dtree[n].Freq = 0;
-    for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0;
-
-    s->dyn_ltree[END_BLOCK].Freq = 1;
-    s->opt_len = s->static_len = 0L;
-    s->last_lit = s->matches = 0;
-}
-
-#define SMALLEST 1
-/* Index within the heap array of least frequent node in the Huffman tree */
-
-
-/* ===========================================================================
- * Remove the smallest element from the heap and recreate the heap with
- * one less element. Updates heap and heap_len.
- */
-#define pqremove(s, tree, top) \
-{\
-    top = s->heap[SMALLEST]; \
-    s->heap[SMALLEST] = s->heap[s->heap_len--]; \
-    pqdownheap(s, tree, SMALLEST); \
-}
-
-/* ===========================================================================
- * Compares to subtrees, using the tree depth as tie breaker when
- * the subtrees have equal frequency. This minimizes the worst case length.
- */
-#define smaller(tree, n, m, depth) \
-   (tree[n].Freq < tree[m].Freq || \
-   (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m]))
-
-/* ===========================================================================
- * Restore the heap property by moving down the tree starting at node k,
- * exchanging a node with the smallest of its two sons if necessary, stopping
- * when the heap property is re-established (each father smaller than its
- * two sons).
- */
-local void pqdownheap(s, tree, k)
-    deflate_state *s;
-    ct_data *tree;  /* the tree to restore */
-    int k;               /* node to move down */
-{
-    int v = s->heap[k];
-    int j = k << 1;  /* left son of k */
-    while (j <= s->heap_len) {
-        /* Set j to the smallest of the two sons: */
-        if (j < s->heap_len &&
-            smaller(tree, s->heap[j+1], s->heap[j], s->depth)) {
-            j++;
-        }
-        /* Exit if v is smaller than both sons */
-        if (smaller(tree, v, s->heap[j], s->depth)) break;
-
-        /* Exchange v with the smallest son */
-        s->heap[k] = s->heap[j];  k = j;
-
-        /* And continue down the tree, setting j to the left son of k */
-        j <<= 1;
-    }
-    s->heap[k] = v;
-}
-
-/* ===========================================================================
- * Compute the optimal bit lengths for a tree and update the total bit length
- * for the current block.
- * IN assertion: the fields freq and dad are set, heap[heap_max] and
- *    above are the tree nodes sorted by increasing frequency.
- * OUT assertions: the field len is set to the optimal bit length, the
- *     array bl_count contains the frequencies for each bit length.
- *     The length opt_len is updated; static_len is also updated if stree is
- *     not null.
- */
-local void gen_bitlen(s, desc)
-    deflate_state *s;
-    tree_desc *desc;    /* the tree descriptor */
-{
-    ct_data *tree        = desc->dyn_tree;
-    int max_code         = desc->max_code;
-    const ct_data *stree = desc->stat_desc->static_tree;
-    const intf *extra    = desc->stat_desc->extra_bits;
-    int base             = desc->stat_desc->extra_base;
-    int max_length       = desc->stat_desc->max_length;
-    int h;              /* heap index */
-    int n, m;           /* iterate over the tree elements */
-    int bits;           /* bit length */
-    int xbits;          /* extra bits */
-    ush f;              /* frequency */
-    int overflow = 0;   /* number of elements with bit length too large */
-
-    for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0;
-
-    /* In a first pass, compute the optimal bit lengths (which may
-     * overflow in the case of the bit length tree).
-     */
-    tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */
-
-    for (h = s->heap_max+1; h < HEAP_SIZE; h++) {
-        n = s->heap[h];
-        bits = tree[tree[n].Dad].Len + 1;
-        if (bits > max_length) bits = max_length, overflow++;
-        tree[n].Len = (ush)bits;
-        /* We overwrite tree[n].Dad which is no longer needed */
-
-        if (n > max_code) continue; /* not a leaf node */
-
-        s->bl_count[bits]++;
-        xbits = 0;
-        if (n >= base) xbits = extra[n-base];
-        f = tree[n].Freq;
-        s->opt_len += (ulg)f * (bits + xbits);
-        if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits);
-    }
-    if (overflow == 0) return;
-
-    Trace((stderr,"\nbit length overflow\n"));
-    /* This happens for example on obj2 and pic of the Calgary corpus */
-
-    /* Find the first bit length which could increase: */
-    do {
-        bits = max_length-1;
-        while (s->bl_count[bits] == 0) bits--;
-        s->bl_count[bits]--;      /* move one leaf down the tree */
-        s->bl_count[bits+1] += 2; /* move one overflow item as its brother */
-        s->bl_count[max_length]--;
-        /* The brother of the overflow item also moves one step up,
-         * but this does not affect bl_count[max_length]
-         */
-        overflow -= 2;
-    } while (overflow > 0);
-
-    /* Now recompute all bit lengths, scanning in increasing frequency.
-     * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
-     * lengths instead of fixing only the wrong ones. This idea is taken
-     * from 'ar' written by Haruhiko Okumura.)
-     */
-    for (bits = max_length; bits != 0; bits--) {
-        n = s->bl_count[bits];
-        while (n != 0) {
-            m = s->heap[--h];
-            if (m > max_code) continue;
-            if (tree[m].Len != (unsigned) bits) {
-                Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits));
-                s->opt_len += ((long)bits - (long)tree[m].Len)
-                              *(long)tree[m].Freq;
-                tree[m].Len = (ush)bits;
-            }
-            n--;
-        }
-    }
-}
-
-/* ===========================================================================
- * Generate the codes for a given tree and bit counts (which need not be
- * optimal).
- * IN assertion: the array bl_count contains the bit length statistics for
- * the given tree and the field len is set for all tree elements.
- * OUT assertion: the field code is set for all tree elements of non
- *     zero code length.
- */
-local void gen_codes (tree, max_code, bl_count)
-    ct_data *tree;             /* the tree to decorate */
-    int max_code;              /* largest code with non zero frequency */
-    ushf *bl_count;            /* number of codes at each bit length */
-{
-    ush next_code[MAX_BITS+1]; /* next code value for each bit length */
-    ush code = 0;              /* running code value */
-    int bits;                  /* bit index */
-    int n;                     /* code index */
-
-    /* The distribution counts are first used to generate the code values
-     * without bit reversal.
-     */
-    for (bits = 1; bits <= MAX_BITS; bits++) {
-        next_code[bits] = code = (code + bl_count[bits-1]) << 1;
-    }
-    /* Check that the bit counts in bl_count are consistent. The last code
-     * must be all ones.
-     */
-    Assert (code + bl_count[MAX_BITS]-1 == (1<dyn_tree;
-    const ct_data *stree  = desc->stat_desc->static_tree;
-    int elems             = desc->stat_desc->elems;
-    int n, m;          /* iterate over heap elements */
-    int max_code = -1; /* largest code with non zero frequency */
-    int node;          /* new node being created */
-
-    /* Construct the initial heap, with least frequent element in
-     * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
-     * heap[0] is not used.
-     */
-    s->heap_len = 0, s->heap_max = HEAP_SIZE;
-
-    for (n = 0; n < elems; n++) {
-        if (tree[n].Freq != 0) {
-            s->heap[++(s->heap_len)] = max_code = n;
-            s->depth[n] = 0;
-        } else {
-            tree[n].Len = 0;
-        }
-    }
-
-    /* The pkzip format requires that at least one distance code exists,
-     * and that at least one bit should be sent even if there is only one
-     * possible code. So to avoid special checks later on we force at least
-     * two codes of non zero frequency.
-     */
-    while (s->heap_len < 2) {
-        node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0);
-        tree[node].Freq = 1;
-        s->depth[node] = 0;
-        s->opt_len--; if (stree) s->static_len -= stree[node].Len;
-        /* node is 0 or 1 so it does not have extra bits */
-    }
-    desc->max_code = max_code;
-
-    /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
-     * establish sub-heaps of increasing lengths:
-     */
-    for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n);
-
-    /* Construct the Huffman tree by repeatedly combining the least two
-     * frequent nodes.
-     */
-    node = elems;              /* next internal node of the tree */
-    do {
-        pqremove(s, tree, n);  /* n = node of least frequency */
-        m = s->heap[SMALLEST]; /* m = node of next least frequency */
-
-        s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */
-        s->heap[--(s->heap_max)] = m;
-
-        /* Create a new node father of n and m */
-        tree[node].Freq = tree[n].Freq + tree[m].Freq;
-        s->depth[node] = (uch) (MAX(s->depth[n], s->depth[m]) + 1);
-        tree[n].Dad = tree[m].Dad = (ush)node;
-#ifdef DUMP_BL_TREE
-        if (tree == s->bl_tree) {
-            fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)",
-                    node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq);
-        }
-#endif
-        /* and insert the new node in the heap */
-        s->heap[SMALLEST] = node++;
-        pqdownheap(s, tree, SMALLEST);
-
-    } while (s->heap_len >= 2);
-
-    s->heap[--(s->heap_max)] = s->heap[SMALLEST];
-
-    /* At this point, the fields freq and dad are set. We can now
-     * generate the bit lengths.
-     */
-    gen_bitlen(s, (tree_desc *)desc);
-
-    /* The field len is now set, we can generate the bit codes */
-    gen_codes ((ct_data *)tree, max_code, s->bl_count);
-}
-
-/* ===========================================================================
- * Scan a literal or distance tree to determine the frequencies of the codes
- * in the bit length tree.
- */
-local void scan_tree (s, tree, max_code)
-    deflate_state *s;
-    ct_data *tree;   /* the tree to be scanned */
-    int max_code;    /* and its largest code of non zero frequency */
-{
-    int n;                     /* iterates over all tree elements */
-    int prevlen = -1;          /* last emitted length */
-    int curlen;                /* length of current code */
-    int nextlen = tree[0].Len; /* length of next code */
-    int count = 0;             /* repeat count of the current code */
-    int max_count = 7;         /* max repeat count */
-    int min_count = 4;         /* min repeat count */
-
-    if (nextlen == 0) max_count = 138, min_count = 3;
-    tree[max_code+1].Len = (ush)0xffff; /* guard */
-
-    for (n = 0; n <= max_code; n++) {
-        curlen = nextlen; nextlen = tree[n+1].Len;
-        if (++count < max_count && curlen == nextlen) {
-            continue;
-        } else if (count < min_count) {
-            s->bl_tree[curlen].Freq += count;
-        } else if (curlen != 0) {
-            if (curlen != prevlen) s->bl_tree[curlen].Freq++;
-            s->bl_tree[REP_3_6].Freq++;
-        } else if (count <= 10) {
-            s->bl_tree[REPZ_3_10].Freq++;
-        } else {
-            s->bl_tree[REPZ_11_138].Freq++;
-        }
-        count = 0; prevlen = curlen;
-        if (nextlen == 0) {
-            max_count = 138, min_count = 3;
-        } else if (curlen == nextlen) {
-            max_count = 6, min_count = 3;
-        } else {
-            max_count = 7, min_count = 4;
-        }
-    }
-}
-
-/* ===========================================================================
- * Send a literal or distance tree in compressed form, using the codes in
- * bl_tree.
- */
-local void send_tree (s, tree, max_code)
-    deflate_state *s;
-    ct_data *tree; /* the tree to be scanned */
-    int max_code;       /* and its largest code of non zero frequency */
-{
-    int n;                     /* iterates over all tree elements */
-    int prevlen = -1;          /* last emitted length */
-    int curlen;                /* length of current code */
-    int nextlen = tree[0].Len; /* length of next code */
-    int count = 0;             /* repeat count of the current code */
-    int max_count = 7;         /* max repeat count */
-    int min_count = 4;         /* min repeat count */
-
-    /* tree[max_code+1].Len = -1; */  /* guard already set */
-    if (nextlen == 0) max_count = 138, min_count = 3;
-
-    for (n = 0; n <= max_code; n++) {
-        curlen = nextlen; nextlen = tree[n+1].Len;
-        if (++count < max_count && curlen == nextlen) {
-            continue;
-        } else if (count < min_count) {
-            do { send_code(s, curlen, s->bl_tree); } while (--count != 0);
-
-        } else if (curlen != 0) {
-            if (curlen != prevlen) {
-                send_code(s, curlen, s->bl_tree); count--;
-            }
-            Assert(count >= 3 && count <= 6, " 3_6?");
-            send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2);
-
-        } else if (count <= 10) {
-            send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3);
-
-        } else {
-            send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7);
-        }
-        count = 0; prevlen = curlen;
-        if (nextlen == 0) {
-            max_count = 138, min_count = 3;
-        } else if (curlen == nextlen) {
-            max_count = 6, min_count = 3;
-        } else {
-            max_count = 7, min_count = 4;
-        }
-    }
-}
-
-/* ===========================================================================
- * Construct the Huffman tree for the bit lengths and return the index in
- * bl_order of the last bit length code to send.
- */
-local int build_bl_tree(s)
-    deflate_state *s;
-{
-    int max_blindex;  /* index of last bit length code of non zero freq */
-
-    /* Determine the bit length frequencies for literal and distance trees */
-    scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code);
-    scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code);
-
-    /* Build the bit length tree: */
-    build_tree(s, (tree_desc *)(&(s->bl_desc)));
-    /* opt_len now includes the length of the tree representations, except
-     * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
-     */
-
-    /* Determine the number of bit length codes to send. The pkzip format
-     * requires that at least 4 bit length codes be sent. (appnote.txt says
-     * 3 but the actual value used is 4.)
-     */
-    for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) {
-        if (s->bl_tree[bl_order[max_blindex]].Len != 0) break;
-    }
-    /* Update opt_len to include the bit length tree and counts */
-    s->opt_len += 3*(max_blindex+1) + 5+5+4;
-    Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld",
-            s->opt_len, s->static_len));
-
-    return max_blindex;
-}
-
-/* ===========================================================================
- * Send the header for a block using dynamic Huffman trees: the counts, the
- * lengths of the bit length codes, the literal tree and the distance tree.
- * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
- */
-local void send_all_trees(s, lcodes, dcodes, blcodes)
-    deflate_state *s;
-    int lcodes, dcodes, blcodes; /* number of codes for each tree */
-{
-    int rank;                    /* index in bl_order */
-
-    Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes");
-    Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,
-            "too many codes");
-    Tracev((stderr, "\nbl counts: "));
-    send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */
-    send_bits(s, dcodes-1,   5);
-    send_bits(s, blcodes-4,  4); /* not -3 as stated in appnote.txt */
-    for (rank = 0; rank < blcodes; rank++) {
-        Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
-        send_bits(s, s->bl_tree[bl_order[rank]].Len, 3);
-    }
-    Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent));
-
-    send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */
-    Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent));
-
-    send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */
-    Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent));
-}
-
-/* ===========================================================================
- * Send a stored block
- */
-void _tr_stored_block(s, buf, stored_len, eof)
-    deflate_state *s;
-    charf *buf;       /* input block */
-    ulg stored_len;   /* length of input block */
-    int eof;          /* true if this is the last block for a file */
-{
-    send_bits(s, (STORED_BLOCK<<1)+eof, 3);  /* send block type */
-#ifdef DEBUG
-    s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L;
-    s->compressed_len += (stored_len + 4) << 3;
-#endif
-    copy_block(s, buf, (unsigned)stored_len, 1); /* with header */
-}
-
-/* ===========================================================================
- * Send one empty static block to give enough lookahead for inflate.
- * This takes 10 bits, of which 7 may remain in the bit buffer.
- * The current inflate code requires 9 bits of lookahead. If the
- * last two codes for the previous block (real code plus EOB) were coded
- * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode
- * the last real code. In this case we send two empty static blocks instead
- * of one. (There are no problems if the previous block is stored or fixed.)
- * To simplify the code, we assume the worst case of last real code encoded
- * on one bit only.
- */
-void _tr_align(s)
-    deflate_state *s;
-{
-    send_bits(s, STATIC_TREES<<1, 3);
-    send_code(s, END_BLOCK, static_ltree);
-#ifdef DEBUG
-    s->compressed_len += 10L; /* 3 for block type, 7 for EOB */
-#endif
-    bi_flush(s);
-    /* Of the 10 bits for the empty block, we have already sent
-     * (10 - bi_valid) bits. The lookahead for the last real code (before
-     * the EOB of the previous block) was thus at least one plus the length
-     * of the EOB plus what we have just sent of the empty static block.
-     */
-    if (1 + s->last_eob_len + 10 - s->bi_valid < 9) {
-        send_bits(s, STATIC_TREES<<1, 3);
-        send_code(s, END_BLOCK, static_ltree);
-#ifdef DEBUG
-        s->compressed_len += 10L;
-#endif
-        bi_flush(s);
-    }
-    s->last_eob_len = 7;
-}
-
-/* ===========================================================================
- * Determine the best encoding for the current block: dynamic trees, static
- * trees or store, and output the encoded block to the zip file.
- */
-void _tr_flush_block(s, buf, stored_len, eof)
-    deflate_state *s;
-    charf *buf;       /* input block, or NULL if too old */
-    ulg stored_len;   /* length of input block */
-    int eof;          /* true if this is the last block for a file */
-{
-    ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */
-    int max_blindex = 0;  /* index of last bit length code of non zero freq */
-
-    /* Build the Huffman trees unless a stored block is forced */
-    if (s->level > 0) {
-
-	 /* Check if the file is ascii or binary */
-	if (s->data_type == Z_UNKNOWN) set_data_type(s);
-
-	/* Construct the literal and distance trees */
-	build_tree(s, (tree_desc *)(&(s->l_desc)));
-	Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len,
-		s->static_len));
-
-	build_tree(s, (tree_desc *)(&(s->d_desc)));
-	Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len,
-		s->static_len));
-	/* At this point, opt_len and static_len are the total bit lengths of
-	 * the compressed block data, excluding the tree representations.
-	 */
-
-	/* Build the bit length tree for the above two trees, and get the index
-	 * in bl_order of the last bit length code to send.
-	 */
-	max_blindex = build_bl_tree(s);
-
-	/* Determine the best encoding. Compute first the block length in bytes*/
-	opt_lenb = (s->opt_len+3+7)>>3;
-	static_lenb = (s->static_len+3+7)>>3;
-
-	Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ",
-		opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,
-		s->last_lit));
-
-	if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
-
-    } else {
-        Assert(buf != (char*)0, "lost buf");
-	opt_lenb = static_lenb = stored_len + 5; /* force a stored block */
-    }
-
-#ifdef FORCE_STORED
-    if (buf != (char*)0) { /* force stored block */
-#else
-    if (stored_len+4 <= opt_lenb && buf != (char*)0) {
-                       /* 4: two words for the lengths */
-#endif
-        /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
-         * Otherwise we can't have processed more than WSIZE input bytes since
-         * the last block flush, because compression would have been
-         * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
-         * transform a block into a stored block.
-         */
-        _tr_stored_block(s, buf, stored_len, eof);
-
-#ifdef FORCE_STATIC
-    } else if (static_lenb >= 0) { /* force static trees */
-#else
-    } else if (static_lenb == opt_lenb) {
-#endif
-        send_bits(s, (STATIC_TREES<<1)+eof, 3);
-        compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree);
-#ifdef DEBUG
-        s->compressed_len += 3 + s->static_len;
-#endif
-    } else {
-        send_bits(s, (DYN_TREES<<1)+eof, 3);
-        send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1,
-                       max_blindex+1);
-        compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree);
-#ifdef DEBUG
-        s->compressed_len += 3 + s->opt_len;
-#endif
-    }
-    Assert (s->compressed_len == s->bits_sent, "bad compressed size");
-    /* The above check is made mod 2^32, for files larger than 512 MB
-     * and uLong implemented on 32 bits.
-     */
-    init_block(s);
-
-    if (eof) {
-        bi_windup(s);
-#ifdef DEBUG
-        s->compressed_len += 7;  /* align on byte boundary */
-#endif
-    }
-    Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3,
-           s->compressed_len-7*eof));
-}
-
-/* ===========================================================================
- * Save the match info and tally the frequency counts. Return true if
- * the current block must be flushed.
- */
-int _tr_tally (s, dist, lc)
-    deflate_state *s;
-    unsigned dist;  /* distance of matched string */
-    unsigned lc;    /* match length-MIN_MATCH or unmatched char (if dist==0) */
-{
-    s->d_buf[s->last_lit] = (ush)dist;
-    s->l_buf[s->last_lit++] = (uch)lc;
-    if (dist == 0) {
-        /* lc is the unmatched char */
-        s->dyn_ltree[lc].Freq++;
-    } else {
-        s->matches++;
-        /* Here, lc is the match length - MIN_MATCH */
-        dist--;             /* dist = match distance - 1 */
-        Assert((ush)dist < (ush)MAX_DIST(s) &&
-               (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&
-               (ush)d_code(dist) < (ush)D_CODES,  "_tr_tally: bad match");
-
-        s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++;
-        s->dyn_dtree[d_code(dist)].Freq++;
-    }
-
-#ifdef TRUNCATE_BLOCK
-    /* Try to guess if it is profitable to stop the current block here */
-    if ((s->last_lit & 0x1fff) == 0 && s->level > 2) {
-        /* Compute an upper bound for the compressed length */
-        ulg out_length = (ulg)s->last_lit*8L;
-        ulg in_length = (ulg)((long)s->strstart - s->block_start);
-        int dcode;
-        for (dcode = 0; dcode < D_CODES; dcode++) {
-            out_length += (ulg)s->dyn_dtree[dcode].Freq *
-                (5L+extra_dbits[dcode]);
-        }
-        out_length >>= 3;
-        Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ",
-               s->last_lit, in_length, out_length,
-               100L - out_length*100L/in_length));
-        if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1;
-    }
-#endif
-    return (s->last_lit == s->lit_bufsize-1);
-    /* We avoid equality with lit_bufsize because of wraparound at 64K
-     * on 16 bit machines and because stored blocks are restricted to
-     * 64K-1 bytes.
-     */
-}
-
-/* ===========================================================================
- * Send the block data compressed using the given Huffman trees
- */
-local void compress_block(s, ltree, dtree)
-    deflate_state *s;
-    ct_data *ltree; /* literal tree */
-    ct_data *dtree; /* distance tree */
-{
-    unsigned dist;      /* distance of matched string */
-    int lc;             /* match length or unmatched char (if dist == 0) */
-    unsigned lx = 0;    /* running index in l_buf */
-    unsigned code;      /* the code to send */
-    int extra;          /* number of extra bits to send */
-
-    if (s->last_lit != 0) do {
-        dist = s->d_buf[lx];
-        lc = s->l_buf[lx++];
-        if (dist == 0) {
-            send_code(s, lc, ltree); /* send a literal byte */
-            Tracecv(isgraph(lc), (stderr," '%c' ", lc));
-        } else {
-            /* Here, lc is the match length - MIN_MATCH */
-            code = _length_code[lc];
-            send_code(s, code+LITERALS+1, ltree); /* send the length code */
-            extra = extra_lbits[code];
-            if (extra != 0) {
-                lc -= base_length[code];
-                send_bits(s, lc, extra);       /* send the extra length bits */
-            }
-            dist--; /* dist is now the match distance - 1 */
-            code = d_code(dist);
-            Assert (code < D_CODES, "bad d_code");
-
-            send_code(s, code, dtree);       /* send the distance code */
-            extra = extra_dbits[code];
-            if (extra != 0) {
-                dist -= base_dist[code];
-                send_bits(s, dist, extra);   /* send the extra distance bits */
-            }
-        } /* literal or match pair ? */
-
-        /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */
-        Assert(s->pending < s->lit_bufsize + 2*lx, "pendingBuf overflow");
-
-    } while (lx < s->last_lit);
-
-    send_code(s, END_BLOCK, ltree);
-    s->last_eob_len = ltree[END_BLOCK].Len;
-}
-
-/* ===========================================================================
- * Set the data type to ASCII or BINARY, using a crude approximation:
- * binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise.
- * IN assertion: the fields freq of dyn_ltree are set and the total of all
- * frequencies does not exceed 64K (to fit in an int on 16 bit machines).
- */
-local void set_data_type(s)
-    deflate_state *s;
-{
-    int n = 0;
-    unsigned ascii_freq = 0;
-    unsigned bin_freq = 0;
-    while (n < 7)        bin_freq += s->dyn_ltree[n++].Freq;
-    while (n < 128)    ascii_freq += s->dyn_ltree[n++].Freq;
-    while (n < LITERALS) bin_freq += s->dyn_ltree[n++].Freq;
-    s->data_type = (Byte)(bin_freq > (ascii_freq >> 2) ? Z_BINARY : Z_ASCII);
-}
-
-/* ===========================================================================
- * Reverse the first len bits of a code, using straightforward code (a faster
- * method would use a table)
- * IN assertion: 1 <= len <= 15
- */
-local unsigned bi_reverse(code, len)
-    unsigned code; /* the value to invert */
-    int len;       /* its bit length */
-{
-    register unsigned res = 0;
-    do {
-        res |= code & 1;
-        code >>= 1, res <<= 1;
-    } while (--len > 0);
-    return res >> 1;
-}
-
-/* ===========================================================================
- * Flush the bit buffer, keeping at most 7 bits in it.
- */
-local void bi_flush(s)
-    deflate_state *s;
-{
-    if (s->bi_valid == 16) {
-        put_short(s, s->bi_buf);
-        s->bi_buf = 0;
-        s->bi_valid = 0;
-    } else if (s->bi_valid >= 8) {
-        put_byte(s, (Byte)s->bi_buf);
-        s->bi_buf >>= 8;
-        s->bi_valid -= 8;
-    }
-}
-
-/* ===========================================================================
- * Flush the bit buffer and align the output on a byte boundary
- */
-local void bi_windup(s)
-    deflate_state *s;
-{
-    if (s->bi_valid > 8) {
-        put_short(s, s->bi_buf);
-    } else if (s->bi_valid > 0) {
-        put_byte(s, (Byte)s->bi_buf);
-    }
-    s->bi_buf = 0;
-    s->bi_valid = 0;
-#ifdef DEBUG
-    s->bits_sent = (s->bits_sent+7) & ~7;
-#endif
-}
-
-/* ===========================================================================
- * Copy a stored block, storing first the length and its
- * one's complement if requested.
- */
-local void copy_block(s, buf, len, header)
-    deflate_state *s;
-    charf    *buf;    /* the input data */
-    unsigned len;     /* its length */
-    int      header;  /* true if block header must be written */
-{
-    bi_windup(s);        /* align on byte boundary */
-    s->last_eob_len = 8; /* enough lookahead for inflate */
-
-    if (header) {
-        put_short(s, (ush)len);   
-        put_short(s, (ush)~len);
-#ifdef DEBUG
-        s->bits_sent += 2*16;
-#endif
-    }
-#ifdef DEBUG
-    s->bits_sent += (ulg)len<<3;
-#endif
-    while (len--) {
-        put_byte(s, *buf++);
-    }
-}
diff --git a/Lib/zlib/trees.h b/Lib/zlib/trees.h
deleted file mode 100644
index 72facf900..000000000
--- a/Lib/zlib/trees.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/* header created automatically with -DGEN_TREES_H */
-
-local const ct_data static_ltree[L_CODES+2] = {
-{{ 12},{  8}}, {{140},{  8}}, {{ 76},{  8}}, {{204},{  8}}, {{ 44},{  8}},
-{{172},{  8}}, {{108},{  8}}, {{236},{  8}}, {{ 28},{  8}}, {{156},{  8}},
-{{ 92},{  8}}, {{220},{  8}}, {{ 60},{  8}}, {{188},{  8}}, {{124},{  8}},
-{{252},{  8}}, {{  2},{  8}}, {{130},{  8}}, {{ 66},{  8}}, {{194},{  8}},
-{{ 34},{  8}}, {{162},{  8}}, {{ 98},{  8}}, {{226},{  8}}, {{ 18},{  8}},
-{{146},{  8}}, {{ 82},{  8}}, {{210},{  8}}, {{ 50},{  8}}, {{178},{  8}},
-{{114},{  8}}, {{242},{  8}}, {{ 10},{  8}}, {{138},{  8}}, {{ 74},{  8}},
-{{202},{  8}}, {{ 42},{  8}}, {{170},{  8}}, {{106},{  8}}, {{234},{  8}},
-{{ 26},{  8}}, {{154},{  8}}, {{ 90},{  8}}, {{218},{  8}}, {{ 58},{  8}},
-{{186},{  8}}, {{122},{  8}}, {{250},{  8}}, {{  6},{  8}}, {{134},{  8}},
-{{ 70},{  8}}, {{198},{  8}}, {{ 38},{  8}}, {{166},{  8}}, {{102},{  8}},
-{{230},{  8}}, {{ 22},{  8}}, {{150},{  8}}, {{ 86},{  8}}, {{214},{  8}},
-{{ 54},{  8}}, {{182},{  8}}, {{118},{  8}}, {{246},{  8}}, {{ 14},{  8}},
-{{142},{  8}}, {{ 78},{  8}}, {{206},{  8}}, {{ 46},{  8}}, {{174},{  8}},
-{{110},{  8}}, {{238},{  8}}, {{ 30},{  8}}, {{158},{  8}}, {{ 94},{  8}},
-{{222},{  8}}, {{ 62},{  8}}, {{190},{  8}}, {{126},{  8}}, {{254},{  8}},
-{{  1},{  8}}, {{129},{  8}}, {{ 65},{  8}}, {{193},{  8}}, {{ 33},{  8}},
-{{161},{  8}}, {{ 97},{  8}}, {{225},{  8}}, {{ 17},{  8}}, {{145},{  8}},
-{{ 81},{  8}}, {{209},{  8}}, {{ 49},{  8}}, {{177},{  8}}, {{113},{  8}},
-{{241},{  8}}, {{  9},{  8}}, {{137},{  8}}, {{ 73},{  8}}, {{201},{  8}},
-{{ 41},{  8}}, {{169},{  8}}, {{105},{  8}}, {{233},{  8}}, {{ 25},{  8}},
-{{153},{  8}}, {{ 89},{  8}}, {{217},{  8}}, {{ 57},{  8}}, {{185},{  8}},
-{{121},{  8}}, {{249},{  8}}, {{  5},{  8}}, {{133},{  8}}, {{ 69},{  8}},
-{{197},{  8}}, {{ 37},{  8}}, {{165},{  8}}, {{101},{  8}}, {{229},{  8}},
-{{ 21},{  8}}, {{149},{  8}}, {{ 85},{  8}}, {{213},{  8}}, {{ 53},{  8}},
-{{181},{  8}}, {{117},{  8}}, {{245},{  8}}, {{ 13},{  8}}, {{141},{  8}},
-{{ 77},{  8}}, {{205},{  8}}, {{ 45},{  8}}, {{173},{  8}}, {{109},{  8}},
-{{237},{  8}}, {{ 29},{  8}}, {{157},{  8}}, {{ 93},{  8}}, {{221},{  8}},
-{{ 61},{  8}}, {{189},{  8}}, {{125},{  8}}, {{253},{  8}}, {{ 19},{  9}},
-{{275},{  9}}, {{147},{  9}}, {{403},{  9}}, {{ 83},{  9}}, {{339},{  9}},
-{{211},{  9}}, {{467},{  9}}, {{ 51},{  9}}, {{307},{  9}}, {{179},{  9}},
-{{435},{  9}}, {{115},{  9}}, {{371},{  9}}, {{243},{  9}}, {{499},{  9}},
-{{ 11},{  9}}, {{267},{  9}}, {{139},{  9}}, {{395},{  9}}, {{ 75},{  9}},
-{{331},{  9}}, {{203},{  9}}, {{459},{  9}}, {{ 43},{  9}}, {{299},{  9}},
-{{171},{  9}}, {{427},{  9}}, {{107},{  9}}, {{363},{  9}}, {{235},{  9}},
-{{491},{  9}}, {{ 27},{  9}}, {{283},{  9}}, {{155},{  9}}, {{411},{  9}},
-{{ 91},{  9}}, {{347},{  9}}, {{219},{  9}}, {{475},{  9}}, {{ 59},{  9}},
-{{315},{  9}}, {{187},{  9}}, {{443},{  9}}, {{123},{  9}}, {{379},{  9}},
-{{251},{  9}}, {{507},{  9}}, {{  7},{  9}}, {{263},{  9}}, {{135},{  9}},
-{{391},{  9}}, {{ 71},{  9}}, {{327},{  9}}, {{199},{  9}}, {{455},{  9}},
-{{ 39},{  9}}, {{295},{  9}}, {{167},{  9}}, {{423},{  9}}, {{103},{  9}},
-{{359},{  9}}, {{231},{  9}}, {{487},{  9}}, {{ 23},{  9}}, {{279},{  9}},
-{{151},{  9}}, {{407},{  9}}, {{ 87},{  9}}, {{343},{  9}}, {{215},{  9}},
-{{471},{  9}}, {{ 55},{  9}}, {{311},{  9}}, {{183},{  9}}, {{439},{  9}},
-{{119},{  9}}, {{375},{  9}}, {{247},{  9}}, {{503},{  9}}, {{ 15},{  9}},
-{{271},{  9}}, {{143},{  9}}, {{399},{  9}}, {{ 79},{  9}}, {{335},{  9}},
-{{207},{  9}}, {{463},{  9}}, {{ 47},{  9}}, {{303},{  9}}, {{175},{  9}},
-{{431},{  9}}, {{111},{  9}}, {{367},{  9}}, {{239},{  9}}, {{495},{  9}},
-{{ 31},{  9}}, {{287},{  9}}, {{159},{  9}}, {{415},{  9}}, {{ 95},{  9}},
-{{351},{  9}}, {{223},{  9}}, {{479},{  9}}, {{ 63},{  9}}, {{319},{  9}},
-{{191},{  9}}, {{447},{  9}}, {{127},{  9}}, {{383},{  9}}, {{255},{  9}},
-{{511},{  9}}, {{  0},{  7}}, {{ 64},{  7}}, {{ 32},{  7}}, {{ 96},{  7}},
-{{ 16},{  7}}, {{ 80},{  7}}, {{ 48},{  7}}, {{112},{  7}}, {{  8},{  7}},
-{{ 72},{  7}}, {{ 40},{  7}}, {{104},{  7}}, {{ 24},{  7}}, {{ 88},{  7}},
-{{ 56},{  7}}, {{120},{  7}}, {{  4},{  7}}, {{ 68},{  7}}, {{ 36},{  7}},
-{{100},{  7}}, {{ 20},{  7}}, {{ 84},{  7}}, {{ 52},{  7}}, {{116},{  7}},
-{{  3},{  8}}, {{131},{  8}}, {{ 67},{  8}}, {{195},{  8}}, {{ 35},{  8}},
-{{163},{  8}}, {{ 99},{  8}}, {{227},{  8}}
-};
-
-local const ct_data static_dtree[D_CODES] = {
-{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}},
-{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}},
-{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}},
-{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}},
-{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}},
-{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}}
-};
-
-const uch _dist_code[DIST_CODE_LEN] = {
- 0,  1,  2,  3,  4,  4,  5,  5,  6,  6,  6,  6,  7,  7,  7,  7,  8,  8,  8,  8,
- 8,  8,  8,  8,  9,  9,  9,  9,  9,  9,  9,  9, 10, 10, 10, 10, 10, 10, 10, 10,
-10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
-11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
-12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
-13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
-14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
-14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
-14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
-15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
-15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
-15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,  0,  0, 16, 17,
-18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
-23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
-27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
-27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
-28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
-28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
-28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
-29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
-29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
-29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
-};
-
-const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {
- 0,  1,  2,  3,  4,  5,  6,  7,  8,  8,  9,  9, 10, 10, 11, 11, 12, 12, 12, 12,
-13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
-17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
-19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
-21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
-22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
-23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
-26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
-27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
-};
-
-local const int base_length[LENGTH_CODES] = {
-0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
-64, 80, 96, 112, 128, 160, 192, 224, 0
-};
-
-local const int base_dist[D_CODES] = {
-    0,     1,     2,     3,     4,     6,     8,    12,    16,    24,
-   32,    48,    64,    96,   128,   192,   256,   384,   512,   768,
- 1024,  1536,  2048,  3072,  4096,  6144,  8192, 12288, 16384, 24576
-};
-
diff --git a/Lib/zlib/uncompr.c b/Lib/zlib/uncompr.c
deleted file mode 100644
index d10332137..000000000
--- a/Lib/zlib/uncompr.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/* uncompr.c -- decompress a memory buffer
- * Copyright (C) 1995-1998 Jean-loup Gailly.
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* @(#) $Id$ */
-
-#include "zlib.h"
-
-/* ===========================================================================
-     Decompresses the source buffer into the destination buffer.  sourceLen is
-   the byte length of the source buffer. Upon entry, destLen is the total
-   size of the destination buffer, which must be large enough to hold the
-   entire uncompressed data. (The size of the uncompressed data must have
-   been saved previously by the compressor and transmitted to the decompressor
-   by some mechanism outside the scope of this compression library.)
-   Upon exit, destLen is the actual size of the compressed buffer.
-     This function can be used to decompress a whole file at once if the
-   input file is mmap'ed.
-
-     uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
-   enough memory, Z_BUF_ERROR if there was not enough room in the output
-   buffer, or Z_DATA_ERROR if the input data was corrupted.
-*/
-int ZEXPORT uncompress (dest, destLen, source, sourceLen)
-    Bytef *dest;
-    uLongf *destLen;
-    const Bytef *source;
-    uLong sourceLen;
-{
-    z_stream stream;
-    int err;
-
-    stream.next_in = (Bytef*)source;
-    stream.avail_in = (uInt)sourceLen;
-    /* Check for source > 64K on 16-bit machine: */
-    if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
-
-    stream.next_out = dest;
-    stream.avail_out = (uInt)*destLen;
-    if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
-
-    stream.zalloc = (alloc_func)0;
-    stream.zfree = (free_func)0;
-
-    err = inflateInit(&stream);
-    if (err != Z_OK) return err;
-
-    err = inflate(&stream, Z_FINISH);
-    if (err != Z_STREAM_END) {
-        inflateEnd(&stream);
-        return err == Z_OK ? Z_BUF_ERROR : err;
-    }
-    *destLen = stream.total_out;
-
-    err = inflateEnd(&stream);
-    return err;
-}
diff --git a/Lib/zlib/zconf.h b/Lib/zlib/zconf.h
deleted file mode 100644
index 6d450fc79..000000000
--- a/Lib/zlib/zconf.h
+++ /dev/null
@@ -1,279 +0,0 @@
-/* zconf.h -- configuration of the zlib compression library
- * Copyright (C) 1995-1998 Jean-loup Gailly.
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* @(#) $Id$ */
-
-#ifndef _ZCONF_H
-#define _ZCONF_H
-
-/*
- * If you *really* need a unique prefix for all types and library functions,
- * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
- */
-#ifdef Z_PREFIX
-#  define deflateInit_	z_deflateInit_
-#  define deflate	z_deflate
-#  define deflateEnd	z_deflateEnd
-#  define inflateInit_ 	z_inflateInit_
-#  define inflate	z_inflate
-#  define inflateEnd	z_inflateEnd
-#  define deflateInit2_	z_deflateInit2_
-#  define deflateSetDictionary z_deflateSetDictionary
-#  define deflateCopy	z_deflateCopy
-#  define deflateReset	z_deflateReset
-#  define deflateParams	z_deflateParams
-#  define inflateInit2_	z_inflateInit2_
-#  define inflateSetDictionary z_inflateSetDictionary
-#  define inflateSync	z_inflateSync
-#  define inflateSyncPoint z_inflateSyncPoint
-#  define inflateReset	z_inflateReset
-#  define compress	z_compress
-#  define compress2	z_compress2
-#  define uncompress	z_uncompress
-#  define adler32	z_adler32
-#  define crc32		z_crc32
-#  define get_crc_table z_get_crc_table
-
-#  define Byte		z_Byte
-#  define uInt		z_uInt
-#  define uLong		z_uLong
-#  define Bytef	        z_Bytef
-#  define charf		z_charf
-#  define intf		z_intf
-#  define uIntf		z_uIntf
-#  define uLongf	z_uLongf
-#  define voidpf	z_voidpf
-#  define voidp		z_voidp
-#endif
-
-#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
-#  define WIN32
-#endif
-#if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386)
-#  ifndef __32BIT__
-#    define __32BIT__
-#  endif
-#endif
-#if defined(__MSDOS__) && !defined(MSDOS)
-#  define MSDOS
-#endif
-
-/*
- * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
- * than 64k bytes at a time (needed on systems with 16-bit int).
- */
-#if defined(MSDOS) && !defined(__32BIT__)
-#  define MAXSEG_64K
-#endif
-#ifdef MSDOS
-#  define UNALIGNED_OK
-#endif
-
-#if (defined(MSDOS) || defined(_WINDOWS) || defined(WIN32))  && !defined(STDC)
-#  define STDC
-#endif
-#if defined(__STDC__) || defined(__cplusplus) || defined(__OS2__)
-#  ifndef STDC
-#    define STDC
-#  endif
-#endif
-
-#ifndef STDC
-#  ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
-#    define const
-#  endif
-#endif
-
-/* Some Mac compilers merge all .h files incorrectly: */
-#if defined(__MWERKS__) || defined(applec) ||defined(THINK_C) ||defined(__SC__)
-#  define NO_DUMMY_DECL
-#endif
-
-/* Old Borland C incorrectly complains about missing returns: */
-#if defined(__BORLANDC__) && (__BORLANDC__ < 0x500)
-#  define NEED_DUMMY_RETURN
-#endif
-
-
-/* Maximum value for memLevel in deflateInit2 */
-#ifndef MAX_MEM_LEVEL
-#  ifdef MAXSEG_64K
-#    define MAX_MEM_LEVEL 8
-#  else
-#    define MAX_MEM_LEVEL 9
-#  endif
-#endif
-
-/* Maximum value for windowBits in deflateInit2 and inflateInit2.
- * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
- * created by gzip. (Files created by minigzip can still be extracted by
- * gzip.)
- */
-#ifndef MAX_WBITS
-#  define MAX_WBITS   15 /* 32K LZ77 window */
-#endif
-
-/* The memory requirements for deflate are (in bytes):
-            (1 << (windowBits+2)) +  (1 << (memLevel+9))
- that is: 128K for windowBits=15  +  128K for memLevel = 8  (default values)
- plus a few kilobytes for small objects. For example, if you want to reduce
- the default memory requirements from 256K to 128K, compile with
-     make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
- Of course this will generally degrade compression (there's no free lunch).
-
-   The memory requirements for inflate are (in bytes) 1 << windowBits
- that is, 32K for windowBits=15 (default value) plus a few kilobytes
- for small objects.
-*/
-
-                        /* Type declarations */
-
-#ifndef OF /* function prototypes */
-#  ifdef STDC
-#    define OF(args)  args
-#  else
-#    define OF(args)  ()
-#  endif
-#endif
-
-/* The following definitions for FAR are needed only for MSDOS mixed
- * model programming (small or medium model with some far allocations).
- * This was tested only with MSC; for other MSDOS compilers you may have
- * to define NO_MEMCPY in zutil.h.  If you don't need the mixed model,
- * just define FAR to be empty.
- */
-#if (defined(M_I86SM) || defined(M_I86MM)) && !defined(__32BIT__)
-   /* MSC small or medium model */
-#  define SMALL_MEDIUM
-#  ifdef _MSC_VER
-#    define FAR _far
-#  else
-#    define FAR far
-#  endif
-#endif
-#if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__MEDIUM__))
-#  ifndef __32BIT__
-#    define SMALL_MEDIUM
-#    define FAR _far
-#  endif
-#endif
-
-/* Compile with -DZLIB_DLL for Windows DLL support */
-#if defined(ZLIB_DLL)
-#  if defined(_WINDOWS) || defined(WINDOWS)
-#    ifdef FAR
-#      undef FAR
-#    endif
-#    include 
-#    define ZEXPORT  WINAPI
-#    ifdef WIN32
-#      define ZEXPORTVA  WINAPIV
-#    else
-#      define ZEXPORTVA  FAR _cdecl _export
-#    endif
-#  endif
-#  if defined (__BORLANDC__)
-#    if (__BORLANDC__ >= 0x0500) && defined (WIN32)
-#      include 
-#      define ZEXPORT __declspec(dllexport) WINAPI
-#      define ZEXPORTRVA __declspec(dllexport) WINAPIV
-#    else
-#      if defined (_Windows) && defined (__DLL__)
-#        define ZEXPORT _export
-#        define ZEXPORTVA _export
-#      endif
-#    endif
-#  endif
-#endif
-
-#if defined (__BEOS__)
-#  if defined (ZLIB_DLL)
-#    define ZEXTERN extern __declspec(dllexport)
-#  else
-#    define ZEXTERN extern __declspec(dllimport)
-#  endif
-#endif
-
-#ifndef ZEXPORT
-#  define ZEXPORT
-#endif
-#ifndef ZEXPORTVA
-#  define ZEXPORTVA
-#endif
-#ifndef ZEXTERN
-#  define ZEXTERN extern
-#endif
-
-#ifndef FAR
-#   define FAR
-#endif
-
-#if !defined(MACOS) && !defined(TARGET_OS_MAC)
-typedef unsigned char  Byte;  /* 8 bits */
-#endif
-typedef unsigned int   uInt;  /* 16 bits or more */
-typedef unsigned long  uLong; /* 32 bits or more */
-
-#ifdef SMALL_MEDIUM
-   /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
-#  define Bytef Byte FAR
-#else
-   typedef Byte  FAR Bytef;
-#endif
-typedef char  FAR charf;
-typedef int   FAR intf;
-typedef uInt  FAR uIntf;
-typedef uLong FAR uLongf;
-
-#ifdef STDC
-   typedef void FAR *voidpf;
-   typedef void     *voidp;
-#else
-   typedef Byte FAR *voidpf;
-   typedef Byte     *voidp;
-#endif
-
-#ifdef HAVE_UNISTD_H
-#  include  /* for off_t */
-#  include     /* for SEEK_* and off_t */
-#  define z_off_t  off_t
-#endif
-#ifndef SEEK_SET
-#  define SEEK_SET        0       /* Seek from beginning of file.  */
-#  define SEEK_CUR        1       /* Seek from current position.  */
-#  define SEEK_END        2       /* Set file pointer to EOF plus "offset" */
-#endif
-#ifndef z_off_t
-#  define  z_off_t long
-#endif
-
-/* MVS linker does not support external names larger than 8 bytes */
-#if defined(__MVS__)
-#   pragma map(deflateInit_,"DEIN")
-#   pragma map(deflateInit2_,"DEIN2")
-#   pragma map(deflateEnd,"DEEND")
-#   pragma map(inflateInit_,"ININ")
-#   pragma map(inflateInit2_,"ININ2")
-#   pragma map(inflateEnd,"INEND")
-#   pragma map(inflateSync,"INSY")
-#   pragma map(inflateSetDictionary,"INSEDI")
-#   pragma map(inflate_blocks,"INBL")
-#   pragma map(inflate_blocks_new,"INBLNE")
-#   pragma map(inflate_blocks_free,"INBLFR")
-#   pragma map(inflate_blocks_reset,"INBLRE")
-#   pragma map(inflate_codes_free,"INCOFR")
-#   pragma map(inflate_codes,"INCO")
-#   pragma map(inflate_fast,"INFA")
-#   pragma map(inflate_flush,"INFLU")
-#   pragma map(inflate_mask,"INMA")
-#   pragma map(inflate_set_dictionary,"INSEDI2")
-#   pragma map(inflate_copyright,"INCOPY")
-#   pragma map(inflate_trees_bits,"INTRBI")
-#   pragma map(inflate_trees_dynamic,"INTRDY")
-#   pragma map(inflate_trees_fixed,"INTRFI")
-#   pragma map(inflate_trees_free,"INTRFR")
-#endif
-
-#endif /* _ZCONF_H */
diff --git a/Lib/zlib/zlib.3 b/Lib/zlib/zlib.3
deleted file mode 100644
index 25c8495d2..000000000
--- a/Lib/zlib/zlib.3
+++ /dev/null
@@ -1,107 +0,0 @@
-.TH ZLIB 3 "9 July 1998"
-.SH NAME
-zlib \- compression/decompression library
-.SH SYNOPSIS
-[see
-.I zlib.h
-for full description]
-.SH DESCRIPTION
-The
-.I zlib
-library is a general purpose data compression library.
-The code is thread safe.
-It provides in-memory compression and decompression functions,
-including integrity checks of the uncompressed data.
-This version of the library supports only one compression method (deflation)
-but other algorithms will be added later and will have the same stream interface.
-.LP
-Compression can be done in a single step if the buffers are large enough
-(for example if an input file is mmap'ed),
-or can be done by repeated calls of the compression function.
-In the latter case,
-the application must provide more input and/or consume the output
-(providing more output space) before each call.
-.LP
-The library also supports reading and writing files in
-.I gzip
-(.gz) format
-with an interface similar to that of stdio.
-.LP
-The library does not install any signal handler. The decoder checks
-the consistency of the compressed data, so the library should never
-crash even in case of corrupted input.
-.LP
-All functions of the compression library are documented in the file
-.IR zlib.h.
-The distribution source includes examples of use of the library
-the files
-.I example.c
-and
-.IR minigzip.c .
-.LP
-A Java implementation of
-.IR zlib
-is available in the Java Development Kit 1.1
-.IP
-http://www.javasoft.com/products/JDK/1.1/docs/api/Package-java.util.zip.html
-.LP
-A Perl interface to
-.IR zlib ,
-written by Paul Marquess (pmarquess@bfsec.bt.co.uk)
-is available at CPAN (Comprehensive Perl Archive Network) sites,
-such as:
-.IP
-ftp://ftp.cis.ufl.edu/pub/perl/CPAN/modules/by-module/Compress/Compress-Zlib*
-.LP
-A Python interface to
-.IR zlib
-written by A.M. Kuchling 
-is available from the Python Software Association sites, such as:
-.IP
-ftp://ftp.python.org/pub/python/contrib/Encoding/zlib*.tar.gz
-.SH "SEE ALSO"
-Questions about zlib should be sent to:
-.IP
-zlib@quest.jpl.nasa.gov
-or, if this fails, to the author addresses given below.
-The zlib home page is:
-.IP
-http://www.cdrom.com/pub/infozip/zlib/
-.LP
-The data format used by the zlib library is described by RFC
-(Request for Comments) 1950 to 1952 in the files: 
-.IP
-ftp://ds.internic.net/rfc/rfc1950.txt (zlib format)
-.br
-rfc1951.txt (deflate format)
-.br
-rfc1952.txt (gzip format)
-.LP
-These documents are also available in other formats from:
-.IP
-ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html
-.SH AUTHORS
-Version 1.1.3
-Copyright (C) 1995-1998 Jean-loup Gailly (jloup@gzip.org)
-and Mark Adler (madler@alumni.caltech.edu).
-.LP
-This software is provided "as-is,"
-without any express or implied warranty.
-In no event will the authors be held liable for any damages
-arising from the use of this software.
-See the distribution directory with respect to requirements
-governing redistribution.
-The deflate format used by
-.I zlib
-was defined by Phil Katz.
-The deflate and
-.I zlib
-specifications were written by L. Peter Deutsch.
-Thanks to all the people who reported problems and suggested various
-improvements in
-.IR zlib ;
-who are too numerous to cite here.
-.LP
-UNIX manual page by R. P. C. Rodgers,
-U.S. National Library of Medicine (rodgers@nlm.nih.gov).
-.\" end of man page
diff --git a/Lib/zlib/zlib.h b/Lib/zlib/zlib.h
deleted file mode 100644
index 49f56b43b..000000000
--- a/Lib/zlib/zlib.h
+++ /dev/null
@@ -1,893 +0,0 @@
-/* zlib.h -- interface of the 'zlib' general purpose compression library
-  version 1.1.3, July 9th, 1998
-
-  Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler
-
-  This software is provided 'as-is', without any express or implied
-  warranty.  In no event will the authors be held liable for any damages
-  arising from the use of this software.
-
-  Permission is granted to anyone to use this software for any purpose,
-  including commercial applications, and to alter it and redistribute it
-  freely, subject to the following restrictions:
-
-  1. The origin of this software must not be misrepresented; you must not
-     claim that you wrote the original software. If you use this software
-     in a product, an acknowledgment in the product documentation would be
-     appreciated but is not required.
-  2. Altered source versions must be plainly marked as such, and must not be
-     misrepresented as being the original software.
-  3. This notice may not be removed or altered from any source distribution.
-
-  Jean-loup Gailly        Mark Adler
-  jloup@gzip.org          madler@alumni.caltech.edu
-
-
-  The data format used by the zlib library is described by RFCs (Request for
-  Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt
-  (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
-*/
-
-#ifndef _ZLIB_H
-#define _ZLIB_H
-
-#include "zconf.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define ZLIB_VERSION "1.1.3"
-
-/* 
-     The 'zlib' compression library provides in-memory compression and
-  decompression functions, including integrity checks of the uncompressed
-  data.  This version of the library supports only one compression method
-  (deflation) but other algorithms will be added later and will have the same
-  stream interface.
-
-     Compression can be done in a single step if the buffers are large
-  enough (for example if an input file is mmap'ed), or can be done by
-  repeated calls of the compression function.  In the latter case, the
-  application must provide more input and/or consume the output
-  (providing more output space) before each call.
-
-     The library also supports reading and writing files in gzip (.gz) format
-  with an interface similar to that of stdio.
-
-     The library does not install any signal handler. The decoder checks
-  the consistency of the compressed data, so the library should never
-  crash even in case of corrupted input.
-*/
-
-typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
-typedef void   (*free_func)  OF((voidpf opaque, voidpf address));
-
-struct internal_state;
-
-typedef struct z_stream_s {
-    Bytef    *next_in;  /* next input byte */
-    uInt     avail_in;  /* number of bytes available at next_in */
-    uLong    total_in;  /* total nb of input bytes read so far */
-
-    Bytef    *next_out; /* next output byte should be put there */
-    uInt     avail_out; /* remaining free space at next_out */
-    uLong    total_out; /* total nb of bytes output so far */
-
-    char     *msg;      /* last error message, NULL if no error */
-    struct internal_state FAR *state; /* not visible by applications */
-
-    alloc_func zalloc;  /* used to allocate the internal state */
-    free_func  zfree;   /* used to free the internal state */
-    voidpf     opaque;  /* private data object passed to zalloc and zfree */
-
-    int     data_type;  /* best guess about the data type: ascii or binary */
-    uLong   adler;      /* adler32 value of the uncompressed data */
-    uLong   reserved;   /* reserved for future use */
-} z_stream;
-
-typedef z_stream FAR *z_streamp;
-
-/*
-   The application must update next_in and avail_in when avail_in has
-   dropped to zero. It must update next_out and avail_out when avail_out
-   has dropped to zero. The application must initialize zalloc, zfree and
-   opaque before calling the init function. All other fields are set by the
-   compression library and must not be updated by the application.
-
-   The opaque value provided by the application will be passed as the first
-   parameter for calls of zalloc and zfree. This can be useful for custom
-   memory management. The compression library attaches no meaning to the
-   opaque value.
-
-   zalloc must return Z_NULL if there is not enough memory for the object.
-   If zlib is used in a multi-threaded application, zalloc and zfree must be
-   thread safe.
-
-   On 16-bit systems, the functions zalloc and zfree must be able to allocate
-   exactly 65536 bytes, but will not be required to allocate more than this
-   if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
-   pointers returned by zalloc for objects of exactly 65536 bytes *must*
-   have their offset normalized to zero. The default allocation function
-   provided by this library ensures this (see zutil.c). To reduce memory
-   requirements and avoid any allocation of 64K objects, at the expense of
-   compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
-
-   The fields total_in and total_out can be used for statistics or
-   progress reports. After compression, total_in holds the total size of
-   the uncompressed data and may be saved for use in the decompressor
-   (particularly if the decompressor wants to decompress everything in
-   a single step).
-*/
-
-                        /* constants */
-
-#define Z_NO_FLUSH      0
-#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */
-#define Z_SYNC_FLUSH    2
-#define Z_FULL_FLUSH    3
-#define Z_FINISH        4
-/* Allowed flush values; see deflate() below for details */
-
-#define Z_OK            0
-#define Z_STREAM_END    1
-#define Z_NEED_DICT     2
-#define Z_ERRNO        (-1)
-#define Z_STREAM_ERROR (-2)
-#define Z_DATA_ERROR   (-3)
-#define Z_MEM_ERROR    (-4)
-#define Z_BUF_ERROR    (-5)
-#define Z_VERSION_ERROR (-6)
-/* Return codes for the compression/decompression functions. Negative
- * values are errors, positive values are used for special but normal events.
- */
-
-#define Z_NO_COMPRESSION         0
-#define Z_BEST_SPEED             1
-#define Z_BEST_COMPRESSION       9
-#define Z_DEFAULT_COMPRESSION  (-1)
-/* compression levels */
-
-#define Z_FILTERED            1
-#define Z_HUFFMAN_ONLY        2
-#define Z_DEFAULT_STRATEGY    0
-/* compression strategy; see deflateInit2() below for details */
-
-#define Z_BINARY   0
-#define Z_ASCII    1
-#define Z_UNKNOWN  2
-/* Possible values of the data_type field */
-
-#define Z_DEFLATED   8
-/* The deflate compression method (the only one supported in this version) */
-
-#define Z_NULL  0  /* for initializing zalloc, zfree, opaque */
-
-#define zlib_version zlibVersion()
-/* for compatibility with versions < 1.0.2 */
-
-                        /* basic functions */
-
-ZEXTERN const char * ZEXPORT zlibVersion OF((void));
-/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
-   If the first character differs, the library code actually used is
-   not compatible with the zlib.h header file used by the application.
-   This check is automatically made by deflateInit and inflateInit.
- */
-
-/* 
-ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level));
-
-     Initializes the internal stream state for compression. The fields
-   zalloc, zfree and opaque must be initialized before by the caller.
-   If zalloc and zfree are set to Z_NULL, deflateInit updates them to
-   use default allocation functions.
-
-     The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
-   1 gives best speed, 9 gives best compression, 0 gives no compression at
-   all (the input data is simply copied a block at a time).
-   Z_DEFAULT_COMPRESSION requests a default compromise between speed and
-   compression (currently equivalent to level 6).
-
-     deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
-   enough memory, Z_STREAM_ERROR if level is not a valid compression level,
-   Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
-   with the version assumed by the caller (ZLIB_VERSION).
-   msg is set to null if there is no error message.  deflateInit does not
-   perform any compression: this will be done by deflate().
-*/
-
-
-ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
-/*
-    deflate compresses as much data as possible, and stops when the input
-  buffer becomes empty or the output buffer becomes full. It may introduce some
-  output latency (reading input without producing any output) except when
-  forced to flush.
-
-    The detailed semantics are as follows. deflate performs one or both of the
-  following actions:
-
-  - Compress more input starting at next_in and update next_in and avail_in
-    accordingly. If not all input can be processed (because there is not
-    enough room in the output buffer), next_in and avail_in are updated and
-    processing will resume at this point for the next call of deflate().
-
-  - Provide more output starting at next_out and update next_out and avail_out
-    accordingly. This action is forced if the parameter flush is non zero.
-    Forcing flush frequently degrades the compression ratio, so this parameter
-    should be set only when necessary (in interactive applications).
-    Some output may be provided even if flush is not set.
-
-  Before the call of deflate(), the application should ensure that at least
-  one of the actions is possible, by providing more input and/or consuming
-  more output, and updating avail_in or avail_out accordingly; avail_out
-  should never be zero before the call. The application can consume the
-  compressed output when it wants, for example when the output buffer is full
-  (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK
-  and with zero avail_out, it must be called again after making room in the
-  output buffer because there might be more output pending.
-
-    If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
-  flushed to the output buffer and the output is aligned on a byte boundary, so
-  that the decompressor can get all input data available so far. (In particular
-  avail_in is zero after the call if enough output space has been provided
-  before the call.)  Flushing may degrade compression for some compression
-  algorithms and so it should be used only when necessary.
-
-    If flush is set to Z_FULL_FLUSH, all output is flushed as with
-  Z_SYNC_FLUSH, and the compression state is reset so that decompression can
-  restart from this point if previous compressed data has been damaged or if
-  random access is desired. Using Z_FULL_FLUSH too often can seriously degrade
-  the compression.
-
-    If deflate returns with avail_out == 0, this function must be called again
-  with the same value of the flush parameter and more output space (updated
-  avail_out), until the flush is complete (deflate returns with non-zero
-  avail_out).
-
-    If the parameter flush is set to Z_FINISH, pending input is processed,
-  pending output is flushed and deflate returns with Z_STREAM_END if there
-  was enough output space; if deflate returns with Z_OK, this function must be
-  called again with Z_FINISH and more output space (updated avail_out) but no
-  more input data, until it returns with Z_STREAM_END or an error. After
-  deflate has returned Z_STREAM_END, the only possible operations on the
-  stream are deflateReset or deflateEnd.
-  
-    Z_FINISH can be used immediately after deflateInit if all the compression
-  is to be done in a single step. In this case, avail_out must be at least
-  0.1% larger than avail_in plus 12 bytes.  If deflate does not return
-  Z_STREAM_END, then it must be called again as described above.
-
-    deflate() sets strm->adler to the adler32 checksum of all input read
-  so far (that is, total_in bytes).
-
-    deflate() may update data_type if it can make a good guess about
-  the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered
-  binary. This field is only for information purposes and does not affect
-  the compression algorithm in any manner.
-
-    deflate() returns Z_OK if some progress has been made (more input
-  processed or more output produced), Z_STREAM_END if all input has been
-  consumed and all output has been produced (only when flush is set to
-  Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
-  if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible
-  (for example avail_in or avail_out was zero).
-*/
-
-
-ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));
-/*
-     All dynamically allocated data structures for this stream are freed.
-   This function discards any unprocessed input and does not flush any
-   pending output.
-
-     deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
-   stream state was inconsistent, Z_DATA_ERROR if the stream was freed
-   prematurely (some input or output was discarded). In the error case,
-   msg may be set but then points to a static string (which must not be
-   deallocated).
-*/
-
-
-/* 
-ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));
-
-     Initializes the internal stream state for decompression. The fields
-   next_in, avail_in, zalloc, zfree and opaque must be initialized before by
-   the caller. If next_in is not Z_NULL and avail_in is large enough (the exact
-   value depends on the compression method), inflateInit determines the
-   compression method from the zlib header and allocates all data structures
-   accordingly; otherwise the allocation will be deferred to the first call of
-   inflate.  If zalloc and zfree are set to Z_NULL, inflateInit updates them to
-   use default allocation functions.
-
-     inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
-   memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
-   version assumed by the caller.  msg is set to null if there is no error
-   message. inflateInit does not perform any decompression apart from reading
-   the zlib header if present: this will be done by inflate().  (So next_in and
-   avail_in may be modified, but next_out and avail_out are unchanged.)
-*/
-
-
-ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
-/*
-    inflate decompresses as much data as possible, and stops when the input
-  buffer becomes empty or the output buffer becomes full. It may some
-  introduce some output latency (reading input without producing any output)
-  except when forced to flush.
-
-  The detailed semantics are as follows. inflate performs one or both of the
-  following actions:
-
-  - Decompress more input starting at next_in and update next_in and avail_in
-    accordingly. If not all input can be processed (because there is not
-    enough room in the output buffer), next_in is updated and processing
-    will resume at this point for the next call of inflate().
-
-  - Provide more output starting at next_out and update next_out and avail_out
-    accordingly.  inflate() provides as much output as possible, until there
-    is no more input data or no more space in the output buffer (see below
-    about the flush parameter).
-
-  Before the call of inflate(), the application should ensure that at least
-  one of the actions is possible, by providing more input and/or consuming
-  more output, and updating the next_* and avail_* values accordingly.
-  The application can consume the uncompressed output when it wants, for
-  example when the output buffer is full (avail_out == 0), or after each
-  call of inflate(). If inflate returns Z_OK and with zero avail_out, it
-  must be called again after making room in the output buffer because there
-  might be more output pending.
-
-    If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much
-  output as possible to the output buffer. The flushing behavior of inflate is
-  not specified for values of the flush parameter other than Z_SYNC_FLUSH
-  and Z_FINISH, but the current implementation actually flushes as much output
-  as possible anyway.
-
-    inflate() should normally be called until it returns Z_STREAM_END or an
-  error. However if all decompression is to be performed in a single step
-  (a single call of inflate), the parameter flush should be set to
-  Z_FINISH. In this case all pending input is processed and all pending
-  output is flushed; avail_out must be large enough to hold all the
-  uncompressed data. (The size of the uncompressed data may have been saved
-  by the compressor for this purpose.) The next operation on this stream must
-  be inflateEnd to deallocate the decompression state. The use of Z_FINISH
-  is never required, but can be used to inform inflate that a faster routine
-  may be used for the single inflate() call.
-
-     If a preset dictionary is needed at this point (see inflateSetDictionary
-  below), inflate sets strm-adler to the adler32 checksum of the
-  dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise 
-  it sets strm->adler to the adler32 checksum of all output produced
-  so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or
-  an error code as described below. At the end of the stream, inflate()
-  checks that its computed adler32 checksum is equal to that saved by the
-  compressor and returns Z_STREAM_END only if the checksum is correct.
-
-    inflate() returns Z_OK if some progress has been made (more input processed
-  or more output produced), Z_STREAM_END if the end of the compressed data has
-  been reached and all uncompressed output has been produced, Z_NEED_DICT if a
-  preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
-  corrupted (input stream not conforming to the zlib format or incorrect
-  adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent
-  (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not
-  enough memory, Z_BUF_ERROR if no progress is possible or if there was not
-  enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR
-  case, the application may then call inflateSync to look for a good
-  compression block.
-*/
-
-
-ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm));
-/*
-     All dynamically allocated data structures for this stream are freed.
-   This function discards any unprocessed input and does not flush any
-   pending output.
-
-     inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
-   was inconsistent. In the error case, msg may be set but then points to a
-   static string (which must not be deallocated).
-*/
-
-                        /* Advanced functions */
-
-/*
-    The following functions are needed only in some special applications.
-*/
-
-/*   
-ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
-                                     int  level,
-                                     int  method,
-                                     int  windowBits,
-                                     int  memLevel,
-                                     int  strategy));
-
-     This is another version of deflateInit with more compression options. The
-   fields next_in, zalloc, zfree and opaque must be initialized before by
-   the caller.
-
-     The method parameter is the compression method. It must be Z_DEFLATED in
-   this version of the library.
-
-     The windowBits parameter is the base two logarithm of the window size
-   (the size of the history buffer).  It should be in the range 8..15 for this
-   version of the library. Larger values of this parameter result in better
-   compression at the expense of memory usage. The default value is 15 if
-   deflateInit is used instead.
-
-     The memLevel parameter specifies how much memory should be allocated
-   for the internal compression state. memLevel=1 uses minimum memory but
-   is slow and reduces compression ratio; memLevel=9 uses maximum memory
-   for optimal speed. The default value is 8. See zconf.h for total memory
-   usage as a function of windowBits and memLevel.
-
-     The strategy parameter is used to tune the compression algorithm. Use the
-   value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
-   filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no
-   string match).  Filtered data consists mostly of small values with a
-   somewhat random distribution. In this case, the compression algorithm is
-   tuned to compress them better. The effect of Z_FILTERED is to force more
-   Huffman coding and less string matching; it is somewhat intermediate
-   between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects
-   the compression ratio but not the correctness of the compressed output even
-   if it is not set appropriately.
-
-      deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
-   memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid
-   method). msg is set to null if there is no error message.  deflateInit2 does
-   not perform any compression: this will be done by deflate().
-*/
-                            
-ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
-                                             const Bytef *dictionary,
-                                             uInt  dictLength));
-/*
-     Initializes the compression dictionary from the given byte sequence
-   without producing any compressed output. This function must be called
-   immediately after deflateInit, deflateInit2 or deflateReset, before any
-   call of deflate. The compressor and decompressor must use exactly the same
-   dictionary (see inflateSetDictionary).
-
-     The dictionary should consist of strings (byte sequences) that are likely
-   to be encountered later in the data to be compressed, with the most commonly
-   used strings preferably put towards the end of the dictionary. Using a
-   dictionary is most useful when the data to be compressed is short and can be
-   predicted with good accuracy; the data can then be compressed better than
-   with the default empty dictionary.
-
-     Depending on the size of the compression data structures selected by
-   deflateInit or deflateInit2, a part of the dictionary may in effect be
-   discarded, for example if the dictionary is larger than the window size in
-   deflate or deflate2. Thus the strings most likely to be useful should be
-   put at the end of the dictionary, not at the front.
-
-     Upon return of this function, strm->adler is set to the Adler32 value
-   of the dictionary; the decompressor may later use this value to determine
-   which dictionary has been used by the compressor. (The Adler32 value
-   applies to the whole dictionary even if only a subset of the dictionary is
-   actually used by the compressor.)
-
-     deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
-   parameter is invalid (such as NULL dictionary) or the stream state is
-   inconsistent (for example if deflate has already been called for this stream
-   or if the compression method is bsort). deflateSetDictionary does not
-   perform any compression: this will be done by deflate().
-*/
-
-ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,
-                                    z_streamp source));
-/*
-     Sets the destination stream as a complete copy of the source stream.
-
-     This function can be useful when several compression strategies will be
-   tried, for example when there are several ways of pre-processing the input
-   data with a filter. The streams that will be discarded should then be freed
-   by calling deflateEnd.  Note that deflateCopy duplicates the internal
-   compression state which can be quite large, so this strategy is slow and
-   can consume lots of memory.
-
-     deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
-   enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
-   (such as zalloc being NULL). msg is left unchanged in both source and
-   destination.
-*/
-
-ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm));
-/*
-     This function is equivalent to deflateEnd followed by deflateInit,
-   but does not free and reallocate all the internal compression state.
-   The stream will keep the same compression level and any other attributes
-   that may have been set by deflateInit2.
-
-      deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
-   stream state was inconsistent (such as zalloc or state being NULL).
-*/
-
-ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
-				      int level,
-				      int strategy));
-/*
-     Dynamically update the compression level and compression strategy.  The
-   interpretation of level and strategy is as in deflateInit2.  This can be
-   used to switch between compression and straight copy of the input data, or
-   to switch to a different kind of input data requiring a different
-   strategy. If the compression level is changed, the input available so far
-   is compressed with the old level (and may be flushed); the new level will
-   take effect only at the next call of deflate().
-
-     Before the call of deflateParams, the stream state must be set as for
-   a call of deflate(), since the currently available input may have to
-   be compressed and flushed. In particular, strm->avail_out must be non-zero.
-
-     deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source
-   stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR
-   if strm->avail_out was zero.
-*/
-
-/*   
-ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
-                                     int  windowBits));
-
-     This is another version of inflateInit with an extra parameter. The
-   fields next_in, avail_in, zalloc, zfree and opaque must be initialized
-   before by the caller.
-
-     The windowBits parameter is the base two logarithm of the maximum window
-   size (the size of the history buffer).  It should be in the range 8..15 for
-   this version of the library. The default value is 15 if inflateInit is used
-   instead. If a compressed stream with a larger window size is given as
-   input, inflate() will return with the error code Z_DATA_ERROR instead of
-   trying to allocate a larger window.
-
-      inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
-   memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative
-   memLevel). msg is set to null if there is no error message.  inflateInit2
-   does not perform any decompression apart from reading the zlib header if
-   present: this will be done by inflate(). (So next_in and avail_in may be
-   modified, but next_out and avail_out are unchanged.)
-*/
-
-ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
-                                             const Bytef *dictionary,
-                                             uInt  dictLength));
-/*
-     Initializes the decompression dictionary from the given uncompressed byte
-   sequence. This function must be called immediately after a call of inflate
-   if this call returned Z_NEED_DICT. The dictionary chosen by the compressor
-   can be determined from the Adler32 value returned by this call of
-   inflate. The compressor and decompressor must use exactly the same
-   dictionary (see deflateSetDictionary).
-
-     inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
-   parameter is invalid (such as NULL dictionary) or the stream state is
-   inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
-   expected one (incorrect Adler32 value). inflateSetDictionary does not
-   perform any decompression: this will be done by subsequent calls of
-   inflate().
-*/
-
-ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));
-/* 
-    Skips invalid compressed data until a full flush point (see above the
-  description of deflate with Z_FULL_FLUSH) can be found, or until all
-  available input is skipped. No output is provided.
-
-    inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR
-  if no more input was provided, Z_DATA_ERROR if no flush point has been found,
-  or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
-  case, the application may save the current current value of total_in which
-  indicates where valid compressed data was found. In the error case, the
-  application may repeatedly call inflateSync, providing more input each time,
-  until success or end of the input data.
-*/
-
-ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm));
-/*
-     This function is equivalent to inflateEnd followed by inflateInit,
-   but does not free and reallocate all the internal decompression state.
-   The stream will keep attributes that may have been set by inflateInit2.
-
-      inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
-   stream state was inconsistent (such as zalloc or state being NULL).
-*/
-
-
-                        /* utility functions */
-
-/*
-     The following utility functions are implemented on top of the
-   basic stream-oriented functions. To simplify the interface, some
-   default options are assumed (compression level and memory usage,
-   standard memory allocation functions). The source code of these
-   utility functions can easily be modified if you need special options.
-*/
-
-ZEXTERN int ZEXPORT compress OF((Bytef *dest,   uLongf *destLen,
-                                 const Bytef *source, uLong sourceLen));
-/*
-     Compresses the source buffer into the destination buffer.  sourceLen is
-   the byte length of the source buffer. Upon entry, destLen is the total
-   size of the destination buffer, which must be at least 0.1% larger than
-   sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the
-   compressed buffer.
-     This function can be used to compress a whole file at once if the
-   input file is mmap'ed.
-     compress returns Z_OK if success, Z_MEM_ERROR if there was not
-   enough memory, Z_BUF_ERROR if there was not enough room in the output
-   buffer.
-*/
-
-ZEXTERN int ZEXPORT compress2 OF((Bytef *dest,   uLongf *destLen,
-                                  const Bytef *source, uLong sourceLen,
-                                  int level));
-/*
-     Compresses the source buffer into the destination buffer. The level
-   parameter has the same meaning as in deflateInit.  sourceLen is the byte
-   length of the source buffer. Upon entry, destLen is the total size of the
-   destination buffer, which must be at least 0.1% larger than sourceLen plus
-   12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
-
-     compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
-   memory, Z_BUF_ERROR if there was not enough room in the output buffer,
-   Z_STREAM_ERROR if the level parameter is invalid.
-*/
-
-ZEXTERN int ZEXPORT uncompress OF((Bytef *dest,   uLongf *destLen,
-                                   const Bytef *source, uLong sourceLen));
-/*
-     Decompresses the source buffer into the destination buffer.  sourceLen is
-   the byte length of the source buffer. Upon entry, destLen is the total
-   size of the destination buffer, which must be large enough to hold the
-   entire uncompressed data. (The size of the uncompressed data must have
-   been saved previously by the compressor and transmitted to the decompressor
-   by some mechanism outside the scope of this compression library.)
-   Upon exit, destLen is the actual size of the compressed buffer.
-     This function can be used to decompress a whole file at once if the
-   input file is mmap'ed.
-
-     uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
-   enough memory, Z_BUF_ERROR if there was not enough room in the output
-   buffer, or Z_DATA_ERROR if the input data was corrupted.
-*/
-
-
-typedef voidp gzFile;
-
-ZEXTERN gzFile ZEXPORT gzopen  OF((const char *path, const char *mode));
-/*
-     Opens a gzip (.gz) file for reading or writing. The mode parameter
-   is as in fopen ("rb" or "wb") but can also include a compression level
-   ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for
-   Huffman only compression as in "wb1h". (See the description
-   of deflateInit2 for more information about the strategy parameter.)
-
-     gzopen can be used to read a file which is not in gzip format; in this
-   case gzread will directly read from the file without decompression.
-
-     gzopen returns NULL if the file could not be opened or if there was
-   insufficient memory to allocate the (de)compression state; errno
-   can be checked to distinguish the two cases (if errno is zero, the
-   zlib error is Z_MEM_ERROR).  */
-
-ZEXTERN gzFile ZEXPORT gzdopen  OF((int fd, const char *mode));
-/*
-     gzdopen() associates a gzFile with the file descriptor fd.  File
-   descriptors are obtained from calls like open, dup, creat, pipe or
-   fileno (in the file has been previously opened with fopen).
-   The mode parameter is as in gzopen.
-     The next call of gzclose on the returned gzFile will also close the
-   file descriptor fd, just like fclose(fdopen(fd), mode) closes the file
-   descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode).
-     gzdopen returns NULL if there was insufficient memory to allocate
-   the (de)compression state.
-*/
-
-ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
-/*
-     Dynamically update the compression level or strategy. See the description
-   of deflateInit2 for the meaning of these parameters.
-     gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not
-   opened for writing.
-*/
-
-ZEXTERN int ZEXPORT    gzread  OF((gzFile file, voidp buf, unsigned len));
-/*
-     Reads the given number of uncompressed bytes from the compressed file.
-   If the input file was not in gzip format, gzread copies the given number
-   of bytes into the buffer.
-     gzread returns the number of uncompressed bytes actually read (0 for
-   end of file, -1 for error). */
-
-ZEXTERN int ZEXPORT    gzwrite OF((gzFile file, 
-				   const voidp buf, unsigned len));
-/*
-     Writes the given number of uncompressed bytes into the compressed file.
-   gzwrite returns the number of uncompressed bytes actually written
-   (0 in case of error).
-*/
-
-ZEXTERN int ZEXPORTVA   gzprintf OF((gzFile file, const char *format, ...));
-/*
-     Converts, formats, and writes the args to the compressed file under
-   control of the format string, as in fprintf. gzprintf returns the number of
-   uncompressed bytes actually written (0 in case of error).
-*/
-
-ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
-/*
-      Writes the given null-terminated string to the compressed file, excluding
-   the terminating null character.
-      gzputs returns the number of characters written, or -1 in case of error.
-*/
-
-ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
-/*
-      Reads bytes from the compressed file until len-1 characters are read, or
-   a newline character is read and transferred to buf, or an end-of-file
-   condition is encountered.  The string is then terminated with a null
-   character.
-      gzgets returns buf, or Z_NULL in case of error.
-*/
-
-ZEXTERN int ZEXPORT    gzputc OF((gzFile file, int c));
-/*
-      Writes c, converted to an unsigned char, into the compressed file.
-   gzputc returns the value that was written, or -1 in case of error.
-*/
-
-ZEXTERN int ZEXPORT    gzgetc OF((gzFile file));
-/*
-      Reads one byte from the compressed file. gzgetc returns this byte
-   or -1 in case of end of file or error.
-*/
-
-ZEXTERN int ZEXPORT    gzflush OF((gzFile file, int flush));
-/*
-     Flushes all pending output into the compressed file. The parameter
-   flush is as in the deflate() function. The return value is the zlib
-   error number (see function gzerror below). gzflush returns Z_OK if
-   the flush parameter is Z_FINISH and all output could be flushed.
-     gzflush should be called only when strictly necessary because it can
-   degrade compression.
-*/
-
-ZEXTERN z_off_t ZEXPORT    gzseek OF((gzFile file,
-				      z_off_t offset, int whence));
-/* 
-      Sets the starting position for the next gzread or gzwrite on the
-   given compressed file. The offset represents a number of bytes in the
-   uncompressed data stream. The whence parameter is defined as in lseek(2);
-   the value SEEK_END is not supported.
-     If the file is opened for reading, this function is emulated but can be
-   extremely slow. If the file is opened for writing, only forward seeks are
-   supported; gzseek then compresses a sequence of zeroes up to the new
-   starting position.
-
-      gzseek returns the resulting offset location as measured in bytes from
-   the beginning of the uncompressed stream, or -1 in case of error, in
-   particular if the file is opened for writing and the new starting position
-   would be before the current position.
-*/
-
-ZEXTERN int ZEXPORT    gzrewind OF((gzFile file));
-/*
-     Rewinds the given file. This function is supported only for reading.
-
-   gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
-*/
-
-ZEXTERN z_off_t ZEXPORT    gztell OF((gzFile file));
-/*
-     Returns the starting position for the next gzread or gzwrite on the
-   given compressed file. This position represents a number of bytes in the
-   uncompressed data stream.
-
-   gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
-*/
-
-ZEXTERN int ZEXPORT gzeof OF((gzFile file));
-/*
-     Returns 1 when EOF has previously been detected reading the given
-   input stream, otherwise zero.
-*/
-
-ZEXTERN int ZEXPORT    gzclose OF((gzFile file));
-/*
-     Flushes all pending output if necessary, closes the compressed file
-   and deallocates all the (de)compression state. The return value is the zlib
-   error number (see function gzerror below).
-*/
-
-ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
-/*
-     Returns the error message for the last error which occurred on the
-   given compressed file. errnum is set to zlib error number. If an
-   error occurred in the file system and not in the compression library,
-   errnum is set to Z_ERRNO and the application may consult errno
-   to get the exact error code.
-*/
-
-                        /* checksum functions */
-
-/*
-     These functions are not related to compression but are exported
-   anyway because they might be useful in applications using the
-   compression library.
-*/
-
-ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
-
-/*
-     Update a running Adler-32 checksum with the bytes buf[0..len-1] and
-   return the updated checksum. If buf is NULL, this function returns
-   the required initial value for the checksum.
-   An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
-   much faster. Usage example:
-
-     uLong adler = adler32(0L, Z_NULL, 0);
-
-     while (read_buffer(buffer, length) != EOF) {
-       adler = adler32(adler, buffer, length);
-     }
-     if (adler != original_adler) error();
-*/
-
-ZEXTERN uLong ZEXPORT crc32   OF((uLong crc, const Bytef *buf, uInt len));
-/*
-     Update a running crc with the bytes buf[0..len-1] and return the updated
-   crc. If buf is NULL, this function returns the required initial value
-   for the crc. Pre- and post-conditioning (one's complement) is performed
-   within this function so it shouldn't be done by the application.
-   Usage example:
-
-     uLong crc = crc32(0L, Z_NULL, 0);
-
-     while (read_buffer(buffer, length) != EOF) {
-       crc = crc32(crc, buffer, length);
-     }
-     if (crc != original_crc) error();
-*/
-
-
-                        /* various hacks, don't look :) */
-
-/* deflateInit and inflateInit are macros to allow checking the zlib version
- * and the compiler's view of z_stream:
- */
-ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level,
-                                     const char *version, int stream_size));
-ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm,
-                                     const char *version, int stream_size));
-ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int  level, int  method,
-                                      int windowBits, int memLevel,
-                                      int strategy, const char *version,
-                                      int stream_size));
-ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int  windowBits,
-                                      const char *version, int stream_size));
-#define deflateInit(strm, level) \
-        deflateInit_((strm), (level),       ZLIB_VERSION, sizeof(z_stream))
-#define inflateInit(strm) \
-        inflateInit_((strm),                ZLIB_VERSION, sizeof(z_stream))
-#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
-        deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
-                      (strategy),           ZLIB_VERSION, sizeof(z_stream))
-#define inflateInit2(strm, windowBits) \
-        inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
-
-
-#if !defined(_Z_UTIL_H) && !defined(NO_DUMMY_DECL)
-    struct internal_state {int dummy;}; /* hack for buggy compilers */
-#endif
-
-ZEXTERN const char   * ZEXPORT zError           OF((int err));
-ZEXTERN int            ZEXPORT inflateSyncPoint OF((z_streamp z));
-ZEXTERN const uLongf * ZEXPORT get_crc_table    OF((void));
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _ZLIB_H */
diff --git a/Lib/zlib/zutil.c b/Lib/zlib/zutil.c
deleted file mode 100644
index b3de4e883..000000000
--- a/Lib/zlib/zutil.c
+++ /dev/null
@@ -1,225 +0,0 @@
-/* zutil.c -- target dependent utility functions for the compression library
- * Copyright (C) 1995-1998 Jean-loup Gailly.
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* @(#) $Id$ */
-
-#include "zutil.h"
-
-struct internal_state      {int dummy;}; /* for buggy compilers */
-
-#ifndef STDC
-extern void exit OF((int));
-#endif
-
-const char *z_errmsg[10] = {
-"need dictionary",     /* Z_NEED_DICT       2  */
-"stream end",          /* Z_STREAM_END      1  */
-"",                    /* Z_OK              0  */
-"file error",          /* Z_ERRNO         (-1) */
-"stream error",        /* Z_STREAM_ERROR  (-2) */
-"data error",          /* Z_DATA_ERROR    (-3) */
-"insufficient memory", /* Z_MEM_ERROR     (-4) */
-"buffer error",        /* Z_BUF_ERROR     (-5) */
-"incompatible version",/* Z_VERSION_ERROR (-6) */
-""};
-
-
-const char * ZEXPORT zlibVersion()
-{
-    return ZLIB_VERSION;
-}
-
-#ifdef DEBUG
-
-#  ifndef verbose
-#    define verbose 0
-#  endif
-int z_verbose = verbose;
-
-void z_error (m)
-    char *m;
-{
-    fprintf(stderr, "%s\n", m);
-    exit(1);
-}
-#endif
-
-/* exported to allow conversion of error code to string for compress() and
- * uncompress()
- */
-const char * ZEXPORT zError(err)
-    int err;
-{
-    return ERR_MSG(err);
-}
-
-
-#ifndef HAVE_MEMCPY
-
-void zmemcpy(dest, source, len)
-    Bytef* dest;
-    const Bytef* source;
-    uInt  len;
-{
-    if (len == 0) return;
-    do {
-        *dest++ = *source++; /* ??? to be unrolled */
-    } while (--len != 0);
-}
-
-int zmemcmp(s1, s2, len)
-    const Bytef* s1;
-    const Bytef* s2;
-    uInt  len;
-{
-    uInt j;
-
-    for (j = 0; j < len; j++) {
-        if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1;
-    }
-    return 0;
-}
-
-void zmemzero(dest, len)
-    Bytef* dest;
-    uInt  len;
-{
-    if (len == 0) return;
-    do {
-        *dest++ = 0;  /* ??? to be unrolled */
-    } while (--len != 0);
-}
-#endif
-
-#ifdef __TURBOC__
-#if (defined( __BORLANDC__) || !defined(SMALL_MEDIUM)) && !defined(__32BIT__)
-/* Small and medium model in Turbo C are for now limited to near allocation
- * with reduced MAX_WBITS and MAX_MEM_LEVEL
- */
-#  define MY_ZCALLOC
-
-/* Turbo C malloc() does not allow dynamic allocation of 64K bytes
- * and farmalloc(64K) returns a pointer with an offset of 8, so we
- * must fix the pointer. Warning: the pointer must be put back to its
- * original form in order to free it, use zcfree().
- */
-
-#define MAX_PTR 10
-/* 10*64K = 640K */
-
-local int next_ptr = 0;
-
-typedef struct ptr_table_s {
-    voidpf org_ptr;
-    voidpf new_ptr;
-} ptr_table;
-
-local ptr_table table[MAX_PTR];
-/* This table is used to remember the original form of pointers
- * to large buffers (64K). Such pointers are normalized with a zero offset.
- * Since MSDOS is not a preemptive multitasking OS, this table is not
- * protected from concurrent access. This hack doesn't work anyway on
- * a protected system like OS/2. Use Microsoft C instead.
- */
-
-voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
-{
-    voidpf buf = opaque; /* just to make some compilers happy */
-    ulg bsize = (ulg)items*size;
-
-    /* If we allocate less than 65520 bytes, we assume that farmalloc
-     * will return a usable pointer which doesn't have to be normalized.
-     */
-    if (bsize < 65520L) {
-        buf = farmalloc(bsize);
-        if (*(ush*)&buf != 0) return buf;
-    } else {
-        buf = farmalloc(bsize + 16L);
-    }
-    if (buf == NULL || next_ptr >= MAX_PTR) return NULL;
-    table[next_ptr].org_ptr = buf;
-
-    /* Normalize the pointer to seg:0 */
-    *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4;
-    *(ush*)&buf = 0;
-    table[next_ptr++].new_ptr = buf;
-    return buf;
-}
-
-void  zcfree (voidpf opaque, voidpf ptr)
-{
-    int n;
-    if (*(ush*)&ptr != 0) { /* object < 64K */
-        farfree(ptr);
-        return;
-    }
-    /* Find the original pointer */
-    for (n = 0; n < next_ptr; n++) {
-        if (ptr != table[n].new_ptr) continue;
-
-        farfree(table[n].org_ptr);
-        while (++n < next_ptr) {
-            table[n-1] = table[n];
-        }
-        next_ptr--;
-        return;
-    }
-    ptr = opaque; /* just to make some compilers happy */
-    Assert(0, "zcfree: ptr not found");
-}
-#endif
-#endif /* __TURBOC__ */
-
-
-#if defined(M_I86) && !defined(__32BIT__)
-/* Microsoft C in 16-bit mode */
-
-#  define MY_ZCALLOC
-
-#if (!defined(_MSC_VER) || (_MSC_VER <= 600))
-#  define _halloc  halloc
-#  define _hfree   hfree
-#endif
-
-voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
-{
-    if (opaque) opaque = 0; /* to make compiler happy */
-    return _halloc((long)items, size);
-}
-
-void  zcfree (voidpf opaque, voidpf ptr)
-{
-    if (opaque) opaque = 0; /* to make compiler happy */
-    _hfree(ptr);
-}
-
-#endif /* MSC */
-
-
-#ifndef MY_ZCALLOC /* Any system without a special alloc function */
-
-#ifndef STDC
-extern voidp  calloc OF((uInt items, uInt size));
-extern void   free   OF((voidpf ptr));
-#endif
-
-voidpf zcalloc (opaque, items, size)
-    voidpf opaque;
-    unsigned items;
-    unsigned size;
-{
-    if (opaque) items += size - size; /* make compiler happy */
-    return (voidpf)calloc(items, size);
-}
-
-void  zcfree (opaque, ptr)
-    voidpf opaque;
-    voidpf ptr;
-{
-    free(ptr);
-    if (opaque) return; /* make compiler happy */
-}
-
-#endif /* MY_ZCALLOC */
diff --git a/Lib/zlib/zutil.h b/Lib/zlib/zutil.h
deleted file mode 100644
index 6f2cb97ca..000000000
--- a/Lib/zlib/zutil.h
+++ /dev/null
@@ -1,220 +0,0 @@
-/* zutil.h -- internal interface and configuration of the compression library
- * Copyright (C) 1995-1998 Jean-loup Gailly.
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-/* @(#) $Id$ */
-
-#ifndef _Z_UTIL_H
-#define _Z_UTIL_H
-
-#include "zlib.h"
-
-#ifdef STDC
-#  include 
-#  include 
-#  include 
-#endif
-#ifdef NO_ERRNO_H
-    extern int errno;
-#else
-#   include 
-#endif
-
-#ifndef local
-#  define local static
-#endif
-/* compile with -Dlocal if your debugger can't find static symbols */
-
-typedef unsigned char  uch;
-typedef uch FAR uchf;
-typedef unsigned short ush;
-typedef ush FAR ushf;
-typedef unsigned long  ulg;
-
-extern const char *z_errmsg[10]; /* indexed by 2-zlib_error */
-/* (size given to avoid silly warnings with Visual C++) */
-
-#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
-
-#define ERR_RETURN(strm,err) \
-  return (strm->msg = (char*)ERR_MSG(err), (err))
-/* To be used only when the state is known to be valid */
-
-        /* common constants */
-
-#ifndef DEF_WBITS
-#  define DEF_WBITS MAX_WBITS
-#endif
-/* default windowBits for decompression. MAX_WBITS is for compression only */
-
-#if MAX_MEM_LEVEL >= 8
-#  define DEF_MEM_LEVEL 8
-#else
-#  define DEF_MEM_LEVEL  MAX_MEM_LEVEL
-#endif
-/* default memLevel */
-
-#define STORED_BLOCK 0
-#define STATIC_TREES 1
-#define DYN_TREES    2
-/* The three kinds of block type */
-
-#define MIN_MATCH  3
-#define MAX_MATCH  258
-/* The minimum and maximum match lengths */
-
-#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
-
-        /* target dependencies */
-
-#ifdef MSDOS
-#  define OS_CODE  0x00
-#  if defined(__TURBOC__) || defined(__BORLANDC__)
-#    if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
-       /* Allow compilation with ANSI keywords only enabled */
-       void _Cdecl farfree( void *block );
-       void *_Cdecl farmalloc( unsigned long nbytes );
-#    else
-#     include 
-#    endif
-#  else /* MSC or DJGPP */
-#    include 
-#  endif
-#endif
-
-#ifdef OS2
-#  define OS_CODE  0x06
-#endif
-
-#ifdef WIN32 /* Window 95 & Windows NT */
-#  define OS_CODE  0x0b
-#endif
-
-#if defined(VAXC) || defined(VMS)
-#  define OS_CODE  0x02
-#  define F_OPEN(name, mode) \
-     fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512")
-#endif
-
-#ifdef AMIGA
-#  define OS_CODE  0x01
-#endif
-
-#if defined(ATARI) || defined(atarist)
-#  define OS_CODE  0x05
-#endif
-
-#if defined(MACOS) || defined(TARGET_OS_MAC)
-#  define OS_CODE  0x07
-#  if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
-#    include  /* for fdopen */
-#  else
-#    ifndef fdopen
-#      define fdopen(fd,mode) NULL /* No fdopen() */
-#    endif
-#  endif
-#endif
-
-#ifdef __50SERIES /* Prime/PRIMOS */
-#  define OS_CODE  0x0F
-#endif
-
-#ifdef TOPS20
-#  define OS_CODE  0x0a
-#endif
-
-#if defined(_BEOS_) || defined(RISCOS)
-#  define fdopen(fd,mode) NULL /* No fdopen() */
-#endif
-
-#if (defined(_MSC_VER) && (_MSC_VER > 600))
-#  define fdopen(fd,type)  _fdopen(fd,type)
-#endif
-
-
-        /* Common defaults */
-
-#ifndef OS_CODE
-#  define OS_CODE  0x03  /* assume Unix */
-#endif
-
-#ifndef F_OPEN
-#  define F_OPEN(name, mode) fopen((name), (mode))
-#endif
-
-         /* functions */
-
-#ifdef HAVE_STRERROR
-   extern char *strerror OF((int));
-#  define zstrerror(errnum) strerror(errnum)
-#else
-#  define zstrerror(errnum) ""
-#endif
-
-#if defined(pyr)
-#  define NO_MEMCPY
-#endif
-#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__)
- /* Use our own functions for small and medium model with MSC <= 5.0.
-  * You may have to use the same strategy for Borland C (untested).
-  * The __SC__ check is for Symantec.
-  */
-#  define NO_MEMCPY
-#endif
-#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY)
-#  define HAVE_MEMCPY
-#endif
-#ifdef HAVE_MEMCPY
-#  ifdef SMALL_MEDIUM /* MSDOS small or medium model */
-#    define zmemcpy _fmemcpy
-#    define zmemcmp _fmemcmp
-#    define zmemzero(dest, len) _fmemset(dest, 0, len)
-#  else
-#    define zmemcpy memcpy
-#    define zmemcmp memcmp
-#    define zmemzero(dest, len) memset(dest, 0, len)
-#  endif
-#else
-   extern void zmemcpy  OF((Bytef* dest, const Bytef* source, uInt len));
-   extern int  zmemcmp  OF((const Bytef* s1, const Bytef* s2, uInt len));
-   extern void zmemzero OF((Bytef* dest, uInt len));
-#endif
-
-/* Diagnostic functions */
-#ifdef DEBUG
-#  include 
-   extern int z_verbose;
-   extern void z_error    OF((char *m));
-#  define Assert(cond,msg) {if(!(cond)) z_error(msg);}
-#  define Trace(x) {if (z_verbose>=0) fprintf x ;}
-#  define Tracev(x) {if (z_verbose>0) fprintf x ;}
-#  define Tracevv(x) {if (z_verbose>1) fprintf x ;}
-#  define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;}
-#  define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;}
-#else
-#  define Assert(cond,msg)
-#  define Trace(x)
-#  define Tracev(x)
-#  define Tracevv(x)
-#  define Tracec(c,x)
-#  define Tracecv(c,x)
-#endif
-
-
-typedef uLong (ZEXPORT *check_func) OF((uLong check, const Bytef *buf,
-				       uInt len));
-voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size));
-void   zcfree  OF((voidpf opaque, voidpf ptr));
-
-#define ZALLOC(strm, items, size) \
-           (*((strm)->zalloc))((strm)->opaque, (items), (size))
-#define ZFREE(strm, addr)  (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
-#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
-
-#endif /* _Z_UTIL_H */
diff --git a/Makefile.am b/Makefile.am
index c78d544c5..a65956d77 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,8 +1,8 @@
 SUBDIRS = Include Lib Simulator Tools Tests
 
 EXTRA_DIST = README.Unix README.Linux README.MacOS README.Win32 \
-	README.autoconf README.running Thanks VERSION acsite.m4 acconfig.h \
-	irix-hack.pl
+	README.autoconf README.gpc README.running Thanks VERSION \
+	acsite.m4 acconfig.h irix-hack.pl
 
 dist-hook:
 	tar cf - Hints | (cd $(distdir); tar xvf -)
diff --git a/README.src b/README.src
new file mode 100644
index 000000000..739f94697
--- /dev/null
+++ b/README.src
@@ -0,0 +1,58 @@
+majordomo writes:
+Subdirectories
+==============
+Main/
+-------
+"main()" and GLUT dependent mouse/keyboard/graphics code.
+
+
+Aircraft/
+---------
+Structure and code to tie together all the pieces of an aircraft such
+as flight model, engine model, panel, controls, etc.
+
+
+Controls/
+---------
+Provide a standardized interface to all aircraft controls.
+
+
+Flight/
+-------
+Strucures and code to implement various flight models.  Provides a 
+standardized interface to all interesting flight model variabls.
+
+
+Math/
+-----
+Contains miscellaneous matrix/vector routines.
+
+
+Scenery/
+--------
+Scenery parsing/generating code.
+
+
+Sound/
+------
+Sound management code
+
+
+Timer/
+------
+Code to handle time and timing of events.
+
+
+Utils/
+------
+Miscellaneous utility routines such as a general random number generator
+
+
+Weather/
+--------
+Weather management and modeling code.
+
+
+Win32/
+------
+Win32 support stuff
diff --git a/Simulator/Aircraft/aircraft.cxx b/Simulator/Aircraft/aircraft.cxx
index ac4b067b0..b3b78b83b 100644
--- a/Simulator/Aircraft/aircraft.cxx
+++ b/Simulator/Aircraft/aircraft.cxx
@@ -68,6 +68,9 @@ void fgAircraftOutputCurrent(fgAIRCRAFT *a) {
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:49  curt
+// Initial revision
+//
 // Revision 1.7  1999/02/05 21:28:09  curt
 // Modifications to incorporate Jon S. Berndts flight model code.
 //
diff --git a/Simulator/Aircraft/aircraft.hxx b/Simulator/Aircraft/aircraft.hxx
index 02e7470ee..b97d1d034 100644
--- a/Simulator/Aircraft/aircraft.hxx
+++ b/Simulator/Aircraft/aircraft.hxx
@@ -61,6 +61,9 @@ void fgAircraftOutputCurrent(fgAIRCRAFT *a);
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:49  curt
+// Initial revision
+//
 // Revision 1.6  1999/02/05 21:28:10  curt
 // Modifications to incorporate Jon S. Berndts flight model code.
 //
diff --git a/Simulator/Airports/genapt.cxx b/Simulator/Airports/genapt.cxx
index b84009974..7292cc4ae 100644
--- a/Simulator/Airports/genapt.cxx
+++ b/Simulator/Airports/genapt.cxx
@@ -294,6 +294,9 @@ fgAptGenerate(const string& path, fgTILE *tile)
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:47  curt
+// Initial revision
+//
 // Revision 1.14  1999/03/02 01:02:31  curt
 // Tweaks for building with native SGI compilers.
 //
diff --git a/Simulator/Airports/genapt.hxx b/Simulator/Airports/genapt.hxx
index fa5c0dccf..ac3a8df6e 100644
--- a/Simulator/Airports/genapt.hxx
+++ b/Simulator/Airports/genapt.hxx
@@ -65,6 +65,9 @@ fgAptGenerate(const string& path, fgTILE *tile);
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:47  curt
+// Initial revision
+//
 // Revision 1.3  1999/03/02 01:02:32  curt
 // Tweaks for building with native SGI compilers.
 //
diff --git a/Simulator/Airports/old_draw_runways.c b/Simulator/Airports/old_draw_runways.c
new file mode 100644
index 000000000..efbb010c9
--- /dev/null
+++ b/Simulator/Airports/old_draw_runways.c
@@ -0,0 +1,83 @@
+// Scenery management routines
+
+/* static void fgSceneryInit_OLD() { */
+    /* make scenery */
+/*     scenery = fgSceneryCompile_OLD();
+    runway = fgRunwayHack_OLD(0.69, 53.07);
+} */
+
+
+/* create the scenery */
+/* GLint fgSceneryCompile_OLD() {
+    GLint scenery;
+
+    scenery = mesh2GL(mesh_ptr_OLD);
+
+    return(scenery);
+}
+*/
+
+/* hack in a runway */
+/* GLint fgRunwayHack_OLD(double width, double length) {
+    static GLfloat concrete[4] = { 0.5, 0.5, 0.5, 1.0 };
+    static GLfloat line[4]     = { 0.9, 0.9, 0.9, 1.0 };
+    int i;
+    int num_lines = 16;
+    float line_len, line_width_2, cur_pos;
+
+    runway = xglGenLists(1);
+    xglNewList(runway, GL_COMPILE);
+    */
+    /* draw concrete */
+/*    xglBegin(GL_POLYGON);
+    xglMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, concrete );
+    xglNormal3f(0.0, 0.0, 1.0);
+
+    xglVertex3d( 0.0,   -width/2.0, 0.0);
+    xglVertex3d( 0.0,    width/2.0, 0.0);
+    xglVertex3d(length,  width/2.0, 0.0);
+    xglVertex3d(length, -width/2.0, 0.0);
+    xglEnd();
+    */
+    /* draw center line */
+/*    xglMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, line );
+    line_len = length / ( 2 * num_lines + 1);
+    printf("line_len = %.3f\n", line_len);
+    line_width_2 = 0.02;
+    cur_pos = line_len;
+    for ( i = 0; i < num_lines; i++ ) {
+	xglBegin(GL_POLYGON);
+	xglVertex3d( cur_pos, -line_width_2, 0.005);
+	xglVertex3d( cur_pos,  line_width_2, 0.005);
+	cur_pos += line_len;
+	xglVertex3d( cur_pos,  line_width_2, 0.005);
+	xglVertex3d( cur_pos, -line_width_2, 0.005);
+	cur_pos += line_len;
+	xglEnd();
+    }
+
+    xglEndList();
+
+    return(runway);
+}
+*/
+
+/* draw the scenery */
+/*static void fgSceneryDraw_OLD() {
+    static float z = 32.35;
+
+    xglPushMatrix();
+
+    xglCallList(scenery);
+
+    printf("*** Drawing runway at %.2f\n", z);
+
+    xglTranslatef( -398391.28, 120070.41, 32.35);
+    xglRotatef(170.0, 0.0, 0.0, 1.0);
+    xglCallList(runway);
+
+    xglPopMatrix();
+}
+*/
+
+
diff --git a/Simulator/Airports/simple.cxx b/Simulator/Airports/simple.cxx
index eddc1c4ec..3dfdfa7bc 100644
--- a/Simulator/Airports/simple.cxx
+++ b/Simulator/Airports/simple.cxx
@@ -110,6 +110,9 @@ fgAIRPORTS::~fgAIRPORTS( void ) {
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:48  curt
+// Initial revision
+//
 // Revision 1.10  1999/02/26 22:08:35  curt
 // Added initial support for native SGI compilers.
 //
diff --git a/Simulator/Airports/simple.hxx b/Simulator/Airports/simple.hxx
index 38e4b8b65..8240f6d3c 100644
--- a/Simulator/Airports/simple.hxx
+++ b/Simulator/Airports/simple.hxx
@@ -111,6 +111,9 @@ public:
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:47  curt
+// Initial revision
+//
 // Revision 1.8  1999/03/15 17:58:57  curt
 // MSVC++ portability tweaks contributed by Bernie Bright.
 //   Added using std::istream declaration.
diff --git a/Simulator/Airports/testair.cxx b/Simulator/Airports/testair.cxx
new file mode 100644
index 000000000..97df920ee
--- /dev/null
+++ b/Simulator/Airports/testair.cxx
@@ -0,0 +1,21 @@
+#include 
+#include 
+#include "airports.hxx"
+
+fgGENERAL general;
+
+main() {
+    fgAIRPORTS a;
+    fgAIRPORT air;
+
+    general.root_dir = getenv("FG_ROOT");
+
+    fgInitDebug();
+
+    a.load("Airports");
+
+    air = a.search("P13");
+
+    printf("%s %lf %lf %lf\n", air.id, 
+	   air.longitude, air.latitude, air.elevation);
+}
diff --git a/Simulator/Astro/sky.cxx b/Simulator/Astro/sky.cxx
index d5e7730c7..f5305faf9 100644
--- a/Simulator/Astro/sky.cxx
+++ b/Simulator/Astro/sky.cxx
@@ -362,6 +362,9 @@ void fgSkyRender( void ) {
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:48  curt
+// Initial revision
+//
 // Revision 1.21  1999/02/05 21:28:50  curt
 // Modifications to incorporate Jon S. Berndts flight model code.
 //
diff --git a/Simulator/Astro/sky.hxx b/Simulator/Astro/sky.hxx
index d39528211..088864906 100644
--- a/Simulator/Astro/sky.hxx
+++ b/Simulator/Astro/sky.hxx
@@ -45,6 +45,9 @@ void fgSkyRender( void );
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:48  curt
+// Initial revision
+//
 // Revision 1.2  1998/10/16 23:27:19  curt
 // C++-ifying.
 //
diff --git a/Simulator/Astro/stars.cxx b/Simulator/Astro/stars.cxx
index 8f7bdb23a..a03f476b4 100644
--- a/Simulator/Astro/stars.cxx
+++ b/Simulator/Astro/stars.cxx
@@ -264,6 +264,9 @@ void fgStarsRender( void ) {
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:48  curt
+// Initial revision
+//
 // Revision 1.27  1999/02/05 21:28:52  curt
 // Modifications to incorporate Jon S. Berndts flight model code.
 //
diff --git a/Simulator/Astro/stars.hxx b/Simulator/Astro/stars.hxx
index 212718d7e..5e008a583 100644
--- a/Simulator/Astro/stars.hxx
+++ b/Simulator/Astro/stars.hxx
@@ -48,6 +48,9 @@ extern fgTIME cur_time_params;
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:48  curt
+// Initial revision
+//
 // Revision 1.8  1999/01/19 20:57:00  curt
 // MacOS portability changes contributed by "Robert Puyol" 
 //
diff --git a/Simulator/Autopilot/autopilot.cxx b/Simulator/Autopilot/autopilot.cxx
index 76c8d3737..8f6437dbe 100644
--- a/Simulator/Autopilot/autopilot.cxx
+++ b/Simulator/Autopilot/autopilot.cxx
@@ -581,6 +581,9 @@ double NormalizeDegrees(double Input)
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:49  curt
+// Initial revision
+//
 // Revision 1.15  1999/02/12 23:22:35  curt
 // Allow auto-throttle adjustment while active.
 //
diff --git a/Simulator/Autopilot/autopilot.hxx b/Simulator/Autopilot/autopilot.hxx
index 18235c735..4169a6c83 100644
--- a/Simulator/Autopilot/autopilot.hxx
+++ b/Simulator/Autopilot/autopilot.hxx
@@ -83,6 +83,9 @@ void fgAPAutoThrottleAdjust( double inc );
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:49  curt
+// Initial revision
+//
 // Revision 1.9  1999/02/12 23:22:36  curt
 // Allow auto-throttle adjustment while active.
 //
diff --git a/Simulator/CVSROOT/checkoutlist b/Simulator/CVSROOT/checkoutlist
deleted file mode 100644
index b04b3501f..000000000
--- a/Simulator/CVSROOT/checkoutlist
+++ /dev/null
@@ -1,13 +0,0 @@
-# The "checkoutlist" file is used to support additional version controlled
-# administrative files in $CVSROOT/CVSROOT, such as template files.
-#
-# The first entry on a line is a filename which will be checked out from
-# the corresponding RCS file in the $CVSROOT/CVSROOT directory.
-# The remainder of the line is an error message to use if the file cannot
-# be checked out.
-#
-# File format:
-#
-#	[]
-#
-# comment lines begin with '#'
diff --git a/Simulator/CVSROOT/commitinfo b/Simulator/CVSROOT/commitinfo
deleted file mode 100644
index b19e7b7a6..000000000
--- a/Simulator/CVSROOT/commitinfo
+++ /dev/null
@@ -1,15 +0,0 @@
-# The "commitinfo" file is used to control pre-commit checks.
-# The filter on the right is invoked with the repository and a list 
-# of files to check.  A non-zero exit of the filter program will 
-# cause the commit to be aborted.
-#
-# The first entry on a line is a regular expression which is tested
-# against the directory that the change is being committed to, relative
-# to the $CVSROOT.  For the first match that is found, then the remainder
-# of the line is the name of the filter to run.
-#
-# If the repository name does not match any of the regular expressions in this
-# file, the "DEFAULT" line is used, if it is specified.
-#
-# If the name "ALL" appears as a regular expression it is always used
-# in addition to the first matching regex or "DEFAULT".
diff --git a/Simulator/CVSROOT/cvswrappers b/Simulator/CVSROOT/cvswrappers
deleted file mode 100644
index 5047bf1c5..000000000
--- a/Simulator/CVSROOT/cvswrappers
+++ /dev/null
@@ -1,22 +0,0 @@
-# This file describes wrappers and other binary files to CVS.
-#
-# Wrappers are the concept where directories of files are to be
-# treated as a single file.  The intended use is to wrap up a wrapper
-# into a single tar such that the tar archive can be treated as a
-# single binary file in CVS.
-#
-# To solve the problem effectively, it was also necessary to be able to
-# prevent rcsmerge from merging these files.
-#
-# Format of wrapper file ($CVSROOT/CVSROOT/cvswrappers or .cvswrappers)
-#
-#  wildcard	[option value][option value]...
-#
-#  where option is one of
-#  -f		from cvs filter		value: path to filter
-#  -t		to cvs filter		value: path to filter
-#  -m		update methodology	value: MERGE or COPY
-#
-#  and value is a single-quote delimited value.
-#
-# For example:
diff --git a/Simulator/CVSROOT/editinfo b/Simulator/CVSROOT/editinfo
deleted file mode 100644
index d78886c15..000000000
--- a/Simulator/CVSROOT/editinfo
+++ /dev/null
@@ -1,21 +0,0 @@
-# The "editinfo" file is used to allow verification of logging
-# information.  It works best when a template (as specified in the
-# rcsinfo file) is provided for the logging procedure.  Given a
-# template with locations for, a bug-id number, a list of people who
-# reviewed the code before it can be checked in, and an external
-# process to catalog the differences that were code reviewed, the
-# following test can be applied to the code:
-#
-#   Making sure that the entered bug-id number is correct.
-#   Validating that the code that was reviewed is indeed the code being
-#       checked in (using the bug-id number or a seperate review
-#       number to identify this particular code set.).
-#
-# If any of the above test failed, then the commit would be aborted.
-#
-# Actions such as mailing a copy of the report to each reviewer are
-# better handled by an entry in the loginfo file.
-#
-# One thing that should be noted is the the ALL keyword is not
-# supported.  There can be only one entry that matches a given
-# repository.
diff --git a/Simulator/CVSROOT/loginfo b/Simulator/CVSROOT/loginfo
deleted file mode 100644
index 226e93771..000000000
--- a/Simulator/CVSROOT/loginfo
+++ /dev/null
@@ -1,19 +0,0 @@
-# The "loginfo" file is used to control where "cvs commit" log information is
-# sent.  The first entry on a line is a regular expression which is tested
-# against the directory that the change is being made to, relative to the
-# $CVSROOT.  For the first match that is found, the remainder of the line is a
-# filter program that should expect log information on its standard input
-#
-# If the repository name does not match any of the regular expressions in the
-# first field of this file, the "DEFAULT" line is used, if it is specified.
-#
-# If the name "ALL" appears as a regular expression it is always used
-# in addition to the first matching regex or "DEFAULT".
-#
-# The filter program may use one and only one "%s" modifier (ala printf).  If
-# such a "%s" is specified in the filter program, a brief title is included
-# (as one argument, enclosed in single quotes) showing the relative directory
-# name and listing the modified file names.
-#
-# For example:
-#DEFAULT		(echo ""; who am i; echo %s; date; cat) >> $CVSROOT/CVSROOT/commitlog
diff --git a/Simulator/CVSROOT/modules b/Simulator/CVSROOT/modules
deleted file mode 100644
index cb9e9efc9..000000000
--- a/Simulator/CVSROOT/modules
+++ /dev/null
@@ -1,26 +0,0 @@
-# Three different line formats are valid:
-#	key	-a    aliases...
-#	key [options] directory
-#	key [options] directory files...
-#
-# Where "options" are composed of:
-#	-i prog		Run "prog" on "cvs commit" from top-level of module.
-#	-o prog		Run "prog" on "cvs checkout" of module.
-#	-e prog		Run "prog" on "cvs export" of module.
-#	-t prog		Run "prog" on "cvs rtag" of module.
-#	-u prog		Run "prog" on "cvs update" of module.
-#	-d dir		Place module in directory "dir" instead of module name.
-#	-l		Top-level directory only -- do not recurse.
-#
-# NOTE:  If you change any of the "Run" options above, you'll have to
-# release and re-checkout any working directories of these modules.
-#
-# And "directory" is a path to a directory relative to $CVSROOT.
-#
-# The "-a" option specifies an alias.  An alias is interpreted as if
-# everything on the right of the "-a" had been typed on the command line.
-#
-# You can encode a module within a module by using the special '&'
-# character to interpose another module into the current module.  This
-# can be useful for creating a module that consists of many directories
-# spread out over the entire source repository.
diff --git a/Simulator/CVSROOT/notify b/Simulator/CVSROOT/notify
deleted file mode 100644
index 34f0bc288..000000000
--- a/Simulator/CVSROOT/notify
+++ /dev/null
@@ -1,12 +0,0 @@
-# The "notify" file controls where notifications from watches set by
-# "cvs watch add" or "cvs edit" are sent.  The first entry on a line is
-# a regular expression which is tested against the directory that the
-# change is being made to, relative to the $CVSROOT.  If it matches,
-# then the remainder of the line is a filter program that should contain
-# one occurrence of %s for the user to notify, and information on its
-# standard input.
-#
-# "ALL" or "DEFAULT" can be used in place of the regular expression.
-#
-# For example:
-#ALL mail %s -s "CVS notification"
diff --git a/Simulator/CVSROOT/rcsinfo b/Simulator/CVSROOT/rcsinfo
deleted file mode 100644
index 49e59f4d0..000000000
--- a/Simulator/CVSROOT/rcsinfo
+++ /dev/null
@@ -1,13 +0,0 @@
-# The "rcsinfo" file is used to control templates with which the editor
-# is invoked on commit and import.
-#
-# The first entry on a line is a regular expression which is tested
-# against the directory that the change is being made to, relative to the
-# $CVSROOT.  For the first match that is found, then the remainder of the
-# line is the name of the file that contains the template.
-#
-# If the repository name does not match any of the regular expressions in this
-# file, the "DEFAULT" line is used, if it is specified.
-#
-# If the name "ALL" appears as a regular expression it is always used
-# in addition to the first matching regex or "DEFAULT".
diff --git a/Simulator/CVSROOT/taginfo b/Simulator/CVSROOT/taginfo
deleted file mode 100644
index 274a46dd5..000000000
--- a/Simulator/CVSROOT/taginfo
+++ /dev/null
@@ -1,20 +0,0 @@
-# The "taginfo" file is used to control pre-tag checks.
-# The filter on the right is invoked with the following arguments:
-#
-# $1 -- tagname
-# $2 -- operation "add" for tag, "mov" for tag -F, and "del" for tag -d
-# $3 -- repository
-# $4->  file revision [file revision ...]
-#
-# A non-zero exit of the filter program will cause the tag to be aborted.
-#
-# The first entry on a line is a regular expression which is tested
-# against the directory that the change is being committed to, relative
-# to the $CVSROOT.  For the first match that is found, then the remainder
-# of the line is the name of the filter to run.
-#
-# If the repository name does not match any of the regular expressions in this
-# file, the "DEFAULT" line is used, if it is specified.
-#
-# If the name "ALL" appears as a regular expression it is always used
-# in addition to the first matching regex or "DEFAULT".
diff --git a/Simulator/Cockpit/cockpit.cxx b/Simulator/Cockpit/cockpit.cxx
index 2b451c311..dc5daff9b 100644
--- a/Simulator/Cockpit/cockpit.cxx
+++ b/Simulator/Cockpit/cockpit.cxx
@@ -261,6 +261,9 @@ void fgCockpitUpdate( void ) {
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:48  curt
+// Initial revision
+//
 // Revision 1.31  1999/03/08 21:56:08  curt
 // Added panel changes sent in by Friedemann.
 //
diff --git a/Simulator/Cockpit/cockpit.hxx b/Simulator/Cockpit/cockpit.hxx
index 5f6ac4b8b..55918cdb4 100644
--- a/Simulator/Cockpit/cockpit.hxx
+++ b/Simulator/Cockpit/cockpit.hxx
@@ -60,10 +60,13 @@ void fgCockpitUpdate( void );
 
 
 /* $Log$
-/* Revision 1.4  1998/07/13 21:00:46  curt
-/* Integrated Charlies latest HUD updates.
-/* Wrote access functions for current fgOPTIONS.
+/* Revision 1.1  1999/04/05 21:32:48  curt
+/* Initial revision
 /*
+ * Revision 1.4  1998/07/13 21:00:46  curt
+ * Integrated Charlies latest HUD updates.
+ * Wrote access functions for current fgOPTIONS.
+ *
  * Revision 1.3  1998/06/27 16:47:54  curt
  * Incorporated Friedemann Reinhard's 
  * first pass at an isntrument panel.
diff --git a/Simulator/Cockpit/hud.cxx b/Simulator/Cockpit/hud.cxx
index eb59d8c24..0f30131ac 100644
--- a/Simulator/Cockpit/hud.cxx
+++ b/Simulator/Cockpit/hud.cxx
@@ -835,6 +835,9 @@ void fgUpdateHUD( void ) {
 }
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:48  curt
+// Initial revision
+//
 // Revision 1.32  1999/03/02 01:02:37  curt
 // Tweaks for building with native SGI compilers.
 //
diff --git a/Simulator/Cockpit/hud.hxx b/Simulator/Cockpit/hud.hxx
index dfee1928d..2783462ad 100644
--- a/Simulator/Cockpit/hud.hxx
+++ b/Simulator/Cockpit/hud.hxx
@@ -525,6 +525,9 @@ void fgHUDSetTimeMode( Hptr hud, int time_of_day );
 #endif // _HUD_H
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:48  curt
+// Initial revision
+//
 // Revision 1.19  1999/03/02 01:02:38  curt
 // Tweaks for building with native SGI compilers.
 //
diff --git a/Simulator/Cockpit/panel.cxx b/Simulator/Cockpit/panel.cxx
index f70639fc0..2f478b831 100644
--- a/Simulator/Cockpit/panel.cxx
+++ b/Simulator/Cockpit/panel.cxx
@@ -1059,6 +1059,9 @@ xglEnable(GL_TEXTURE_2D);
      }
      
 // $Log$
+// Revision 1.1  1999/04/05 21:32:48  curt
+// Initial revision
+//
 // Revision 1.18  1999/03/09 20:58:17  curt
 // Tweaks for compiling under native Irix compilers.
 //
diff --git a/Simulator/Cockpit/panel.hxx b/Simulator/Cockpit/panel.hxx
index 1809e7fbc..d82385ff3 100644
--- a/Simulator/Cockpit/panel.hxx
+++ b/Simulator/Cockpit/panel.hxx
@@ -254,6 +254,9 @@ void PrintMatrix( void);
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:48  curt
+// Initial revision
+//
 // Revision 1.9  1999/03/09 20:58:18  curt
 // Tweaks for compiling under native Irix compilers.
 //
diff --git a/Simulator/Cockpit/proposed-navaids.hpp b/Simulator/Cockpit/proposed-navaids.hpp
new file mode 100644
index 000000000..2b86abd84
--- /dev/null
+++ b/Simulator/Cockpit/proposed-navaids.hpp
@@ -0,0 +1,107 @@
+/**************************************************************************
+ * navaids.hpp -- navigation defines and prototypes
+ *
+ * Written by Charles Hotchkiss, started March 1998.
+ *
+ * Copyright (C) 1998  Charles Hotchkiss chotchkiss@namg.us.anritsu.com
+ *
+ * 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.
+ *
+ * $Id$
+ * (Log is kept at end of this file)
+ **************************************************************************/
+
+
+// Class nav_aid
+//
+//  Includes NDB and IMO Markers, base for all other navigational aids.
+//  The destructor is virtual to permit use of nav_aid pointers to derived
+//  classes, but is instantiable none the less.
+//  Assumes global pointer to current aircraft.
+
+class nav_aid
+  private:
+    LRECT  here_at;   // Codes left = Long,
+                      //        top = Lat,
+                      //      right = Alt,
+                      //     bottom = Range
+    UINT   frequency; // special coding
+    UINT   range;
+    char  *ID;
+    char  *Name;
+
+  public:
+    nav_aid( LRECT loc,
+             UNIT freq, UINT range,
+             const char *eye_dee, const char *MyName );
+
+    virtual ~nav_aid();
+    operator ==
+
+    void update_status( void );  // Called by main loop?
+
+    bool        in_range   ( LRECT loc );
+    const char *pID        ( void );
+    const char *pName      ( void );
+    Cartestian  Location   ( void );
+};
+
+// Class ATIS_stn
+//
+
+class ATIS_stn :: public nav_aid {
+  private:
+    int   runways;
+    int  *pref_rnwys; // prefered runway list;
+    char *format;
+
+  public:
+    bool set_message( const char *pmsg ); // MSFS coded message
+    ~ATIS_stn();
+    ATIS_stn( LRECT here,
+              UINT  radius,
+              char *eye_dee,
+              char *itsname,
+              int  *runways,
+              char *defaultmsg);
+};
+
+// Class DirBeacon
+//
+// Includes VOR Stations. Base for Omni?
+
+class DirBeacon :: public nav_aid{
+  private:
+    UINT        radial;
+
+  public:
+    int         phase_angle( void );
+    int         deflection ( void );
+    double      ground_rate( void );
+};
+
+// Class ils_station
+//
+// Includes ILS
+
+class ils_station :: public DirBeacon{
+  private:
+    long slope_freq;
+    UINT glide_angle;
+    UINT approach_angle;
+
+  public:
+    ULONG deflection( void );
+};
diff --git a/Simulator/Controls/controls.cxx b/Simulator/Controls/controls.cxx
index 62e4cc8ed..4763bd488 100644
--- a/Simulator/Controls/controls.cxx
+++ b/Simulator/Controls/controls.cxx
@@ -51,6 +51,9 @@ FGControls::~FGControls() {
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:49  curt
+// Initial revision
+//
 // Revision 1.3  1998/12/05 16:13:12  curt
 // Renamed class fgCONTROLS to class FGControls.
 //
diff --git a/Simulator/Controls/controls.hxx b/Simulator/Controls/controls.hxx
index 286cc86e8..99a21be27 100644
--- a/Simulator/Controls/controls.hxx
+++ b/Simulator/Controls/controls.hxx
@@ -182,6 +182,9 @@ extern FGControls controls;
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:49  curt
+// Initial revision
+//
 // Revision 1.4  1999/01/27 04:48:13  curt
 // C++ style refinements by Bernie Bright.
 //
diff --git a/Simulator/Simulator/Done b/Simulator/Done
similarity index 100%
rename from Simulator/Simulator/Done
rename to Simulator/Done
diff --git a/Simulator/External/Makefile.am b/Simulator/FDM/External/Makefile.am
similarity index 100%
rename from Simulator/External/Makefile.am
rename to Simulator/FDM/External/Makefile.am
diff --git a/Simulator/External/external.cxx b/Simulator/FDM/External/external.cxx
similarity index 96%
rename from Simulator/External/external.cxx
rename to Simulator/FDM/External/external.cxx
index 2325f1052..7950245e6 100644
--- a/Simulator/External/external.cxx
+++ b/Simulator/FDM/External/external.cxx
@@ -42,6 +42,9 @@ void fgExternalUpdate( FGInterface& f, int multiloop ) {
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:46  curt
+// Initial revision
+//
 // Revision 1.5  1999/02/05 21:29:03  curt
 // Modifications to incorporate Jon S. Berndts flight model code.
 //
diff --git a/Simulator/External/external.hxx b/Simulator/FDM/External/external.hxx
similarity index 97%
rename from Simulator/External/external.hxx
rename to Simulator/FDM/External/external.hxx
index ba7023fdb..87c4dec6d 100644
--- a/Simulator/External/external.hxx
+++ b/Simulator/FDM/External/external.hxx
@@ -83,6 +83,9 @@ void fgExternalInit( FGInterface& f );
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:46  curt
+// Initial revision
+//
 // Revision 1.6  1999/02/05 21:29:04  curt
 // Modifications to incorporate Jon S. Berndts flight model code.
 //
diff --git a/Simulator/FDM/JSBsim.cxx b/Simulator/FDM/JSBsim.cxx
index b8aa1dff0..7e0c34e72 100644
--- a/Simulator/FDM/JSBsim.cxx
+++ b/Simulator/FDM/JSBsim.cxx
@@ -258,6 +258,9 @@ int fgJSBsim_2_FGInterface (FGInterface& f) {
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:45  curt
+// Initial revision
+//
 // Revision 1.4  1999/04/03 04:20:01  curt
 // Optimizations (tm) by Norman Vine.
 //
diff --git a/Simulator/FDM/JSBsim.hxx b/Simulator/FDM/JSBsim.hxx
index 1901b2f6f..9d2211a94 100644
--- a/Simulator/FDM/JSBsim.hxx
+++ b/Simulator/FDM/JSBsim.hxx
@@ -48,6 +48,9 @@ int fgJSBsim_2_FGInterface (FGInterface& f);
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:45  curt
+// Initial revision
+//
 // Revision 1.2  1999/02/11 21:09:41  curt
 // Interface with Jon's submitted JSBsim changes.
 //
diff --git a/Simulator/JSBsim/FGAircraft.cpp b/Simulator/FDM/JSBsim/FGAircraft.cpp
similarity index 100%
rename from Simulator/JSBsim/FGAircraft.cpp
rename to Simulator/FDM/JSBsim/FGAircraft.cpp
diff --git a/Simulator/JSBsim/FGAircraft.h b/Simulator/FDM/JSBsim/FGAircraft.h
similarity index 100%
rename from Simulator/JSBsim/FGAircraft.h
rename to Simulator/FDM/JSBsim/FGAircraft.h
diff --git a/Simulator/JSBsim/FGAtmosphere.cpp b/Simulator/FDM/JSBsim/FGAtmosphere.cpp
similarity index 100%
rename from Simulator/JSBsim/FGAtmosphere.cpp
rename to Simulator/FDM/JSBsim/FGAtmosphere.cpp
diff --git a/Simulator/JSBsim/FGAtmosphere.h b/Simulator/FDM/JSBsim/FGAtmosphere.h
similarity index 100%
rename from Simulator/JSBsim/FGAtmosphere.h
rename to Simulator/FDM/JSBsim/FGAtmosphere.h
diff --git a/Simulator/JSBsim/FGAuxiliary.cpp b/Simulator/FDM/JSBsim/FGAuxiliary.cpp
similarity index 100%
rename from Simulator/JSBsim/FGAuxiliary.cpp
rename to Simulator/FDM/JSBsim/FGAuxiliary.cpp
diff --git a/Simulator/JSBsim/FGAuxiliary.h b/Simulator/FDM/JSBsim/FGAuxiliary.h
similarity index 100%
rename from Simulator/JSBsim/FGAuxiliary.h
rename to Simulator/FDM/JSBsim/FGAuxiliary.h
diff --git a/Simulator/JSBsim/FGCoefficient.cpp b/Simulator/FDM/JSBsim/FGCoefficient.cpp
similarity index 100%
rename from Simulator/JSBsim/FGCoefficient.cpp
rename to Simulator/FDM/JSBsim/FGCoefficient.cpp
diff --git a/Simulator/JSBsim/FGCoefficient.h b/Simulator/FDM/JSBsim/FGCoefficient.h
similarity index 100%
rename from Simulator/JSBsim/FGCoefficient.h
rename to Simulator/FDM/JSBsim/FGCoefficient.h
diff --git a/Simulator/JSBsim/FGControls.cpp b/Simulator/FDM/JSBsim/FGControls.cpp
similarity index 97%
rename from Simulator/JSBsim/FGControls.cpp
rename to Simulator/FDM/JSBsim/FGControls.cpp
index e79535986..714b4e16f 100644
--- a/Simulator/JSBsim/FGControls.cpp
+++ b/Simulator/FDM/JSBsim/FGControls.cpp
@@ -51,6 +51,9 @@ FGControls::~FGControls() {
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:46  curt
+// Initial revision
+//
 // Revision 1.1  1999/02/13 01:12:03  curt
 // Initial Revision.
 //
diff --git a/Simulator/JSBsim/FGControls.h b/Simulator/FDM/JSBsim/FGControls.h
similarity index 99%
rename from Simulator/JSBsim/FGControls.h
rename to Simulator/FDM/JSBsim/FGControls.h
index e347b6b2b..3979b4b02 100644
--- a/Simulator/JSBsim/FGControls.h
+++ b/Simulator/FDM/JSBsim/FGControls.h
@@ -176,6 +176,9 @@ extern FGControls controls;
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:45  curt
+// Initial revision
+//
 // Revision 1.1  1999/02/13 01:12:03  curt
 // Initial Revision.
 //
diff --git a/Simulator/JSBsim/FGDefs.h b/Simulator/FDM/JSBsim/FGDefs.h
similarity index 100%
rename from Simulator/JSBsim/FGDefs.h
rename to Simulator/FDM/JSBsim/FGDefs.h
diff --git a/Simulator/JSBsim/FGEngine.cpp b/Simulator/FDM/JSBsim/FGEngine.cpp
similarity index 100%
rename from Simulator/JSBsim/FGEngine.cpp
rename to Simulator/FDM/JSBsim/FGEngine.cpp
diff --git a/Simulator/JSBsim/FGEngine.h b/Simulator/FDM/JSBsim/FGEngine.h
similarity index 100%
rename from Simulator/JSBsim/FGEngine.h
rename to Simulator/FDM/JSBsim/FGEngine.h
diff --git a/Simulator/JSBsim/FGFCS.cpp b/Simulator/FDM/JSBsim/FGFCS.cpp
similarity index 100%
rename from Simulator/JSBsim/FGFCS.cpp
rename to Simulator/FDM/JSBsim/FGFCS.cpp
diff --git a/Simulator/JSBsim/FGFCS.h b/Simulator/FDM/JSBsim/FGFCS.h
similarity index 100%
rename from Simulator/JSBsim/FGFCS.h
rename to Simulator/FDM/JSBsim/FGFCS.h
diff --git a/Simulator/JSBsim/FGFDMExec.cpp b/Simulator/FDM/JSBsim/FGFDMExec.cpp
similarity index 100%
rename from Simulator/JSBsim/FGFDMExec.cpp
rename to Simulator/FDM/JSBsim/FGFDMExec.cpp
diff --git a/Simulator/JSBsim/FGFDMExec.h b/Simulator/FDM/JSBsim/FGFDMExec.h
similarity index 100%
rename from Simulator/JSBsim/FGFDMExec.h
rename to Simulator/FDM/JSBsim/FGFDMExec.h
diff --git a/Simulator/JSBsim/FGMain.cpp b/Simulator/FDM/JSBsim/FGMain.cpp
similarity index 100%
rename from Simulator/JSBsim/FGMain.cpp
rename to Simulator/FDM/JSBsim/FGMain.cpp
diff --git a/Simulator/JSBsim/FGMatrix.cpp b/Simulator/FDM/JSBsim/FGMatrix.cpp
similarity index 100%
rename from Simulator/JSBsim/FGMatrix.cpp
rename to Simulator/FDM/JSBsim/FGMatrix.cpp
diff --git a/Simulator/JSBsim/FGMatrix.h b/Simulator/FDM/JSBsim/FGMatrix.h
similarity index 100%
rename from Simulator/JSBsim/FGMatrix.h
rename to Simulator/FDM/JSBsim/FGMatrix.h
diff --git a/Simulator/JSBsim/FGModel.cpp b/Simulator/FDM/JSBsim/FGModel.cpp
similarity index 100%
rename from Simulator/JSBsim/FGModel.cpp
rename to Simulator/FDM/JSBsim/FGModel.cpp
diff --git a/Simulator/JSBsim/FGModel.h b/Simulator/FDM/JSBsim/FGModel.h
similarity index 100%
rename from Simulator/JSBsim/FGModel.h
rename to Simulator/FDM/JSBsim/FGModel.h
diff --git a/Simulator/JSBsim/FGOutput.cpp b/Simulator/FDM/JSBsim/FGOutput.cpp
similarity index 100%
rename from Simulator/JSBsim/FGOutput.cpp
rename to Simulator/FDM/JSBsim/FGOutput.cpp
diff --git a/Simulator/JSBsim/FGOutput.h b/Simulator/FDM/JSBsim/FGOutput.h
similarity index 100%
rename from Simulator/JSBsim/FGOutput.h
rename to Simulator/FDM/JSBsim/FGOutput.h
diff --git a/Simulator/JSBsim/FGPosition.cpp b/Simulator/FDM/JSBsim/FGPosition.cpp
similarity index 100%
rename from Simulator/JSBsim/FGPosition.cpp
rename to Simulator/FDM/JSBsim/FGPosition.cpp
diff --git a/Simulator/JSBsim/FGPosition.h b/Simulator/FDM/JSBsim/FGPosition.h
similarity index 100%
rename from Simulator/JSBsim/FGPosition.h
rename to Simulator/FDM/JSBsim/FGPosition.h
diff --git a/Simulator/JSBsim/FGRotation.cpp b/Simulator/FDM/JSBsim/FGRotation.cpp
similarity index 100%
rename from Simulator/JSBsim/FGRotation.cpp
rename to Simulator/FDM/JSBsim/FGRotation.cpp
diff --git a/Simulator/JSBsim/FGRotation.h b/Simulator/FDM/JSBsim/FGRotation.h
similarity index 100%
rename from Simulator/JSBsim/FGRotation.h
rename to Simulator/FDM/JSBsim/FGRotation.h
diff --git a/Simulator/JSBsim/FGState.cpp b/Simulator/FDM/JSBsim/FGState.cpp
similarity index 100%
rename from Simulator/JSBsim/FGState.cpp
rename to Simulator/FDM/JSBsim/FGState.cpp
diff --git a/Simulator/JSBsim/FGState.h b/Simulator/FDM/JSBsim/FGState.h
similarity index 100%
rename from Simulator/JSBsim/FGState.h
rename to Simulator/FDM/JSBsim/FGState.h
diff --git a/Simulator/JSBsim/FGTank.cpp b/Simulator/FDM/JSBsim/FGTank.cpp
similarity index 100%
rename from Simulator/JSBsim/FGTank.cpp
rename to Simulator/FDM/JSBsim/FGTank.cpp
diff --git a/Simulator/JSBsim/FGTank.h b/Simulator/FDM/JSBsim/FGTank.h
similarity index 100%
rename from Simulator/JSBsim/FGTank.h
rename to Simulator/FDM/JSBsim/FGTank.h
diff --git a/Simulator/JSBsim/FGTranslation.cpp b/Simulator/FDM/JSBsim/FGTranslation.cpp
similarity index 100%
rename from Simulator/JSBsim/FGTranslation.cpp
rename to Simulator/FDM/JSBsim/FGTranslation.cpp
diff --git a/Simulator/JSBsim/FGTranslation.h b/Simulator/FDM/JSBsim/FGTranslation.h
similarity index 100%
rename from Simulator/JSBsim/FGTranslation.h
rename to Simulator/FDM/JSBsim/FGTranslation.h
diff --git a/Simulator/JSBsim/FGUtility.cpp b/Simulator/FDM/JSBsim/FGUtility.cpp
similarity index 100%
rename from Simulator/JSBsim/FGUtility.cpp
rename to Simulator/FDM/JSBsim/FGUtility.cpp
diff --git a/Simulator/JSBsim/FGUtility.h b/Simulator/FDM/JSBsim/FGUtility.h
similarity index 100%
rename from Simulator/JSBsim/FGUtility.h
rename to Simulator/FDM/JSBsim/FGUtility.h
diff --git a/Simulator/JSBsim/Makefile.am b/Simulator/FDM/JSBsim/Makefile.am
similarity index 100%
rename from Simulator/JSBsim/Makefile.am
rename to Simulator/FDM/JSBsim/Makefile.am
diff --git a/Simulator/FDM/LaRCsim.cxx b/Simulator/FDM/LaRCsim.cxx
index b647f0340..49010e043 100644
--- a/Simulator/FDM/LaRCsim.cxx
+++ b/Simulator/FDM/LaRCsim.cxx
@@ -405,6 +405,9 @@ int fgLaRCsim_2_FGInterface (FGInterface& f) {
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:44  curt
+// Initial revision
+//
 // Revision 1.12  1999/04/03 04:20:02  curt
 // Optimizations (tm) by Norman Vine.
 //
diff --git a/Simulator/FDM/LaRCsim.hxx b/Simulator/FDM/LaRCsim.hxx
index 0231834c0..05d33c391 100644
--- a/Simulator/FDM/LaRCsim.hxx
+++ b/Simulator/FDM/LaRCsim.hxx
@@ -48,6 +48,9 @@ int fgLaRCsim_2_FGInterface (FGInterface& f);
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:44  curt
+// Initial revision
+//
 // Revision 1.5  1999/02/05 21:28:59  curt
 // Modifications to incorporate Jon S. Berndts flight model code.
 //
diff --git a/Simulator/FDM/LaRCsim/Cherokee.txt b/Simulator/FDM/LaRCsim/Cherokee.txt
new file mode 100644
index 000000000..7b7ca2275
--- /dev/null
+++ b/Simulator/FDM/LaRCsim/Cherokee.txt
@@ -0,0 +1,60 @@
+
+I will explain assumptions I have made:
+
+	All global vars, such as Alpha, Alpha_dot, Density, Altitude, so on,
+	have correct values in the moment cherokee functions are called.
+
+	Body coord system is defined as follows:
+		X_body  -> from cg to nose
+		Y_body  -> along right wing
+		Z_body  -> "down" (to make right coord system)
+		All forces and moments act in CG.
+
+		If strange behaviour is experienced, (like impossibility of level
+		flight), it is probably misused coord system. Let me know and fix
+		the error.
+
+	All controls are in the range [-1.0, 1.0] If it is not so, values in
+	cherokee_aero.c on lines 119-121 should be changed acordingly. If
+	commands appear to be oposite, this is the place to change sign
+	convention.
+
+	Engine controls are in range [0.0, 1.0] (I found out later that lower
+	bound is -0.2, so I added fabs(). I know, it is dirty and phisiclly
+	wrong, but it was simply the fastest way to deal with it).
+
+	All initialization files are *.ic:
+		mass = 74.53 slugs
+		Ixx  = 1070  slugs
+		Iyy  = 1249  slugs
+		Izz  = 2312  slugs
+		Ixz  = 0.0   slugs
+	above changes are writen in *.ic included in cherokee.zip. However,
+	other data in *.ic files are not changed in any way.
+
+	aditional properties: (if needed)
+		S    = 157.5 ft^2   -> wing area
+		b    = 30.0 ft 		-> wing span
+		Ar   = 5.71			-> aspect ratio
+		c    = 5.25 ft		-> midspan chord
+
+
+Once more: Source are TOTALY UNCHECKED. I hope it will work, but I do not
+dare to claim that ewerything will work first time you compile it.
+
+Good Luck!
+Gordan
+gsikic@public.srce.hr
+
+
+PS
+
+Work to be done (for myself):
+	Landing gear (it is just navion_gear.c copied for now, these are similar
+	class of aircraft, so it should work),
+	Alpha_max is still undone,
+	Spin (if I find any references concerning simulating spin),
+	Efect of ground,
+	Flaps,
+	.......
+
diff --git a/Simulator/LaRCsim/Makefile.am b/Simulator/FDM/LaRCsim/Makefile.am
similarity index 100%
rename from Simulator/LaRCsim/Makefile.am
rename to Simulator/FDM/LaRCsim/Makefile.am
diff --git a/Simulator/LaRCsim/atmos_62.c b/Simulator/FDM/LaRCsim/atmos_62.c
similarity index 100%
rename from Simulator/LaRCsim/atmos_62.c
rename to Simulator/FDM/LaRCsim/atmos_62.c
diff --git a/Simulator/LaRCsim/atmos_62.h b/Simulator/FDM/LaRCsim/atmos_62.h
similarity index 100%
rename from Simulator/LaRCsim/atmos_62.h
rename to Simulator/FDM/LaRCsim/atmos_62.h
diff --git a/Simulator/FDM/LaRCsim/cherokee_aero.c b/Simulator/FDM/LaRCsim/cherokee_aero.c
new file mode 100644
index 000000000..665f80cc2
--- /dev/null
+++ b/Simulator/FDM/LaRCsim/cherokee_aero.c
@@ -0,0 +1,170 @@
+/***************************************************************************
+
+  TITLE:	Cherokee_aero
+		
+----------------------------------------------------------------------------
+
+  FUNCTION:	Linear aerodynamics model
+
+----------------------------------------------------------------------------
+
+  MODULE STATUS:	developmental
+
+----------------------------------------------------------------------------
+
+  GENEALOGY:
+
+----------------------------------------------------------------------------
+
+  MODIFICATION HISTORY:
+		
+
+----------------------------------------------------------------------------
+
+  REFERENCES:
+
+  		Based upon book:
+				Barnes W. McCormick,
+				"Aerodynamics, Aeronautics and Flight Mechanics",
+				John Wiley & Sons,1995, ISBN 0-471-11087-6
+
+	any suggestions, corrections, aditional data, flames, everything to 
+	Gordan Sikic
+	gsikic@public.srce.hr
+
+This source is not checked in this configuration in any way.
+
+
+----------------------------------------------------------------------------
+
+  CALLED BY:
+
+----------------------------------------------------------------------------
+
+  CALLS TO:
+
+----------------------------------------------------------------------------
+
+  INPUTS:
+
+----------------------------------------------------------------------------
+
+  OUTPUTS:
+
+--------------------------------------------------------------------------*/
+
+
+
+
+#include 
+#include 
+#include "ls_types.h"
+#include "ls_generic.h"
+#include "ls_cockpit.h"
+
+
+
+
+
+void aero()
+/*float ** Cherokee (float t, VectorStanja &X, float *U)*/
+{
+ 	static float
+		Cza  = -19149.0/(146.69*146.69*157.5/2.0*0.00238), 
+		Czat = -73.4*4*146.69/0.00238/157.5/5.25, 
+		Czq  = -2.655*4*2400.0/32.2/0.00238/157.5/146.69/5.25, 
+		Cma  = -21662.0 *2/146.69/0.00238/157.5/146.69/5.25, 
+		Cmat = -892.4 *4/146.69/0.00238/157.5/146.69/5.25, 
+		Cmq  = -2405.1 *4/0.00238/157.5/146.69/5.25/5.25, 
+		Czde = -1050.49 *2/0.00238/157.5/146.69/146.69, 
+		Cmde = -12771.9 *2/0.00238/157.5/146.69/146.69/5.25, 
+		Clb  = -12891.0/(146.69*146.69*157.5/2.0*0.00238)/30.0, 
+		Clp  = -0.4704, 
+		Clr  = 0.1665, 
+		Cyb  = -1169.8/(146.69*146.69*157.5/2.0*0.00238),
+		Cyp  = -0.0342, 
+		Cnb  = 11127.2/(146.69*146.69*157.5/2.0*0.00238)/30.0, 
+		Cnp  = -0.0691, 
+		Cnr  = -0.0930, 
+		Cyf  = -14.072/(146.69*146.69*157.5/2.0*0.00238), 
+		Cyps = 89.229/(146.69*146.69*157.5/2.0*0.00238), 
+		Clf  = -5812.4/(146.69*146.69*157.5/2.0*0.00238)/30.0,  //%Clda ?  
+		Cnf  = -853.93/(146.69*146.69*157.5/2.0*0.00238)/30.0,  //%Cnda ?  
+		Cnps = -1149.0/(146.69*146.69*157.5/2.0*0.00238)/30.0,  //%Cndr ?  
+		Cyr  = 1.923/(146.69*146.69*157.5/2.0*0.00238), 
+
+		Cx0 = -0.4645/(157.5*0.3048*0.3048), 
+
+		Cz0 = -0.11875, 
+		Cm0 =  0.0959, 
+
+		Clda = -5812.4/(146.69*146.69*157.5/2.0*0.00238)/30.0, // Clf
+		Cnda = -853.93/(146.69*146.69*157.5/2.0*0.00238)/30.0, // Cnf
+		Cndr = -1149.0/(146.69*146.69*157.5/2.0*0.00238)/30.0, // Cnps
+
+/*
+	Possible problems: convention about positive control surfaces offset
+*/
+		elevator = 0.0, // 20.0 * 180.0/57.3 * Long_control
+		aileron  = 0.0, // 30.0 * 180.0/57.3 * Lat_control
+		rudder   = 0.0, // 30.0 * 180.0/57.3 * Rudder_pedal,
+
+
+//		m = 2400/32.2,		// mass 
+		S = 157.5,			// wing area
+		b = 30.0,			// wing span
+		c = 5.25,			// main aerodynamic chrod
+
+//		Ixyz[3] = {1070.0*14.59*0.3048*0.3048, 1249.0*14.59*0.3048*0.3048, 2312.0*14.59*0.3048*0.3048}, 
+//		Fa[3], 
+//		Ma[3], 
+//		*RetVal[4] = {&m, Ixyz, Fa, Ma}; 
+
+
+//	float
+	        V = 0.0, // V_rel_wind
+	        qd = 0.0, // Density*V*V/2.0, 			//dinamicki tlak  
+
+		Cx,Cy,Cz,
+		Cl,Cm,Cn,
+		p,q,r;
+
+
+/* derivatives are defined in "wind" axes so... */
+		p =  P_body*Cos_alpha + R_body*Sin_alpha;
+		q =  Q_body;
+		r = -P_body*Sin_alpha + R_body*Cos_alpha;
+
+
+
+		Cz = Cz0 + Cza*Alpha + Czat*(Alpha_dot*c/2.0/V) + Czq*(q*c/2.0/V) + Czde * elevator;
+		Cm = Cm0 + Cma*Alpha + Cmat*(Alpha_dot*c/2.0/V) + Cmq*(q*c/2.0/V) + Cmde * elevator; 
+
+		Cx = Cx0 - (Cza*Alpha)*(Cza*Alpha)/(M_PI*5.71*0.6);
+		Cl = Clb*Beta + Clp*(p*b/2.0/V) + Clr*(r*b/2.0/V) + Clda * aileron;
+
+		Cy = Cyb*Beta + Cyr*(r*b/2.0/V); 
+		Cn = Cnb*Beta + Cnp*(p*b/2.0/V) + Cnr*(r*b/2.0/V) + Cndr * rudder; 
+
+/* back to body axes */
+	{
+		float
+			CD = Cx,
+			CL = Cz;
+
+			Cx = CD - CL*Sin_alpha;
+			Cz = CL;
+	}
+
+/* AD forces and moments   */
+		F_X_aero = Cx*qd*S;
+		F_Y_aero = Cy*qd*S;
+		F_Z_aero = Cz*qd*S;
+
+		M_l_aero = (Cl*Cos_alpha - Cn*Sin_alpha)*b*qd*S; 
+		M_m_aero = Cm*c*qd*S; 
+		M_n_aero = (Cl*Sin_alpha + Cn*Cos_alpha)*b*qd*S; 
+}
+
+
+
diff --git a/Simulator/FDM/LaRCsim/cherokee_engine.c b/Simulator/FDM/LaRCsim/cherokee_engine.c
new file mode 100644
index 000000000..e67a8b9b9
--- /dev/null
+++ b/Simulator/FDM/LaRCsim/cherokee_engine.c
@@ -0,0 +1,104 @@
+/*
+cherokee_engine.c
+
+very rough model of Lycoming engine built in PA-28 Cherokee
+Only "AD" characteristics are modelled, no transient behaviour,
+meaning that there is no time delay, engine acts as gain only.
+
+
+
+  		Based upon book:
+				Barnes W. McCormick,
+				"Aerodynamics, Aeronautics and Flight Mechanics",
+				John Wiley & Sons,1995, ISBN 0-471-11087-6
+
+	any suggestions, corrections, aditional data, flames, everything to 
+	Gordan Sikic
+	gsikic@public.srce.hr
+
+
+This source is not checked in this configuration in any way.
+
+
+*/
+
+
+
+#include 
+#include 
+#include "ls_types.h"
+#include "ls_constants.h"
+#include "ls_generic.h"
+#include "ls_cockpit.h"
+#include "ls_sim_control.h"
+
+
+
+
+
+void engine( SCALAR dt, int init )
+{
+
+	static float
+		dP = (180.0-117.0)*745.7,   // in Wats
+		dn = (2700.0-2350.0)/60.0,  // d_rpm (I mean d_rps, in seconds)
+		D  = 6.17*0.3048,			// propeller diameter
+		dPh = (58.0-180.0)*745.7,	// change of power as f-cn of height
+		dH = 25000.0*0.3048;
+
+	float 	n, 			// rps
+	                H,
+			J,			// advance ratio (ratio of horizontal speed to speed of propeller's tip)
+			eta,		// iskoristivost elise
+			T,
+			V,
+			P;
+
+/* copied from  navion_engine.c */
+    if (init || sim_control_.sim_type != cockpit) 
+	Throttle[3] = Throttle_pct;
+
+	/*assumption -> 0.0 <= Throttle[3] <=1.0 */
+	P = fabs(Throttle[3])*180.0*745.7;		/*180.0*745.5 ->max avail power in W */
+	n = dn/dP*(P-117.0*745.7) + 2350.0/60.0;
+
+/*  V  [m/s]   */
+	V = (V_rel_wind < 10.0*0.3048 ? 10.0 : V_rel_wind*0.3048);
+
+	J = V/n/D;  
+
+
+/*
+	propeller efficiency
+
+if J >0.7 & J < .85
+	eta = 0.8;
+elseif J < 0.7
+	eta = (0.8-0.55)/(.7-.3)*(J-0.3) + 0.55;
+else
+	eta = (0.6-0.8)/(1.0-0.85)*(J-0.85) + 0.8;
+end
+*/
+	eta = (J < 0.7 ? ((0.8-0.55)/(.7-.3)*(J-0.3) + 0.55) : 
+			(J > 0.85 ? ((0.6-0.8)/(1.0-0.85)*(J-0.85) + 0.8) : 0.8));
+
+
+
+/* power on Altitude  (I mean Altitude, not Attitude...)*/
+
+	H = Altitude/0.3048; /* H == Altitude in [m] */
+	
+	P *= (dPh/dH*H + 180.0*745.7)/(180.0*745.7);
+
+	T = eta*P/V;	/* T in N (Thrust in Newtons) */ 
+
+/*assumption: Engine's line of thrust passes through cg */
+
+    F_X_engine = T*0.2248;	/* F_X_engine in lb */
+    F_Y_engine = 0.0;
+    F_Z_engine = 0.0;
+
+/* copied from  navion_engine.c */
+    Throttle_pct = Throttle[3];
+
+}
diff --git a/Simulator/FDM/LaRCsim/cherokee_gear.c b/Simulator/FDM/LaRCsim/cherokee_gear.c
new file mode 100644
index 000000000..304345066
--- /dev/null
+++ b/Simulator/FDM/LaRCsim/cherokee_gear.c
@@ -0,0 +1,314 @@
+/***************************************************************************
+
+	TITLE:	gear
+	
+----------------------------------------------------------------------------
+
+	FUNCTION:	Landing gear model for example simulation
+
+----------------------------------------------------------------------------
+
+	MODULE STATUS:	developmental
+
+----------------------------------------------------------------------------
+
+	GENEALOGY:	Created 931012 by E. B. Jackson
+
+----------------------------------------------------------------------------
+
+	DESIGNED BY:	E. B. Jackson
+	
+	CODED BY:	E. B. Jackson
+	
+	MAINTAINED BY:	E. B. Jackson
+
+----------------------------------------------------------------------------
+
+	MODIFICATION HISTORY:
+	
+	DATE	PURPOSE						BY
+
+	931218	Added navion.h header to allow connection with
+		aileron displacement for nosewheel steering.	EBJ
+	940511	Connected nosewheel to rudder pedal; adjusted gain.
+	
+	CURRENT RCS HEADER:
+
+$Header$
+$Log$
+Revision 1.1  1999/04/05 21:32:45  curt
+Initial revision
+
+
+----------------------------------------------------------------------------
+
+	REFERENCES:
+
+----------------------------------------------------------------------------
+
+	CALLED BY:
+
+----------------------------------------------------------------------------
+
+	CALLS TO:
+
+----------------------------------------------------------------------------
+
+	INPUTS:
+
+----------------------------------------------------------------------------
+
+	OUTPUTS:
+
+--------------------------------------------------------------------------*/
+#include 
+#include "ls_types.h"
+#include "ls_constants.h"
+#include "ls_generic.h"
+#include "ls_cockpit.h"
+
+
+void sub3( DATA v1[],  DATA v2[], DATA result[] )
+{
+    result[0] = v1[0] - v2[0];
+    result[1] = v1[1] - v2[1];
+    result[2] = v1[2] - v2[2];
+}
+
+void add3( DATA v1[],  DATA v2[], DATA result[] )
+{
+    result[0] = v1[0] + v2[0];
+    result[1] = v1[1] + v2[1];
+    result[2] = v1[2] + v2[2];
+}
+
+void cross3( DATA v1[],  DATA v2[], DATA result[] )
+{
+    result[0] = v1[1]*v2[2] - v1[2]*v2[1];
+    result[1] = v1[2]*v2[0] - v1[0]*v2[2];
+    result[2] = v1[0]*v2[1] - v1[1]*v2[0];
+}
+
+void multtrans3x3by3( DATA m[][3], DATA v[], DATA result[] )
+{
+    result[0] = m[0][0]*v[0] + m[1][0]*v[1] + m[2][0]*v[2];
+    result[1] = m[0][1]*v[0] + m[1][1]*v[1] + m[2][1]*v[2];
+    result[2] = m[0][2]*v[0] + m[1][2]*v[1] + m[2][2]*v[2];
+}
+
+void mult3x3by3( DATA m[][3], DATA v[], DATA result[] )
+{
+    result[0] = m[0][0]*v[0] + m[0][1]*v[1] + m[0][2]*v[2];
+    result[1] = m[1][0]*v[0] + m[1][1]*v[1] + m[1][2]*v[2];
+    result[2] = m[2][0]*v[0] + m[2][1]*v[1] + m[2][2]*v[2];
+}
+
+void clear3( DATA v[] )
+{
+    v[0] = 0.; v[1] = 0.; v[2] = 0.;
+}
+
+void gear()
+{
+char rcsid[] = "$Id$";
+
+  /*
+   * Aircraft specific initializations and data goes here
+   */
+   
+#define NUM_WHEELS 3
+
+    static int num_wheels = NUM_WHEELS;		    /* number of wheels  */
+    static DATA d_wheel_rp_body_v[NUM_WHEELS][3] =  /* X, Y, Z locations */
+    {
+	{ 10.,  0., 4. },				/* in feet */
+	{ -1.,  3., 4. }, 
+	{ -1., -3., 4. }
+    };
+    static DATA spring_constant[NUM_WHEELS] =	    /* springiness, lbs/ft */
+	{ 1500., 5000., 5000. };
+    static DATA spring_damping[NUM_WHEELS] =	    /* damping, lbs/ft/sec */
+	{ 100.,  150.,  150. };		
+    static DATA percent_brake[NUM_WHEELS] =	    /* percent applied braking */
+	{ 0.,  0.,  0. };			    /* 0 = none, 1 = full */
+    static DATA caster_angle_rad[NUM_WHEELS] =	    /* steerable tires - in */
+	{ 0., 0., 0.};				    /* radians, +CW */	
+  /*
+   * End of aircraft specific code
+   */
+    
+  /*
+   * Constants & coefficients for tyres on tarmac - ref [1]
+   */
+   
+    /* skid function looks like:
+     * 
+     *           mu  ^
+     *               |
+     *       max_mu  |       +		
+     *               |      /|		
+     *   sliding_mu  |     / +------	
+     *               |    /		
+     *               |   /		
+     *               +--+------------------------> 
+     *               |  |    |      sideward V
+     *               0 bkout skid
+     *	               V     V
+     */
+  
+  
+    static DATA sliding_mu   = 0.5;	
+    static DATA rolling_mu   = 0.01;	
+    static DATA max_brake_mu = 0.6;	
+    static DATA max_mu	     = 0.8;	
+    static DATA bkout_v	     = 0.1;
+    static DATA skid_v       = 1.0;
+  /*
+   * Local data variables
+   */
+   
+    DATA d_wheel_cg_body_v[3];		/* wheel offset from cg,  X-Y-Z	*/
+    DATA d_wheel_cg_local_v[3];		/* wheel offset from cg,  N-E-D	*/
+    DATA d_wheel_rwy_local_v[3];	/* wheel offset from rwy, N-E-U */
+    DATA v_wheel_body_v[3];		/* wheel velocity,	  X-Y-Z	*/
+    DATA v_wheel_local_v[3];		/* wheel velocity,	  N-E-D	*/
+    DATA f_wheel_local_v[3];		/* wheel reaction force,  N-E-D	*/
+    DATA temp3a[3], temp3b[3], tempF[3], tempM[3];	
+    DATA reaction_normal_force;		/* wheel normal (to rwy) force	*/
+    DATA cos_wheel_hdg_angle, sin_wheel_hdg_angle;	/* temp storage */
+    DATA v_wheel_forward, v_wheel_sideward,  abs_v_wheel_sideward;
+    DATA forward_mu, sideward_mu;	/* friction coefficients	*/
+    DATA beta_mu;			/* breakout friction slope	*/
+    DATA forward_wheel_force, sideward_wheel_force;
+
+    int i;				/* per wheel loop counter */
+  
+  /*
+   * Execution starts here
+   */
+   
+    beta_mu = max_mu/(skid_v-bkout_v);
+    clear3( F_gear_v );		/* Initialize sum of forces...	*/
+    clear3( M_gear_v );		/* ...and moments		*/
+    
+  /*
+   * Put aircraft specific executable code here
+   */
+   
+    percent_brake[1] = 0.; /* replace with cockpit brake handle connection code */
+    percent_brake[2] = percent_brake[1];
+    
+    caster_angle_rad[0] = 0.03*Rudder_pedal;
+    
+    for (i=0;i 0.) reaction_normal_force = 0.;
+		/* to prevent damping component from swamping spring component */
+	}
+	
+	    /* Calculate friction coefficients */
+	    
+	forward_mu = (max_brake_mu - rolling_mu)*percent_brake[i] + rolling_mu;
+	abs_v_wheel_sideward = sqrt(v_wheel_sideward*v_wheel_sideward);
+	sideward_mu = sliding_mu;
+	if (abs_v_wheel_sideward < skid_v) 
+	    sideward_mu = (abs_v_wheel_sideward - bkout_v)*beta_mu;
+	if (abs_v_wheel_sideward < bkout_v) sideward_mu = 0.;
+
+	    /* Calculate foreward and sideward reaction forces */
+	    
+	forward_wheel_force  =   forward_mu*reaction_normal_force;
+	sideward_wheel_force =  sideward_mu*reaction_normal_force;
+	if(v_wheel_forward < 0.) forward_wheel_force = -forward_wheel_force;
+	if(v_wheel_sideward < 0.) sideward_wheel_force = -sideward_wheel_force;
+	
+	    /* Rotate into local (N-E-D) axes */
+	
+	f_wheel_local_v[0] = forward_wheel_force*cos_wheel_hdg_angle
+			  - sideward_wheel_force*sin_wheel_hdg_angle;
+	f_wheel_local_v[1] = forward_wheel_force*sin_wheel_hdg_angle
+			  + sideward_wheel_force*cos_wheel_hdg_angle;
+	f_wheel_local_v[2] = reaction_normal_force;	  
+	   
+	    /* Convert reaction force from local (N-E-D) axes to body (X-Y-Z) */
+	
+	mult3x3by3( T_local_to_body_m, f_wheel_local_v, tempF );
+	
+	    /* Calculate moments from force and offsets in body axes */
+
+	cross3( d_wheel_cg_body_v, tempF, tempM );
+	
+	/* Sum forces and moments across all wheels */
+	
+	add3( tempF, F_gear_v, F_gear_v );
+	add3( tempM, M_gear_v, M_gear_v );
+	
+    }
+}
diff --git a/Simulator/FDM/LaRCsim/cherokee_init.c b/Simulator/FDM/LaRCsim/cherokee_init.c
new file mode 100644
index 000000000..23ce52915
--- /dev/null
+++ b/Simulator/FDM/LaRCsim/cherokee_init.c
@@ -0,0 +1,63 @@
+/***************************************************************************
+
+	TITLE:	cherokee_init.c
+	
+----------------------------------------------------------------------------
+
+	FUNCTION:	Initializes cherokee math model
+
+----------------------------------------------------------------------------
+
+	MODULE STATUS:	developmental
+
+----------------------------------------------------------------------------
+
+	GENEALOGY: 
+
+----------------------------------------------------------------------------
+
+----------------------------------------------------------------------------
+
+	CURRENT RCS HEADER:
+
+	 Well, 
+	 I do not have vorking RCS here (Sorry)
+
+----------------------------------------------------------------------------
+
+	REFERENCES:
+
+----------------------------------------------------------------------------
+
+	CALLED BY:
+
+----------------------------------------------------------------------------
+
+	CALLS TO:
+
+----------------------------------------------------------------------------
+
+	INPUTS:
+
+----------------------------------------------------------------------------
+
+	OUTPUTS:
+
+--------------------------------------------------------------------------*/
+#include "ls_types.h"
+#include "ls_generic.h"
+#include "ls_cockpit.h"
+
+void model_init( void )
+{
+
+  Throttle[3] = 0.2; Rudder_pedal = 0; Lat_control = 0; Long_control = 0;
+  
+  Dx_pilot = 0; Dy_pilot = 0; Dz_pilot = 0;
+  
+  Runway_altitude = 0;
+  Runway_latitude = 0;
+  Runway_longitude = 0;
+  Runway_heading = 0;
+  
+}
diff --git a/Simulator/LaRCsim/default_model_routines.c b/Simulator/FDM/LaRCsim/default_model_routines.c
similarity index 97%
rename from Simulator/LaRCsim/default_model_routines.c
rename to Simulator/FDM/LaRCsim/default_model_routines.c
index 4fb611c95..c223390f0 100644
--- a/Simulator/LaRCsim/default_model_routines.c
+++ b/Simulator/FDM/LaRCsim/default_model_routines.c
@@ -33,6 +33,9 @@
 $Header$
 
 $Log$
+Revision 1.1  1999/04/05 21:32:45  curt
+Initial revision
+
 Revision 1.3  1998/08/06 12:46:37  curt
 Header change.
 
diff --git a/Simulator/LaRCsim/default_model_routines.h b/Simulator/FDM/LaRCsim/default_model_routines.h
similarity index 100%
rename from Simulator/LaRCsim/default_model_routines.h
rename to Simulator/FDM/LaRCsim/default_model_routines.h
diff --git a/Simulator/LaRCsim/ls_accel.c b/Simulator/FDM/LaRCsim/ls_accel.c
similarity index 99%
rename from Simulator/LaRCsim/ls_accel.c
rename to Simulator/FDM/LaRCsim/ls_accel.c
index 7e419fdef..e7b7339c0 100644
--- a/Simulator/LaRCsim/ls_accel.c
+++ b/Simulator/FDM/LaRCsim/ls_accel.c
@@ -38,6 +38,9 @@
 	    
 $Header$
 $Log$
+Revision 1.1  1999/04/05 21:32:45  curt
+Initial revision
+
 Revision 1.4  1998/08/24 20:09:26  curt
 Code optimization tweaks from Norman Vine.
 
diff --git a/Simulator/LaRCsim/ls_accel.h b/Simulator/FDM/LaRCsim/ls_accel.h
similarity index 100%
rename from Simulator/LaRCsim/ls_accel.h
rename to Simulator/FDM/LaRCsim/ls_accel.h
diff --git a/Simulator/LaRCsim/ls_aux.c b/Simulator/FDM/LaRCsim/ls_aux.c
similarity index 99%
rename from Simulator/LaRCsim/ls_aux.c
rename to Simulator/FDM/LaRCsim/ls_aux.c
index 448448cf6..252de03ad 100644
--- a/Simulator/LaRCsim/ls_aux.c
+++ b/Simulator/FDM/LaRCsim/ls_aux.c
@@ -47,6 +47,9 @@
 
 $Header$
 $Log$
+Revision 1.1  1999/04/05 21:32:45  curt
+Initial revision
+
 Revision 1.4  1998/08/24 20:09:26  curt
 Code optimization tweaks from Norman Vine.
 
diff --git a/Simulator/LaRCsim/ls_aux.h b/Simulator/FDM/LaRCsim/ls_aux.h
similarity index 100%
rename from Simulator/LaRCsim/ls_aux.h
rename to Simulator/FDM/LaRCsim/ls_aux.h
diff --git a/Simulator/LaRCsim/ls_cockpit.h b/Simulator/FDM/LaRCsim/ls_cockpit.h
similarity index 97%
rename from Simulator/LaRCsim/ls_cockpit.h
rename to Simulator/FDM/LaRCsim/ls_cockpit.h
index 3dcddcdc9..1ac8e63ee 100644
--- a/Simulator/LaRCsim/ls_cockpit.h
+++ b/Simulator/FDM/LaRCsim/ls_cockpit.h
@@ -35,6 +35,9 @@
 
 $Header$
 $Log$
+Revision 1.1  1999/04/05 21:32:45  curt
+Initial revision
+
 Revision 1.5  1998/10/17 01:34:14  curt
 C++ ifying ...
 
diff --git a/Simulator/LaRCsim/ls_constants.h b/Simulator/FDM/LaRCsim/ls_constants.h
similarity index 100%
rename from Simulator/LaRCsim/ls_constants.h
rename to Simulator/FDM/LaRCsim/ls_constants.h
diff --git a/Simulator/LaRCsim/ls_generic.h b/Simulator/FDM/LaRCsim/ls_generic.h
similarity index 100%
rename from Simulator/LaRCsim/ls_generic.h
rename to Simulator/FDM/LaRCsim/ls_generic.h
diff --git a/Simulator/LaRCsim/ls_geodesy.c b/Simulator/FDM/LaRCsim/ls_geodesy.c
similarity index 98%
rename from Simulator/LaRCsim/ls_geodesy.c
rename to Simulator/FDM/LaRCsim/ls_geodesy.c
index ed808d135..6d4073c8b 100644
--- a/Simulator/LaRCsim/ls_geodesy.c
+++ b/Simulator/FDM/LaRCsim/ls_geodesy.c
@@ -40,6 +40,9 @@
 
 $Header$
 $Log$
+Revision 1.1  1999/04/05 21:32:45  curt
+Initial revision
+
 Revision 1.3  1998/07/08 14:41:37  curt
 .
 
diff --git a/Simulator/LaRCsim/ls_geodesy.h b/Simulator/FDM/LaRCsim/ls_geodesy.h
similarity index 100%
rename from Simulator/LaRCsim/ls_geodesy.h
rename to Simulator/FDM/LaRCsim/ls_geodesy.h
diff --git a/Simulator/LaRCsim/ls_gravity.c b/Simulator/FDM/LaRCsim/ls_gravity.c
similarity index 97%
rename from Simulator/LaRCsim/ls_gravity.c
rename to Simulator/FDM/LaRCsim/ls_gravity.c
index 44b56349f..b095e6bfc 100644
--- a/Simulator/LaRCsim/ls_gravity.c
+++ b/Simulator/FDM/LaRCsim/ls_gravity.c
@@ -35,6 +35,9 @@
 										
 $Header$
 $Log$
+Revision 1.1  1999/04/05 21:32:45  curt
+Initial revision
+
 Revision 1.3  1998/08/06 12:46:39  curt
 Header change.
 
diff --git a/Simulator/LaRCsim/ls_gravity.h b/Simulator/FDM/LaRCsim/ls_gravity.h
similarity index 100%
rename from Simulator/LaRCsim/ls_gravity.h
rename to Simulator/FDM/LaRCsim/ls_gravity.h
diff --git a/Simulator/LaRCsim/ls_init.c b/Simulator/FDM/LaRCsim/ls_init.c
similarity index 99%
rename from Simulator/LaRCsim/ls_init.c
rename to Simulator/FDM/LaRCsim/ls_init.c
index 755076446..e1669f880 100644
--- a/Simulator/LaRCsim/ls_init.c
+++ b/Simulator/FDM/LaRCsim/ls_init.c
@@ -34,6 +34,9 @@
 
 $Header$
 $Log$
+Revision 1.1  1999/04/05 21:32:45  curt
+Initial revision
+
 Revision 1.5  1998/07/12 03:11:03  curt
 Removed some printf()'s.
 Fixed the autopilot integration so it should be able to update it's control
diff --git a/Simulator/LaRCsim/ls_init.h b/Simulator/FDM/LaRCsim/ls_init.h
similarity index 100%
rename from Simulator/LaRCsim/ls_init.h
rename to Simulator/FDM/LaRCsim/ls_init.h
diff --git a/Simulator/LaRCsim/ls_interface.c b/Simulator/FDM/LaRCsim/ls_interface.c
similarity index 99%
rename from Simulator/LaRCsim/ls_interface.c
rename to Simulator/FDM/LaRCsim/ls_interface.c
index 09eda1ed1..532e9accb 100644
--- a/Simulator/LaRCsim/ls_interface.c
+++ b/Simulator/FDM/LaRCsim/ls_interface.c
@@ -574,6 +574,9 @@ int ls_ForceAltitude(double alt_feet) {
 /* Flight Gear Modification Log
  *
  * $Log$
+ * Revision 1.1  1999/04/05 21:32:45  curt
+ * Initial revision
+ *
  * Revision 1.25  1999/01/19 20:57:02  curt
  * MacOS portability changes contributed by "Robert Puyol" 
  *
diff --git a/Simulator/LaRCsim/ls_interface.h b/Simulator/FDM/LaRCsim/ls_interface.h
similarity index 98%
rename from Simulator/LaRCsim/ls_interface.h
rename to Simulator/FDM/LaRCsim/ls_interface.h
index 67745dd28..fa3a8aed4 100644
--- a/Simulator/LaRCsim/ls_interface.h
+++ b/Simulator/FDM/LaRCsim/ls_interface.h
@@ -65,6 +65,9 @@ int ls_ForceAltitude(double alt_feet);
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:45  curt
+// Initial revision
+//
 // Revision 1.11  1998/10/17 01:34:15  curt
 // C++ ifying ...
 //
diff --git a/Simulator/LaRCsim/ls_matrix.c b/Simulator/FDM/LaRCsim/ls_matrix.c
similarity index 99%
rename from Simulator/LaRCsim/ls_matrix.c
rename to Simulator/FDM/LaRCsim/ls_matrix.c
index 808eade4b..cb8fcc2d5 100644
--- a/Simulator/LaRCsim/ls_matrix.c
+++ b/Simulator/FDM/LaRCsim/ls_matrix.c
@@ -46,6 +46,9 @@
 
 $Header$
 $Log$
+Revision 1.1  1999/04/05 21:32:45  curt
+Initial revision
+
 Revision 1.1  1998/06/27 22:34:57  curt
 Initial revision.
 
diff --git a/Simulator/LaRCsim/ls_matrix.h b/Simulator/FDM/LaRCsim/ls_matrix.h
similarity index 98%
rename from Simulator/LaRCsim/ls_matrix.h
rename to Simulator/FDM/LaRCsim/ls_matrix.h
index 85ec27e94..9de1fcb14 100644
--- a/Simulator/LaRCsim/ls_matrix.h
+++ b/Simulator/FDM/LaRCsim/ls_matrix.h
@@ -44,6 +44,9 @@
 
 $Header$
 $Log$
+Revision 1.1  1999/04/05 21:32:45  curt
+Initial revision
+
 Revision 1.1  1998/06/27 22:34:58  curt
 Initial revision.
 
diff --git a/Simulator/LaRCsim/ls_model.c b/Simulator/FDM/LaRCsim/ls_model.c
similarity index 97%
rename from Simulator/LaRCsim/ls_model.c
rename to Simulator/FDM/LaRCsim/ls_model.c
index b9646a14f..ccdfc875e 100644
--- a/Simulator/LaRCsim/ls_model.c
+++ b/Simulator/FDM/LaRCsim/ls_model.c
@@ -37,6 +37,9 @@
 	CURRENT RCS HEADER INFO:
 $Header$
 $Log$
+Revision 1.1  1999/04/05 21:32:45  curt
+Initial revision
+
 Revision 1.3  1998/08/06 12:46:39  curt
 Header change.
 
diff --git a/Simulator/LaRCsim/ls_model.h b/Simulator/FDM/LaRCsim/ls_model.h
similarity index 100%
rename from Simulator/LaRCsim/ls_model.h
rename to Simulator/FDM/LaRCsim/ls_model.h
diff --git a/Simulator/LaRCsim/ls_sim_control.h b/Simulator/FDM/LaRCsim/ls_sim_control.h
similarity index 98%
rename from Simulator/LaRCsim/ls_sim_control.h
rename to Simulator/FDM/LaRCsim/ls_sim_control.h
index 753c75be5..16d4238ab 100644
--- a/Simulator/LaRCsim/ls_sim_control.h
+++ b/Simulator/FDM/LaRCsim/ls_sim_control.h
@@ -40,6 +40,9 @@
 
 $Header$
 $Log$
+Revision 1.1  1999/04/05 21:32:45  curt
+Initial revision
+
 Revision 1.4  1998/08/06 12:46:39  curt
 Header change.
 
diff --git a/Simulator/LaRCsim/ls_step.c b/Simulator/FDM/LaRCsim/ls_step.c
similarity index 99%
rename from Simulator/LaRCsim/ls_step.c
rename to Simulator/FDM/LaRCsim/ls_step.c
index 58838e8d3..7bbae99a8 100644
--- a/Simulator/LaRCsim/ls_step.c
+++ b/Simulator/FDM/LaRCsim/ls_step.c
@@ -50,6 +50,9 @@
 
 $Header$
 $Log$
+Revision 1.1  1999/04/05 21:32:45  curt
+Initial revision
+
 Revision 1.4  1998/08/24 20:09:27  curt
 Code optimization tweaks from Norman Vine.
 
diff --git a/Simulator/LaRCsim/ls_step.h b/Simulator/FDM/LaRCsim/ls_step.h
similarity index 100%
rename from Simulator/LaRCsim/ls_step.h
rename to Simulator/FDM/LaRCsim/ls_step.h
diff --git a/Simulator/LaRCsim/ls_sym.h b/Simulator/FDM/LaRCsim/ls_sym.h
similarity index 98%
rename from Simulator/LaRCsim/ls_sym.h
rename to Simulator/FDM/LaRCsim/ls_sym.h
index eca19894b..3d2763a2d 100644
--- a/Simulator/LaRCsim/ls_sym.h
+++ b/Simulator/FDM/LaRCsim/ls_sym.h
@@ -40,6 +40,9 @@
 
 $Header$
 $Log$
+Revision 1.1  1999/04/05 21:32:45  curt
+Initial revision
+
 Revision 1.3  1998/08/06 12:46:40  curt
 Header change.
 
diff --git a/Simulator/FDM/LaRCsim/ls_trim.c b/Simulator/FDM/LaRCsim/ls_trim.c
new file mode 100644
index 000000000..97a2d8907
--- /dev/null
+++ b/Simulator/FDM/LaRCsim/ls_trim.c
@@ -0,0 +1,685 @@
+/***************************************************************************
+
+  	TITLE:		ls_trim.c
+
+----------------------------------------------------------------------------
+
+	FUNCTION:  	Trims the simulated aircraft by using certain
+			controls to null out a similar number of outputs.
+
+        This routine used modified Newton-Raphson method to find the vector
+	of control corrections, delta_U, to drive a similar-sized vector of
+	output errors, Y, to near-zero.  Nearness to zero is to within a
+	tolerance specified by the Criteria vector.  An optional Weight
+	vector can be used to improve the numerical properties of the
+	Jacobian matrix (called H_Partials).
+
+	Using a single-sided difference method, each control is
+	independently perturbed and the change in each output of
+	interest is calculated, forming a Jacobian matrix H (variable
+	name is H_Partials):
+
+			dY = H dU
+
+
+	The columns of H correspond to the control effect; the rows of
+	H correspond to the outputs affected.
+
+	We wish to find dU such that for U = U0 + dU,
+	
+			Y = Y0 + dY = 0
+			or dY = -Y0
+
+	One solution is dU = inv(H)*(-Y0); however, inverting H
+	directly is not numerically sound, since it may be singular
+	(especially if one of the controls is on a limit, or the
+	problem is poorly posed).  An alternative is to either weight
+	the elements of dU to make them more normalized; another is to
+	multiply both sides by the transpose of H and invert the
+	resulting [H' H].  This routine does both:
+
+                        -Y0  =      H dU
+		     W (-Y0) =    W H dU	premultiply by W
+		  H' W (-Y0) = H' W H dU        premultiply by H'
+
+              dU = [inv(H' W H)][ H' W (-Y0)]   Solve for dU
+
+	As a further refinement, dU is limited to a smallish magnitude
+	so that Y approaches 0 in small steps (to avoid an overshoot
+	if the problem is inherently non-linear).
+
+	Lastly, this routine can be easily fooled by "local minima",
+	or depressions in the solution space that don't lead to a Y =
+	0 solution.  The only advice we can offer is to "go somewheres
+	else and try again"; often approaching a trim solution from a
+	different (non-trimmed) starting point will prove beneficial.
+
+
+----------------------------------------------------------------------------
+
+	MODULE STATUS:	developmental
+
+----------------------------------------------------------------------------
+
+	GENEALOGY:	Created from old CASTLE SHELL$TRIM.PAS
+			on 6 FEB 95, which was based upon an Ames
+			CASPRE routine called BQUIET.
+
+----------------------------------------------------------------------------
+
+	DESIGNED BY:	E. B. Jackson
+
+	CODED BY:	same
+
+	MAINTAINED BY:	same
+
+----------------------------------------------------------------------------
+
+	MODIFICATION HISTORY:
+
+	DATE	PURPOSE						BY
+
+	950307	Modified to make use of ls_get_sym_val and ls_put_sym_val
+		routines.					EBJ
+	950329	Fixed bug in making use of more than 3 controls;
+		removed call by ls_trim_get_set() to ls_trim_init(). EBJ
+
+	CURRENT RCS HEADER:
+
+$Header$
+$Log$
+Revision 1.1  1999/04/05 21:32:45  curt
+Initial revision
+
+ * Revision 1.9  1995/03/29  16:09:56  bjax
+ * Fixed bug in having more than three trim controls; removed unnecessary
+ * call to ls_trim_init in ls_trim_get_set. EBJ
+ *
+ * Revision 1.8  1995/03/16  12:28:40  bjax
+ * Fixed problem where ls_trim() returns non-zero if
+ * symbols are not loaded - implies vehicle trimmed when
+ * actually no trim attempt is made. This results in storing of non-
+ * trimmed initial conditions in sims without defined trim controls.
+ *
+ * Revision 1.7  1995/03/15  12:17:12  bjax
+ * Added flag marker line to ls_trim_put_set() routine output.
+ *
+ * Revision 1.6  1995/03/08  11:49:07  bjax
+ * Minor improvements to ls_trim_get_set; deleted weighting parameter
+ * for output definition; added comment lines to settings file output.
+ *
+ * Revision 1.5  1995/03/07  22:38:04  bjax
+ * Removed ls_generic.h; this version relies entirely on symbol table routines to
+ * set and get variable values. Added additional fields to Control record structure;
+ * created Output record with appropriate fields. Added ls_trim_put_set() and
+ * ls_trim_get_set() routines. Heavily modified initialization routine; most of this
+ * logic now resides in ls_trim_get_set(). Renamed all routines so that they being
+ * with "ls_trim_" to avoid conflicts.
+ *  EBJ
+ *
+ * Revision 1.4  1995/03/07  13:04:16  bjax
+ * Configured to use ls_get_sym_val() and ls_set_sym_val().
+ *
+ * Revision 1.3  1995/03/03  01:59:53  bjax
+ * Moved definition of SYMBOL_NAME and SYMBOL_TYPE to ls_sym.h
+ * and removed from this module. EBJ
+ *
+ * Revision 1.2  1995/02/27  19:53:41  bjax
+ * Moved symbol routines to ls_sym.c to declutter this file. EBJ
+ *
+ * Revision 1.1  1995/02/27  18:14:10  bjax
+ * Initial revision
+ *
+
+----------------------------------------------------------------------------
+
+	REFERENCES:
+
+----------------------------------------------------------------------------
+
+	CALLED BY:
+
+----------------------------------------------------------------------------
+
+	CALLS TO:
+
+----------------------------------------------------------------------------
+
+	INPUTS:
+
+----------------------------------------------------------------------------
+
+	OUTPUTS:
+
+--------------------------------------------------------------------------*/
+
+static char rcsid[] = "$Id$";
+
+#ifdef __SUNPRO_CC
+#  define _REENTRANT
+#endif
+
+#include 
+#include "ls_constants.h"
+#include "ls_types.h"
+#include "ls_sym.h"
+#include "ls_matrix.h"
+#include "ls_interface.h"
+
+
+#ifndef TRUE
+#define FALSE  0
+#define TRUE  !FALSE
+#endif
+
+#define MAX_NUMBER_OF_CONTROLS 10
+#define MAX_NUMBER_OF_OUTPUTS 10
+#define STEP_LIMIT 0.01
+#define NIL_POINTER 0L
+
+#define FACILITY_NAME_STRING "trim"
+#define CURRENT_VERSION 10
+
+
+typedef struct
+{
+    symbol_rec	Symbol;
+    double	Min_Val, Max_Val, Curr_Val, Authority;
+    double	Percent, Requested_Percent, Pert_Size;
+    int		Ineffective, At_Limit;
+} control_rec;
+
+typedef struct
+{
+    symbol_rec	Symbol;
+    double	Curr_Val, Weighting, Trim_Criteria;
+    int		Uncontrollable;
+} output_rec;
+
+
+static	int		Symbols_loaded = 0;
+static  int 		Index;
+static  int 		Trim_Cycles;
+static  int 		First;
+static  int 		Trimmed;
+static	double		Gain;
+
+static  int		Number_of_Controls;
+static	int		Number_of_Outputs;
+static  control_rec	Controls[ MAX_NUMBER_OF_CONTROLS ];
+static	output_rec	Outputs[ MAX_NUMBER_OF_OUTPUTS ];
+
+static  double		**H_Partials;
+
+static	double		Baseline_Output[ MAX_NUMBER_OF_OUTPUTS ];
+static	double		Saved_Control, Saved_Control_Percent;
+
+static  double		Cost, Previous_Cost;
+
+
+
+
+int ls_trim_init()
+/*  Initialize partials matrix */
+{
+    int i, error;
+    int result;
+
+    Index = -1;
+    Trim_Cycles = 0;
+    Gain = 1;
+    First = 1;
+    Previous_Cost = 0.0;
+    Trimmed = 0;
+
+    for (i=0;i= 1.0)
+		{
+		    Controls[i].Requested_Percent = 1.0;
+		    Controls[i].At_Limit = 1;
+		}
+	    Controls[i].Curr_Val = Controls[i].Min_Val +
+		(Controls[i].Max_Val - Controls[i].Min_Val) *
+		Controls[i].Requested_Percent;
+	}
+}
+
+void ls_trim_put_controls()
+/* Put current control requests out to controls themselves */
+{
+    int i;
+
+    for (i=0;i Outputs[i].Trim_Criteria) trimmed = 0;
+    return trimmed;
+}
+
+void ls_trim_calc_h_column()
+{
+    int i;
+    double delta_control, delta_output;
+
+    delta_control = (Controls[Index].Curr_Val - Saved_Control)/Controls[Index].Authority;
+
+    for(i=0;i EPS) Controls[j].Ineffective = 0;
+	}
+
+    /* Identify uncontrollable outputs */
+
+    for (j=0;j EPS) Outputs[j].Uncontrollable = 0;
+	}
+
+    /* Calculate well-conditioned partials matrix [ H' W H ] */
+
+    h_trans_w_h = nr_matrix(1, Number_of_Controls, 1, Number_of_Controls);
+    if (h_trans_w_h == 0)
+	{
+	    fprintf(stderr, "Memory error in ls_trim().\n");
+	    exit(1);
+	}
+    for (l=1;l<=Number_of_Controls;l++)
+	for (j=1;j<=Number_of_Controls;j++)
+	    {
+		h_trans_w_h[l][j] = 0.0;
+		for (i=1;i<=Number_of_Outputs;i++)
+		    h_trans_w_h[l][j] +=
+			H_Partials[i][l]*H_Partials[i][j]*Outputs[i-1].Weighting;
+	    }
+
+    /* Invert the partials array  [ inv( H' W H ) ]; note: h_trans_w_h is replaced
+       with its inverse during this function call */
+
+    singular = nr_gaussj( h_trans_w_h, Number_of_Controls, 0, 0 );
+
+    if (singular) /* Can't invert successfully */
+	{
+	    nr_free_matrix( h_trans_w_h, 1, Number_of_Controls,
+			                 1, Number_of_Controls );
+	    fprintf(stderr, "Singular matrix in ls_trim().\n");
+	    return;
+	}
+
+    /* Form right hand side of equality: temp = [ H' W (-Y) ] */
+
+    for(i=0;i= Number_of_Controls)
+			    {
+				Baseline = TRUE;
+				Index = -1;
+				ls_trim_do_step();
+			    }
+			else
+			    { /* Save the current value & pert next control */
+				Baseline = FALSE;
+				Saved_Control = Controls[Index].Curr_Val;
+				Saved_Control_Percent = Controls[Index].Percent;
+
+				if (Controls[Index].Percent < 
+				    (1.0 - Controls[Index].Pert_Size) )
+				    {
+					Controls[Index].Requested_Percent =
+					    Controls[Index].Percent +
+					    Controls[Index].Pert_Size ;
+				    }
+				else
+				    {
+					Controls[Index].Requested_Percent =
+					    Controls[Index].Percent -
+					    Controls[Index].Pert_Size;
+				    }
+			    }
+			ls_trim_move_controls();
+			ls_trim_put_controls();
+			ls_loop( 0.0, -1 );
+			Trim_Cycles++;
+		    }
+	    }
+
+	nr_free_matrix( H_Partials, 1, Number_of_Controls, 1, Number_of_Controls );
+    }
+
+    if (!Trimmed)  fprintf(stderr, "Trim unsuccessful.\n");
+    return Trimmed;
+
+}
+
+
+char *ls_trim_get_set(char *buffer, char *eob)
+/* This routine parses the settings file for "trim" entries. */
+{
+
+    static char *fac_name = FACILITY_NAME_STRING;
+    char *bufptr, **lasts, *nullptr, null = '\0';
+    char line[256];
+    int n, ver, i, error, abrt;
+    enum {controls_header, controls, outputs_header, outputs, done} looking_for;
+
+    nullptr = &null;
+    lasts = &nullptr;
+    abrt = 0;
+    looking_for = controls_header;
+
+
+    n = sscanf(buffer, "%s", line);
+    if (n == 0) return 0L;
+    if (strncasecmp( fac_name, line, strlen(fac_name) )) return 0L;
+
+    bufptr = strtok_r( buffer+strlen(fac_name)+1, "\n", lasts);
+    if (bufptr == 0) return 0L;
+
+    sscanf( bufptr, "%d", &ver );
+    if (ver != CURRENT_VERSION) return 0L;
+
+    while( !abrt && (eob > bufptr))
+      {
+	bufptr = strtok_r( 0L, "\n", lasts );
+	if (bufptr == 0) return 0L;
+	if (strncasecmp( bufptr, "end", 3) == 0) break;
+
+	sscanf( bufptr, "%s", line );
+	if (line[0] != '#') /* ignore comments */
+	    {
+		switch (looking_for)
+		    {
+		    case controls_header:
+			{
+			    if (strncasecmp( line, "controls", 8) == 0) 
+				{
+				    n = sscanf( bufptr, "%s%d", line, &Number_of_Controls );
+				    if (n != 2) abrt = 1;
+				    looking_for = controls;
+				    i = 0;
+				}
+			    break;
+			}
+		    case controls:
+			{
+			    n = sscanf( bufptr, "%s%s%le%le%le", 
+					Controls[i].Symbol.Mod_Name,
+					Controls[i].Symbol.Par_Name,
+					&Controls[i].Min_Val,
+					&Controls[i].Max_Val,
+					&Controls[i].Pert_Size); 
+			    if (n != 5) abrt = 1;
+			    Controls[i].Symbol.Addr = NIL_POINTER;
+			    i++;
+			    if (i >= Number_of_Controls) looking_for = outputs_header;
+			    break;
+			}
+		    case outputs_header:
+			{
+			    if (strncasecmp( line, "outputs", 7) == 0) 
+				{
+				    n = sscanf( bufptr, "%s%d", line, &Number_of_Outputs );
+				    if (n != 2) abrt = 1;
+				    looking_for = outputs;
+				    i = 0;
+				}
+			    break;
+			}
+		    case outputs:
+			{
+			    n = sscanf( bufptr, "%s%s%le", 
+					Outputs[i].Symbol.Mod_Name,
+					Outputs[i].Symbol.Par_Name,
+					&Outputs[i].Trim_Criteria );
+			    if (n != 3) abrt = 1;
+			    Outputs[i].Symbol.Addr = NIL_POINTER;
+			    i++;
+			    if (i >= Number_of_Outputs) looking_for = done;
+			}  
+		    case done:
+			{
+			    break;
+			}
+		    }
+
+	    }
+      }
+
+    if ((!abrt) && 
+	(Number_of_Controls > 0) && 
+	(Number_of_Outputs == Number_of_Controls))
+	{
+	    Symbols_loaded = 1;
+
+	    for(i=0;i
+#include 
+
+main() {
+  double x;
+
+  x = sqrt(-1);
+  
+  if ( errno == EDOM ) {
+     printf("domain error\n");
+  }
+
+  printf("x = %.2f\n", x);
+
+  if ( x < 0 ) {
+	printf ("x < 0\n");
+  }
+  if ( x > 0 ) {
+	printf ("x > 0\n");
+  }
+  if ( x > -9999.0 ) {
+	printf ("x > 0\n");
+  }
+}
diff --git a/Simulator/Main/options.cxx b/Simulator/Main/options.cxx
index 0d4db31de..230f9cb77 100644
--- a/Simulator/Main/options.cxx
+++ b/Simulator/Main/options.cxx
@@ -642,6 +642,9 @@ fgOPTIONS::~fgOPTIONS( void ) {
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:47  curt
+// Initial revision
+//
 // Revision 1.43  1999/03/22 23:47:55  curt
 // FOV set properly when panel activated.
 //
diff --git a/Simulator/Main/options.hxx b/Simulator/Main/options.hxx
index ece666757..25e7307ef 100644
--- a/Simulator/Main/options.hxx
+++ b/Simulator/Main/options.hxx
@@ -245,6 +245,9 @@ extern fgOPTIONS current_options;
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:46  curt
+// Initial revision
+//
 // Revision 1.30  1999/03/11 23:09:51  curt
 // When "Help" is selected from the menu check to see if netscape is running.
 // If so, command it to go to the flight gear user guide url.  Otherwise
diff --git a/Simulator/Main/runfgfs.in b/Simulator/Main/runfgfs.in
index 6787f0179..7492f499b 100755
--- a/Simulator/Main/runfgfs.in
+++ b/Simulator/Main/runfgfs.in
@@ -89,6 +89,9 @@ exec("$savepath/$savefile --fg-root=$fg_root @ARGV");
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.1  1999/04/05 21:32:46  curt
+# Initial revision
+#
 # Revision 1.2  1998/08/25 16:59:10  curt
 # Directory reshuffling.
 #
diff --git a/Simulator/Main/splash.cxx b/Simulator/Main/splash.cxx
index 9322aaf97..49d4e1c8a 100644
--- a/Simulator/Main/splash.cxx
+++ b/Simulator/Main/splash.cxx
@@ -155,6 +155,9 @@ void fgSplashUpdate ( double progress ) {
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:47  curt
+// Initial revision
+//
 // Revision 1.10  1999/03/08 21:56:40  curt
 // Added panel changes sent in by Friedemann.
 // Added a splash screen randomization since we have several nice splash screens.
diff --git a/Simulator/Main/splash.hxx b/Simulator/Main/splash.hxx
index 1610dc37a..cd6a115e4 100644
--- a/Simulator/Main/splash.hxx
+++ b/Simulator/Main/splash.hxx
@@ -43,6 +43,9 @@ void fgSplashUpdate ( double progress );
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:47  curt
+// Initial revision
+//
 // Revision 1.1  1998/07/06 02:42:37  curt
 // Initial revision.
 //
diff --git a/Simulator/Main/ttest.cxx b/Simulator/Main/ttest.cxx
new file mode 100644
index 000000000..ff4ed676f
--- /dev/null
+++ b/Simulator/Main/ttest.cxx
@@ -0,0 +1,93 @@
+#include 
+#include 
+
+main() {
+    MAT3mat R_Phi, R_Theta, R_Psi, R_Lat, R_Lon, T_view;
+    MAT3mat TMP, AIRCRAFT, WORLD, EYE_TO_WORLD, WORLD_TO_EYE;
+    MAT3hvec vec, eye, vec1;
+
+    double FG_Phi = 0.00;
+    double FG_Theta = 0.00;
+    double FG_Psi = 0.00;
+    // double FG_Latitude = 33.3528917 * DEG_TO_RAD;
+    double FG_Latitude = 0.0;
+    // double FG_Longitude = -110.6642444 * DEG_TO_RAD;
+    double FG_Longitude = 90.0 * DEG_TO_RAD;
+    // double view_pos[] = {2936.3222, 1736.9243, 3689.5359, 1.0};
+    double view_pos[] = {0.0, 0.0, 0.0, 1.0};
+
+    // Roll Matrix
+    MAT3_SET_HVEC(vec, 0.0, 0.0, -1.0, 1.0);
+    MAT3rotate(R_Phi, vec, FG_Phi);
+    printf("Roll matrix (Phi)\n");
+    MAT3print(R_Phi, stdout);
+
+    // Pitch Matrix
+    MAT3_SET_HVEC(vec, 1.0, 0.0, 0.0, 1.0);
+    MAT3rotate(R_Theta, vec, FG_Theta);
+    printf("\nPitch matrix (Theta)\n");
+    MAT3print(R_Theta, stdout);
+
+    // Yaw Matrix
+    MAT3_SET_HVEC(vec, 0.0, -1.0, 0.0, 1.0);
+    MAT3rotate(R_Psi, vec, FG_PI + FG_Psi);
+    printf("\nYaw matrix (Psi)\n");
+    MAT3print(R_Psi, stdout);
+
+    // Latitude
+    MAT3_SET_HVEC(vec, 1.0, 0.0, 0.0, 1.0);
+    // R_Lat = rotate about X axis
+    MAT3rotate(R_Lat, vec, FG_Latitude);
+    printf("\nLatitude matrix\n");
+    MAT3print(R_Lat, stdout);
+
+    // Longitude
+    MAT3_SET_HVEC(vec, 0.0, 0.0, 1.0, 1.0);
+    // R_Lon = rotate about Z axis
+    MAT3rotate(R_Lon, vec, FG_Longitude - FG_PI_2 );
+    printf("\nLongitude matrix\n");
+    MAT3print(R_Lon, stdout);
+
+    // View position in scenery centered coordinates
+    MAT3translate(T_view, view_pos);
+    printf("\nTranslation matrix\n");
+    MAT3print(T_view, stdout);
+
+    // aircraft roll/pitch/yaw
+    MAT3mult(TMP, R_Phi, R_Theta);
+    MAT3mult(AIRCRAFT, TMP, R_Psi);
+    printf("\naircraft roll pitch yaw\n");
+    MAT3print(AIRCRAFT, stdout);
+
+    // lon/lat
+    MAT3mult(WORLD, R_Lat, R_Lon);
+    printf("\nworld\n");
+    MAT3print(WORLD, stdout);
+
+    MAT3mult(EYE_TO_WORLD, AIRCRAFT, WORLD);
+    MAT3mult(EYE_TO_WORLD, EYE_TO_WORLD, T_view);
+    printf("\nEye to world\n");
+    MAT3print(EYE_TO_WORLD, stdout);
+
+    MAT3invert(WORLD_TO_EYE, EYE_TO_WORLD);
+    printf("\nWorld to eye\n");
+    MAT3print(WORLD_TO_EYE, stdout);
+
+    MAT3_SET_HVEC(eye, 0.0, 0.0, 0.0, 1.0);
+    MAT3mult_vec(vec, eye, EYE_TO_WORLD);
+    printf("\neye -> world = %.2f %.2f %.2f\n", vec[0], vec[1], vec[2]);
+
+    MAT3_SET_HVEC(vec1, 0.0, 6378138.12, 0.0, 1.0);
+    MAT3mult_vec(vec, vec1, EYE_TO_WORLD);
+    printf( "\n+y (eye) -> +y (world) = %.2f %.2f %.2f\n", 
+	    vec[0], vec[1], vec[2]);
+
+    MAT3mult_vec(vec1, vec, WORLD_TO_EYE);
+    printf( "\n+y (world) -> +y (eye) = %.2f %.2f %.2f\n", 
+	    vec1[0], vec1[1], vec1[2]);
+}
+
+
+
+
+
diff --git a/Simulator/Main/views.cxx b/Simulator/Main/views.cxx
index 57c059a3d..b4595c588 100644
--- a/Simulator/Main/views.cxx
+++ b/Simulator/Main/views.cxx
@@ -1010,6 +1010,9 @@ FGView::~FGView( void ) {
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:47  curt
+// Initial revision
+//
 // Revision 1.35  1999/04/03 04:21:04  curt
 // Integration of Steve's plib conglomeration.
 // Optimizations (tm) by Norman Vine.
diff --git a/Simulator/Main/views.hxx b/Simulator/Main/views.hxx
index 1de311f69..9883bcbfd 100644
--- a/Simulator/Main/views.hxx
+++ b/Simulator/Main/views.hxx
@@ -254,6 +254,9 @@ extern FGView current_view;
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:47  curt
+// Initial revision
+//
 // Revision 1.23  1999/04/03 04:21:06  curt
 // Integration of Steve's plib conglomeration.
 // Optimizations (tm) by Norman Vine.
diff --git a/Simulator/Simulator/Makefile.am b/Simulator/Makefile.am
similarity index 100%
rename from Simulator/Simulator/Makefile.am
rename to Simulator/Makefile.am
diff --git a/Simulator/Objects/fragment.cxx b/Simulator/Objects/fragment.cxx
index 9af71d78f..2641015b4 100644
--- a/Simulator/Objects/fragment.cxx
+++ b/Simulator/Objects/fragment.cxx
@@ -323,6 +323,9 @@ int fgFRAGMENT::intersect( const Point3D& end0,
 }
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:49  curt
+// Initial revision
+//
 // Revision 1.7  1999/02/26 22:09:56  curt
 // Added initial support for native SGI compilers.
 //
diff --git a/Simulator/Objects/fragment.hxx b/Simulator/Objects/fragment.hxx
index 86b718e83..a44bd843f 100644
--- a/Simulator/Objects/fragment.hxx
+++ b/Simulator/Objects/fragment.hxx
@@ -172,6 +172,9 @@ operator == ( const fgFRAGMENT & lhs, const fgFRAGMENT & rhs ) {
 
 
 // $Log$
+// Revision 1.1  1999/04/05 21:32:49  curt
+// Initial revision
+//
 // Revision 1.12  1999/04/05 02:14:21  curt
 // Moved max node per tile definition to fg_constants.h
 //
diff --git a/Simulator/Objects/material.cxx b/Simulator/Objects/material.cxx
deleted file mode 100644
index 6500edc85..000000000
--- a/Simulator/Objects/material.cxx
+++ /dev/null
@@ -1,559 +0,0 @@
-// material.cxx -- class to handle material properties
-//
-// Written by Curtis Olson, started May 1998.
-//
-// Copyright (C) 1998  Curtis L. Olson  - curt@me.umn.edu
-//
-// 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.
-//
-// $Id$
-// (Log is kept at end of this file)
-
-
-#ifdef HAVE_CONFIG_H
-#  include 
-#endif
-
-#ifdef HAVE_WINDOWS_H
-#  include 
-#endif
-
-#include 
-#include 
-
-#include 
-
-#include 
-#include STL_STRING
-
-#include 
-#include 
-#include 
-#include
-#include - -#include "material.hxx" -#include "fragment.hxx" -#include "texload.h" - -FG_USING_STD(string); - - -// global material management class -fgMATERIAL_MGR material_mgr; - - -// Constructor -fgMATERIAL::fgMATERIAL ( void ) - : texture_name(""), - alpha(0) - // , list_size(0) -{ - ambient[0] = ambient[1] = ambient[2] = ambient[3] = 0.0; - diffuse[0] = diffuse[1] = diffuse[2] = diffuse[3] = 0.0; - specular[0] = specular[1] = specular[2] = specular[3] = 0.0; - emissive[0] = emissive[1] = emissive[2] = emissive[3] = 0.0; -} - -/* -int -fgMATERIAL::append_sort_list( fgFRAGMENT *object ) -{ - if ( list_size < FG_MAX_MATERIAL_FRAGS ) { - list[ list_size++ ] = object; - return 1; - } else { - return 0; - } -} -*/ - -istream& -operator >> ( istream& in, fgMATERIAL& m ) -{ - string token; - - for (;;) { - in >> token; - if ( token == "texture" ) - { - in >> token >> m.texture_name; - } - else if ( token == "ambient" ) - { - in >> token >> m.ambient[0] >> m.ambient[1] - >> m.ambient[2] >> m.ambient[3]; - } - else if ( token == "diffuse" ) - { - in >> token >> m.diffuse[0] >> m.diffuse[1] - >> m.diffuse[2] >> m.diffuse[3]; - } - else if ( token == "specular" ) - { - in >> token >> m.specular[0] >> m.specular[1] - >> m.specular[2] >> m.specular[3]; - } - else if ( token == "emissive" ) - { - in >> token >> m.emissive[0] >> m.emissive[1] - >> m.emissive[2] >> m.emissive[3]; - } - else if ( token == "alpha" ) - { - in >> token >> token; - if ( token == "yes" ) - m.alpha = 1; - else if ( token == "no" ) - m.alpha = 0; - else - { - FG_LOG( FG_TERRAIN, FG_INFO, "Bad alpha value " << token ); - } - } - else if ( token[0] == '}' ) - { - break; - } - } - - return in; -} - -void -fgMATERIAL::load_texture() -{ - GLubyte *texbuf; - int width, height; - - // create the texture object and bind it -#ifdef GL_VERSION_1_1 - xglGenTextures(1, &texture_id ); - xglBindTexture(GL_TEXTURE_2D, texture_id ); -#elif GL_EXT_texture_object - xglGenTexturesEXT(1, &texture_id ); - xglBindTextureEXT(GL_TEXTURE_2D, texture_id ); -#else -# error port me -#endif - - // set the texture parameters for this texture - xglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ) ; - xglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ) ; - xglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, - GL_LINEAR ); - // xglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, - // GL_NEAREST_MIPMAP_NEAREST ); - xglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, - /* GL_LINEAR */ - /* GL_NEAREST_MIPMAP_LINEAR */ - GL_LINEAR_MIPMAP_LINEAR ) ; - - /* load in the texture data */ - string tpath = current_options.get_fg_root() + "/Textures/" + - texture_name + ".rgb"; - string fg_tpath = tpath + ".gz"; - - if ( alpha == 0 ) { - // load rgb texture - - // Try uncompressed - if ( (texbuf = - read_rgb_texture(tpath.c_str(), &width, &height)) == - NULL ) - { - // Try compressed - if ( (texbuf = - read_rgb_texture(fg_tpath.c_str(), &width, &height)) - == NULL ) - { - FG_LOG( FG_GENERAL, FG_ALERT, - "Error in loading texture " << tpath ); - exit(-1); - } - } - - /* xglTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, - GL_RGB, GL_UNSIGNED_BYTE, texbuf); */ - - gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGB, width, height, - GL_RGB, GL_UNSIGNED_BYTE, texbuf ); - } else if ( alpha == 1 ) { - // load rgba (alpha) texture - - // Try uncompressed - if ( (texbuf = - read_alpha_texture(tpath.c_str(), &width, &height)) - == NULL ) - { - // Try compressed - if ((texbuf = - read_alpha_texture(fg_tpath.c_str(), &width, &height)) - == NULL ) - { - FG_LOG( FG_GENERAL, FG_ALERT, - "Error in loading texture " << tpath ); - exit(-1); - } - } - - xglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, - GL_RGBA, GL_UNSIGNED_BYTE, texbuf); - } -} - - -// Destructor -fgMATERIAL::~fgMATERIAL ( void ) { -} - - -// Constructor -fgMATERIAL_MGR::fgMATERIAL_MGR ( void ) { - textures_loaded = false; -} - - -void -fgMATERIAL::render_fragments() -{ - int tris_rendered = current_view.get_tris_rendered(); - - // cout << "rendering " + texture_name + " = " << list_size << "\n"; - - if ( empty() ) - return; - - if ( current_options.get_textures() ) - { -#ifdef GL_VERSION_1_1 - xglBindTexture(GL_TEXTURE_2D, texture_id); -#elif GL_EXT_texture_object - xglBindTextureEXT(GL_TEXTURE_2D, texture_id); -#else -# error port me -#endif - } else { - xglMaterialfv (GL_FRONT, GL_AMBIENT, ambient); - xglMaterialfv (GL_FRONT, GL_DIFFUSE, diffuse); - } - - fgTILE* last_tile_ptr = NULL; - frag_list_iterator current = list.begin(); - frag_list_iterator last = list.end(); - - for ( ; current != last; ++current ) { - fgFRAGMENT* frag_ptr = *current; - tris_rendered += frag_ptr->num_faces(); - if ( frag_ptr->tile_ptr != last_tile_ptr ) - { - // new tile, new translate - last_tile_ptr = frag_ptr->tile_ptr; - xglLoadMatrixd( frag_ptr->tile_ptr->model_view ); - } - - // Woohoo!!! We finally get to draw something! - // printf(" display_list = %d\n", frag_ptr->display_list); - xglCallList( frag_ptr->display_list ); - } - - current_view.set_tris_rendered( tris_rendered ); -} - - -// Load a library of material properties -int -fgMATERIAL_MGR::load_lib ( void ) -{ - string material_name; - - // build the path name to the material db - string mpath = current_options.get_fg_root() + "/materials"; - fg_gzifstream in( mpath ); - if ( ! in ) { - FG_LOG( FG_GENERAL, FG_ALERT, "Cannot open file: " << mpath ); - exit(-1); - } - - while ( ! in.eof() ) { - // printf("%s", line); - - // strip leading white space and comments - in >> skipcomment; - - // set to zero to prevent its value accidently being '{' - // after a failed >> operation. - char token = 0; - - in >> material_name >> token; - - if ( token == '{' ) { - FG_LOG( FG_TERRAIN, FG_INFO, - " Loading material " << material_name ); - fgMATERIAL m; - in >> m; - - if ( current_options.get_textures() ) { - m.load_texture(); - } - - material_mgr.material_map[material_name] = m; - } - } - - if ( current_options.get_textures() ) { - textures_loaded = true; - } - - return(1); -} - - -// Initialize the transient list of fragments for each material property -void -fgMATERIAL_MGR::init_transient_material_lists( void ) -{ - iterator last = end(); - for ( iterator it = begin(); it != last; ++it ) - { - (*it).second.init_sort_list(); - } -} - - -bool -fgMATERIAL_MGR::find( const string& material, fgMATERIAL*& mtl_ptr ) -{ - iterator it = material_map.find( material ); - if ( it != end() ) - { - mtl_ptr = &((*it).second); - return true; - } - - return false; -} - - -// Destructor -fgMATERIAL_MGR::~fgMATERIAL_MGR ( void ) { -} - - -void -fgMATERIAL_MGR::render_fragments() -{ - current_view.set_tris_rendered( 0 ); - - iterator last = end(); - for ( iterator current = begin(); current != last; ++current ) - (*current).second.render_fragments(); -} - - -// $Log$ -// Revision 1.14 1999/03/02 01:03:24 curt -// Tweaks for building with native SGI compilers. -// -// Revision 1.13 1999/02/26 22:09:58 curt -// Added initial support for native SGI compilers. -// -// Revision 1.12 1998/12/09 18:50:30 curt -// Converted "class fgVIEW" to "class FGView" and updated to make data -// members private and make required accessor functions. -// -// Revision 1.11 1998/11/07 19:07:12 curt -// Enable release builds using the --without-logging option to the configure -// script. Also a couple log message cleanups, plus some C to C++ comment -// conversion. -// -// Revision 1.10 1998/11/06 21:18:17 curt -// Converted to new logstream debugging facility. This allows release -// builds with no messages at all (and no performance impact) by using -// the -DFG_NDEBUG flag. -// -// Revision 1.9 1998/11/06 14:47:05 curt -// Changes to track Bernie's updates to fgstream. -// -// Revision 1.8 1998/10/12 23:49:17 curt -// Changes from NHV to make the code more dynamic with fewer hard coded limits. -// -// Revision 1.7 1998/09/17 18:35:52 curt -// Tweaks and optimizations by Norman Vine. -// -// Revision 1.6 1998/09/15 01:35:05 curt -// cleaned up my fragment.num_faces hack :-) to use the STL (no need in -// duplicating work.) -// Tweaked fgTileMgrRender() do not calc tile matrix unless necessary. -// removed some unneeded stuff from fgTileMgrCurElev() -// -// Revision 1.5 1998/09/10 19:07:11 curt -// /Simulator/Objects/fragment.hxx -// Nested fgFACE inside fgFRAGMENT since its not used anywhere else. -// -// ./Simulator/Objects/material.cxx -// ./Simulator/Objects/material.hxx -// Made fgMATERIAL and fgMATERIAL_MGR bona fide classes with private -// data members - that should keep the rabble happy :) -// -// ./Simulator/Scenery/tilemgr.cxx -// In viewable() delay evaluation of eye[0] and eye[1] in until they're -// actually needed. -// Change to fgTileMgrRender() to call fgMATERIAL_MGR::render_fragments() -// method. -// -// ./Include/fg_stl_config.h -// ./Include/auto_ptr.hxx -// Added support for g++ 2.7. -// Further changes to other files are forthcoming. -// -// Brief summary of changes required for g++ 2.7. -// operator->() not supported by iterators: use (*i).x instead of i->x -// default template arguments not supported, -// doesn't have mem_fun_ref() needed by callbacks. -// some std include files have different names. -// template member functions not supported. -// -// Revision 1.4 1998/09/01 19:03:08 curt -// Changes contributed by Bernie Bright -// - The new classes in libmisc.tgz define a stream interface into zlib. -// I've put these in a new directory, Lib/Misc. Feel free to rename it -// to something more appropriate. However you'll have to change the -// include directives in all the other files. Additionally you'll have -// add the library to Lib/Makefile.am and Simulator/Main/Makefile.am. -// -// The StopWatch class in Lib/Misc requires a HAVE_GETRUSAGE autoconf -// test so I've included the required changes in config.tgz. -// -// There are a fair few changes to Simulator/Objects as I've moved -// things around. Loading tiles is quicker but thats not where the delay -// is. Tile loading takes a few tenths of a second per file on a P200 -// but it seems to be the post-processing that leads to a noticeable -// blip in framerate. I suppose its time to start profiling to see where -// the delays are. -// -// I've included a brief description of each archives contents. -// -// Lib/Misc/ -// zfstream.cxx -// zfstream.hxx -// C++ stream interface into zlib. -// Taken from zlib-1.1.3/contrib/iostream/. -// Minor mods for STL compatibility. -// There's no copyright associated with these so I assume they're -// covered by zlib's. -// -// fgstream.cxx -// fgstream.hxx -// FlightGear input stream using gz_ifstream. Tries to open the -// given filename. If that fails then filename is examined and a -// ".gz" suffix is removed or appended and that file is opened. -// -// stopwatch.hxx -// A simple timer for benchmarking. Not used in production code. -// Taken from the Blitz++ project. Covered by GPL. -// -// strutils.cxx -// strutils.hxx -// Some simple string manipulation routines. -// -// Simulator/Airports/ -// Load airports database using fgstream. -// Changed fgAIRPORTS to use set<> instead of map<>. -// Added bool fgAIRPORTS::search() as a neater way doing the lookup. -// Returns true if found. -// -// Simulator/Astro/ -// Modified fgStarsInit() to load stars database using fgstream. -// -// Simulator/Objects/ -// Modified fgObjLoad() to use fgstream. -// Modified fgMATERIAL_MGR::load_lib() to use fgstream. -// Many changes to fgMATERIAL. -// Some changes to fgFRAGMENT but I forget what! -// -// Revision 1.3 1998/08/27 17:02:09 curt -// Contributions from Bernie Bright -// - use strings for fg_root and airport_id and added methods to return -// them as strings, -// - inlined all access methods, -// - made the parsing functions private methods, -// - deleted some unused functions. -// - propogated some of these changes out a bit further. -// -// Revision 1.2 1998/08/25 20:53:33 curt -// Shuffled $FG_ROOT file layout. -// -// Revision 1.1 1998/08/25 16:51:24 curt -// Moved from ../Scenery -// -// Revision 1.13 1998/08/24 20:11:39 curt -// Tweaks ... -// -// Revision 1.12 1998/08/12 21:41:27 curt -// Need to negate the test for textures so that textures aren't loaded when -// they are disabled rather than visa versa ... :-) -// -// Revision 1.11 1998/08/12 21:13:03 curt -// material.cxx: don't load textures if they are disabled -// obj.cxx: optimizations from Norman Vine -// tile.cxx: minor tweaks -// tile.hxx: addition of num_faces -// tilemgr.cxx: minor tweaks -// -// Revision 1.10 1998/07/24 21:42:06 curt -// material.cxx: whups, double method declaration with no definition. -// obj.cxx: tweaks to avoid errors in SGI's CC. -// tile.cxx: optimizations by Norman Vine. -// tilemgr.cxx: optimizations by Norman Vine. -// -// Revision 1.9 1998/07/13 21:01:57 curt -// Wrote access functions for current fgOPTIONS. -// -// Revision 1.8 1998/07/08 14:47:20 curt -// Fix GL_MODULATE vs. GL_DECAL problem introduced by splash screen. -// polare3d.h renamed to polar3d.hxx -// fg{Cartesian,Polar}Point3d consolodated. -// Added some initial support for calculating local current ground elevation. -// -// Revision 1.7 1998/07/04 00:54:28 curt -// Added automatic mipmap generation. -// -// When rendering fragments, use saved model view matrix from associated tile -// rather than recalculating it with push() translate() pop(). -// -// Revision 1.6 1998/06/27 16:54:59 curt -// Check for GL_VERSION_1_1 or GL_EXT_texture_object to decide whether to use -// "EXT" versions of texture management routines. -// -// Revision 1.5 1998/06/17 21:36:39 curt -// Load and manage multiple textures defined in the Materials library. -// Boost max material fagments for each material property to 800. -// Multiple texture support when rendering. -// -// Revision 1.4 1998/06/12 00:58:04 curt -// Build only static libraries. -// Declare memmove/memset for Sloaris. -// -// Revision 1.3 1998/06/05 22:39:53 curt -// Working on sorting by, and rendering by material properties. -// -// Revision 1.2 1998/06/01 17:56:20 curt -// Incremental additions to material.cxx (not fully functional) -// Tweaked vfc_ratio math to avoid divide by zero. -// -// Revision 1.1 1998/05/30 01:56:45 curt -// Added material.cxx material.hxx -// diff --git a/Simulator/Objects/material.hxx b/Simulator/Objects/material.hxx deleted file mode 100644 index 9e8b1b1d3..000000000 --- a/Simulator/Objects/material.hxx +++ /dev/null @@ -1,320 +0,0 @@ -// material.hxx -- class to handle material properties -// -// Written by Curtis Olson, started May 1998. -// -// Copyright (C) 1998 Curtis L. Olson - curt@me.umn.edu -// -// 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. -// -// $Id$ -// (Log is kept at end of this file) - - -#ifndef _MATERIAL_HXX -#define _MATERIAL_HXX - - -#ifndef __cplusplus -# error This library requires C++ -#endif - -#ifdef HAVE_CONFIG_H -# include -#endif - -#ifdef HAVE_WINDOWS_H -# include -#endif - -#include -#include - -#include // Standard C++ string library -#include // STL associative "array" -#include // STL "array" - -#include "Include/compiler.h" -FG_USING_STD(string); -FG_USING_STD(map); -FG_USING_STD(vector); -FG_USING_STD(less); - -// forward decl. -class fgFRAGMENT; - - -// convenience types -typedef vector < fgFRAGMENT * > frag_list_type; -typedef frag_list_type::iterator frag_list_iterator; -typedef frag_list_type::const_iterator frag_list_const_iterator; - - -// #define FG_MAX_MATERIAL_FRAGS 800 - -// MSVC++ 6.0 kuldge - Need forward declaration of friends. -class fgMATERIAL; -istream& operator >> ( istream& in, fgMATERIAL& m ); - -// Material property class -class fgMATERIAL { - -private: - // OpenGL texture name - GLuint texture_id; - - // file name of texture - string texture_name; - - // alpha texture? - int alpha; - - // material properties - GLfloat ambient[4], diffuse[4], specular[4], emissive[4]; - GLint texture_ptr; - - // transient list of objects with this material type (used for sorting - // by material to reduce GL state changes when rendering the scene - frag_list_type list; - // size_t list_size; - -public: - - // Constructor - fgMATERIAL ( void ); - - int size() const { return list.size(); } - bool empty() const { return list.size() == 0; } - - // Sorting routines - void init_sort_list( void ) { - list.erase( list.begin(), list.end() ); - } - - bool append_sort_list( fgFRAGMENT *object ) { - list.push_back( object ); - return true; - } - - void render_fragments(); - - void load_texture(); - - // Destructor - ~fgMATERIAL ( void ); - - friend istream& operator >> ( istream& in, fgMATERIAL& m ); -}; - - -// Material management class -class fgMATERIAL_MGR { - -public: - - // associative array of materials - typedef map < string, fgMATERIAL, less > container; - typedef container::iterator iterator; - typedef container::const_iterator const_iterator; - - iterator begin() { return material_map.begin(); } - const_iterator begin() const { return material_map.begin(); } - - iterator end() { return material_map.end(); } - const_iterator end() const { return material_map.end(); } - - // Constructor - fgMATERIAL_MGR ( void ); - - // Load a library of material properties - int load_lib ( void ); - - bool get_textures_loaded() { return textures_loaded; } - - // Initialize the transient list of fragments for each material property - void init_transient_material_lists( void ); - - bool find( const string& material, fgMATERIAL*& mtl_ptr ); - - void render_fragments(); - - // Destructor - ~fgMATERIAL_MGR ( void ); - -private: - - // Have textures been loaded - bool textures_loaded; - - container material_map; -}; - - -// global material management class -extern fgMATERIAL_MGR material_mgr; - - -#endif // _MATERIAL_HXX - - -// $Log$ -// Revision 1.6 1999/02/02 20:13:39 curt -// MSVC++ portability changes by Bernie Bright: -// -// Lib/Serial/serial.[ch]xx: Initial Windows support - incomplete. -// Simulator/Astro/stars.cxx: typo? included instead of -// Simulator/Cockpit/hud.cxx: Added Standard headers -// Simulator/Cockpit/panel.cxx: Redefinition of default parameter -// Simulator/Flight/flight.cxx: Replaced cout with FG_LOG. Deleted -// Simulator/Main/fg_init.cxx: -// Simulator/Main/GLUTmain.cxx: -// Simulator/Main/options.hxx: Shuffled dependency -// Simulator/Objects/material.hxx: -// Simulator/Time/timestamp.hxx: VC++ friend kludge -// Simulator/Scenery/tile.[ch]xx: Fixed using std::X declarations -// Simulator/Main/views.hxx: Added a constant -// -// Revision 1.5 1998/10/12 23:49:18 curt -// Changes from NHV to make the code more dynamic with fewer hard coded limits. -// -// Revision 1.4 1998/09/17 18:35:53 curt -// Tweaks and optimizations by Norman Vine. -// -// Revision 1.3 1998/09/10 19:07:12 curt -// /Simulator/Objects/fragment.hxx -// Nested fgFACE inside fgFRAGMENT since its not used anywhere else. -// -// ./Simulator/Objects/material.cxx -// ./Simulator/Objects/material.hxx -// Made fgMATERIAL and fgMATERIAL_MGR bona fide classes with private -// data members - that should keep the rabble happy :) -// -// ./Simulator/Scenery/tilemgr.cxx -// In viewable() delay evaluation of eye[0] and eye[1] in until they're -// actually needed. -// Change to fgTileMgrRender() to call fgMATERIAL_MGR::render_fragments() -// method. -// -// ./Include/fg_stl_config.h -// ./Include/auto_ptr.hxx -// Added support for g++ 2.7. -// Further changes to other files are forthcoming. -// -// Brief summary of changes required for g++ 2.7. -// operator->() not supported by iterators: use (*i).x instead of i->x -// default template arguments not supported, -// doesn't have mem_fun_ref() needed by callbacks. -// some std include files have different names. -// template member functions not supported. -// -// Revision 1.2 1998/09/01 19:03:09 curt -// Changes contributed by Bernie Bright -// - The new classes in libmisc.tgz define a stream interface into zlib. -// I've put these in a new directory, Lib/Misc. Feel free to rename it -// to something more appropriate. However you'll have to change the -// include directives in all the other files. Additionally you'll have -// add the library to Lib/Makefile.am and Simulator/Main/Makefile.am. -// -// The StopWatch class in Lib/Misc requires a HAVE_GETRUSAGE autoconf -// test so I've included the required changes in config.tgz. -// -// There are a fair few changes to Simulator/Objects as I've moved -// things around. Loading tiles is quicker but thats not where the delay -// is. Tile loading takes a few tenths of a second per file on a P200 -// but it seems to be the post-processing that leads to a noticeable -// blip in framerate. I suppose its time to start profiling to see where -// the delays are. -// -// I've included a brief description of each archives contents. -// -// Lib/Misc/ -// zfstream.cxx -// zfstream.hxx -// C++ stream interface into zlib. -// Taken from zlib-1.1.3/contrib/iostream/. -// Minor mods for STL compatibility. -// There's no copyright associated with these so I assume they're -// covered by zlib's. -// -// fgstream.cxx -// fgstream.hxx -// FlightGear input stream using gz_ifstream. Tries to open the -// given filename. If that fails then filename is examined and a -// ".gz" suffix is removed or appended and that file is opened. -// -// stopwatch.hxx -// A simple timer for benchmarking. Not used in production code. -// Taken from the Blitz++ project. Covered by GPL. -// -// strutils.cxx -// strutils.hxx -// Some simple string manipulation routines. -// -// Simulator/Airports/ -// Load airports database using fgstream. -// Changed fgAIRPORTS to use set<> instead of map<>. -// Added bool fgAIRPORTS::search() as a neater way doing the lookup. -// Returns true if found. -// -// Simulator/Astro/ -// Modified fgStarsInit() to load stars database using fgstream. -// -// Simulator/Objects/ -// Modified fgObjLoad() to use fgstream. -// Modified fgMATERIAL_MGR::load_lib() to use fgstream. -// Many changes to fgMATERIAL. -// Some changes to fgFRAGMENT but I forget what! -// -// Revision 1.1 1998/08/25 16:51:24 curt -// Moved from ../Scenery -// -// Revision 1.10 1998/07/24 21:42:06 curt -// material.cxx: whups, double method declaration with no definition. -// obj.cxx: tweaks to avoid errors in SGI's CC. -// tile.cxx: optimizations by Norman Vine. -// tilemgr.cxx: optimizations by Norman Vine. -// -// Revision 1.9 1998/07/06 21:34:33 curt -// Added using namespace std for compilers that support this. -// -// Revision 1.8 1998/06/17 21:36:39 curt -// Load and manage multiple textures defined in the Materials library. -// Boost max material fagments for each material property to 800. -// Multiple texture support when rendering. -// -// Revision 1.7 1998/06/12 00:58:04 curt -// Build only static libraries. -// Declare memmove/memset for Sloaris. -// -// Revision 1.6 1998/06/06 01:09:31 curt -// I goofed on the log message in the last commit ... now fixed. -// -// Revision 1.5 1998/06/06 01:07:17 curt -// Increased per material fragment list size from 100 to 400. -// Now correctly draw viewable fragments in per material order. -// -// Revision 1.4 1998/06/05 22:39:53 curt -// Working on sorting by, and rendering by material properties. -// -// Revision 1.3 1998/06/03 00:47:50 curt -// No .h for STL includes. -// Minor view culling optimizations. -// -// Revision 1.2 1998/06/01 17:56:20 curt -// Incremental additions to material.cxx (not fully functional) -// Tweaked vfc_ratio math to avoid divide by zero. -// -// Revision 1.1 1998/05/30 01:56:45 curt -// Added material.cxx material.hxx -// diff --git a/Simulator/Objects/obj.cxx b/Simulator/Objects/obj.cxx index 56cb1d8fe..b200d8992 100644 --- a/Simulator/Objects/obj.cxx +++ b/Simulator/Objects/obj.cxx @@ -595,6 +595,9 @@ int fgObjLoad( const string& path, fgTILE *t) { // $Log$ +// Revision 1.1 1999/04/05 21:32:49 curt +// Initial revision +// // Revision 1.15 1999/03/31 13:25:58 curt // Removed some debugging output. // diff --git a/Simulator/Objects/obj.hxx b/Simulator/Objects/obj.hxx index c07dd1c26..e233aced7 100644 --- a/Simulator/Objects/obj.hxx +++ b/Simulator/Objects/obj.hxx @@ -54,6 +54,9 @@ int fgObjLoad(const string& path, fgTILE *tile); // $Log$ +// Revision 1.1 1999/04/05 21:32:49 curt +// Initial revision +// // Revision 1.3 1998/10/16 00:54:41 curt // Converted to Point3D class. // diff --git a/Simulator/Objects/texload.c b/Simulator/Objects/texload.c deleted file mode 100644 index e6ebbb137..000000000 --- a/Simulator/Objects/texload.c +++ /dev/null @@ -1,273 +0,0 @@ - -/* texture.c - by David Blythe, SGI */ - -/* texload is a simplistic routine for reading an SGI .rgb image file. */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#ifdef HAVE_WINDOWS_H -# include -#endif - -#include -#include -#include - -#include - -#include "texload.h" - -typedef struct _ImageRec { - unsigned short imagic; - unsigned short type; - unsigned short dim; - unsigned short xsize, ysize, zsize; - unsigned int min, max; - unsigned int wasteBytes; - char name[80]; - unsigned long colorMap; - fgFile file; - unsigned char *tmp; - unsigned long rleEnd; - unsigned int *rowStart; - int *rowSize; -} ImageRec; - -void -rgbtorgb(unsigned char *r,unsigned char *g,unsigned char *b,unsigned char *l,int n) { - while(n--) { - l[0] = r[0]; - l[1] = g[0]; - l[2] = b[0]; - l += 3; r++; g++; b++; - } -} - -static void -ConvertShort(unsigned short *array, unsigned int length) { - unsigned short b1, b2; - unsigned char *ptr; - - ptr = (unsigned char *)array; - while (length--) { - b1 = *ptr++; - b2 = *ptr++; - *array++ = (b1 << 8) | (b2); - } -} - -static void -ConvertUint(unsigned *array, unsigned int length) { - unsigned int b1, b2, b3, b4; - unsigned char *ptr; - - ptr = (unsigned char *)array; - while (length--) { - b1 = *ptr++; - b2 = *ptr++; - b3 = *ptr++; - b4 = *ptr++; - *array++ = (b1 << 24) | (b2 << 16) | (b3 << 8) | (b4); - } -} - -static ImageRec *ImageOpen(const char *fileName) -{ - union { - int testWord; - char testByte[4]; - } endianTest; - - ImageRec *image; - int swapFlag; - int x; - - endianTest.testWord = 1; - if (endianTest.testByte[0] == 1) { - swapFlag = 1; - } else { - swapFlag = 0; - } - - image = (ImageRec *)malloc(sizeof(ImageRec)); - if (image == NULL) { - fprintf(stderr, "Out of memory!\n"); - exit(1); - } - if ((image->file = fgopen(fileName, "rb")) == NULL) { - return NULL; - } - - // fread(image, 1, 12, image->file); - fgread(image->file, image, 12); - - if (swapFlag) { - ConvertShort(&image->imagic, 6); - } - - image->tmp = (unsigned char *)malloc(image->xsize*256); - if (image->tmp == NULL) { - fprintf(stderr, "\nOut of memory!\n"); - exit(1); - } - - if ((image->type & 0xFF00) == 0x0100) { - x = image->ysize * image->zsize * (int) sizeof(unsigned); - image->rowStart = (unsigned *)malloc(x); - image->rowSize = (int *)malloc(x); - if (image->rowStart == NULL || image->rowSize == NULL) { - fprintf(stderr, "\nOut of memory!\n"); - exit(1); - } - image->rleEnd = 512 + (2 * x); - fgseek(image->file, 512, SEEK_SET); - // fread(image->rowStart, 1, x, image->file); - fgread(image->file, image->rowStart, x); - // fread(image->rowSize, 1, x, image->file); - fgread(image->file, image->rowSize, x); - if (swapFlag) { - ConvertUint(image->rowStart, x/(int) sizeof(unsigned)); - ConvertUint((unsigned *)image->rowSize, x/(int) sizeof(int)); - } - } - return image; -} - -static void -ImageClose(ImageRec *image) { - fgclose(image->file); - free(image->tmp); - free(image); -} - -static void -ImageGetRow(ImageRec *image, unsigned char *buf, int y, int z) { - unsigned char *iPtr, *oPtr, pixel; - int count; - - if ((image->type & 0xFF00) == 0x0100) { - fgseek(image->file, (long) image->rowStart[y+z*image->ysize], SEEK_SET); - // fread(image->tmp, 1, (unsigned int)image->rowSize[y+z*image->ysize], - // image->file); - fgread(image->file, image->tmp, - (unsigned int)image->rowSize[y+z*image->ysize]); - - iPtr = image->tmp; - oPtr = buf; - for (;;) { - pixel = *iPtr++; - count = (int)(pixel & 0x7F); - if (!count) { - return; - } - if (pixel & 0x80) { - while (count--) { - *oPtr++ = *iPtr++; - } - } else { - pixel = *iPtr++; - while (count--) { - *oPtr++ = pixel; - } - } - } - } else { - fgseek(image->file, 512+(y*image->xsize)+(z*image->xsize*image->ysize), - SEEK_SET); - // fread(buf, 1, image->xsize, image->file); - fgread(image->file, buf, image->xsize); - } -} - -GLubyte * -read_alpha_texture(const char *name, int *width, int *height) -{ - unsigned char *base, *lptr; - ImageRec *image; - int y; - - image = ImageOpen(name); - if(!image) { - return NULL; - } - - (*width)=image->xsize; - (*height)=image->ysize; - - printf("image->zsize = %d\n", image->zsize); - - if (image->zsize != 1) { - ImageClose(image); - return NULL; - } - - base = (unsigned char *)malloc(image->xsize*image->ysize*sizeof(unsigned char)); - lptr = base; - for(y=0; yysize; y++) { - ImageGetRow(image,lptr,y,0); - lptr += image->xsize; - } - ImageClose(image); - - return (unsigned char *) base; -} - -GLubyte * -read_rgb_texture(const char *name, int *width, int *height) -{ - unsigned char *base, *ptr; - unsigned char *rbuf, *gbuf, *bbuf, *abuf; - ImageRec *image; - int y; - - image = ImageOpen(name); - - if(!image) - return NULL; - (*width)=image->xsize; - (*height)=image->ysize; - if (image->zsize != 3 && image->zsize != 4) { - ImageClose(image); - return NULL; - } - - base = (unsigned char*)malloc(image->xsize*image->ysize*sizeof(unsigned int)*3); - rbuf = (unsigned char *)malloc(image->xsize*sizeof(unsigned char)); - gbuf = (unsigned char *)malloc(image->xsize*sizeof(unsigned char)); - bbuf = (unsigned char *)malloc(image->xsize*sizeof(unsigned char)); - abuf = (unsigned char *)malloc(image->xsize*sizeof(unsigned char)); - if(!base || !rbuf || !gbuf || !bbuf || !abuf) { - if (base) free(base); - if (rbuf) free(rbuf); - if (gbuf) free(gbuf); - if (bbuf) free(bbuf); - if (abuf) free(abuf); - return NULL; - } - ptr = base; - for(y=0; yysize; y++) { - if(image->zsize == 4) { - ImageGetRow(image,rbuf,y,0); - ImageGetRow(image,gbuf,y,1); - ImageGetRow(image,bbuf,y,2); - ImageGetRow(image,abuf,y,3); /* Discard. */ - rgbtorgb(rbuf,gbuf,bbuf,ptr,image->xsize); - ptr += (image->xsize * 3); - } else { - ImageGetRow(image,rbuf,y,0); - ImageGetRow(image,gbuf,y,1); - ImageGetRow(image,bbuf,y,2); - rgbtorgb(rbuf,gbuf,bbuf,ptr,image->xsize); - ptr += (image->xsize * 3); - } - } - ImageClose(image); - free(rbuf); - free(gbuf); - free(bbuf); - free(abuf); - - return (GLubyte *) base; -} diff --git a/Simulator/Objects/texload.h b/Simulator/Objects/texload.h deleted file mode 100644 index e15e025cf..000000000 --- a/Simulator/Objects/texload.h +++ /dev/null @@ -1,30 +0,0 @@ - -/* Copyright (c) Mark J. Kilgard, 1997. */ - -/* 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 _TEXLOAD_H -#define _TEXLOAD_H - - -#include - - -#ifdef __cplusplus -extern "C" { -#endif - - -extern GLubyte *read_alpha_texture(const char *name, int *width, int *height); -extern GLubyte * read_rgb_texture(const char *name, int *width, int *height); - - -#ifdef __cplusplus -} -#endif - - -#endif /* _TEXLOAD_H */ diff --git a/Simulator/Scenery/design b/Simulator/Scenery/design new file mode 100644 index 000000000..26ef38f10 --- /dev/null +++ b/Simulator/Scenery/design @@ -0,0 +1,46 @@ +(x) class fgOBJECT { + // material property pointer + int material_ptr; + + // culling data + double ref[3]; + double radius; + + // OpenGL display list for object data + GLint display_list_ptr; +} + + +(x) class fgTILE { + // culling data + double ref[3]; + double radius; + + list < fgOBJECT > object_list; +} + + +class fgMATERIAL { + int list_size; + int counter; + +public: + + // material properties + GLfloat ambient[4], diffuse[4], specular[4]; + GLint texture_ptr; + + // transient list of objects with this material type (used for sorting + // by material to reduce GL state changes when rendering the scene + fgOBJECT *material_object_list[lots]; + + init_list(); + append_list(); + list_traverse_init(); + next_obj() +} + + +class fgMATERIAL_MGR { + list < fgMATERIAL > material_list; +} diff --git a/Simulator/Scenery/maptest.cxx b/Simulator/Scenery/maptest.cxx new file mode 100644 index 000000000..e8249aa60 --- /dev/null +++ b/Simulator/Scenery/maptest.cxx @@ -0,0 +1,21 @@ +// a simple STL test + +#include // stl +#include // stl +#include + +using namespace std; + +main() { + map < string, int, less > mymap; + string name; + int value; + + mymap["curt"] = 1; + mymap["doug"] = 2; + mymap["doug"] = 3; + mymap["dan"] = 4; + + printf("curt = %d\n", mymap["curt"]); + printf("doug = %d\n", mymap["doug"]); +} diff --git a/Simulator/Scenery/scenery.cxx b/Simulator/Scenery/scenery.cxx index 730a9c924..a7cff2f13 100644 --- a/Simulator/Scenery/scenery.cxx +++ b/Simulator/Scenery/scenery.cxx @@ -82,6 +82,9 @@ void fgSceneryRender( void ) { // $Log$ +// Revision 1.1 1999/04/05 21:32:49 curt +// Initial revision +// // Revision 1.10 1998/11/06 21:18:20 curt // Converted to new logstream debugging facility. This allows release // builds with no messages at all (and no performance impact) by using diff --git a/Simulator/Scenery/scenery.hxx b/Simulator/Scenery/scenery.hxx index 385c8a8f2..eabbd5d1d 100644 --- a/Simulator/Scenery/scenery.hxx +++ b/Simulator/Scenery/scenery.hxx @@ -70,6 +70,9 @@ void fgSceneryRender( void ); // $Log$ +// Revision 1.1 1999/04/05 21:32:49 curt +// Initial revision +// // Revision 1.6 1998/10/16 23:27:59 curt // C++-ifying. // diff --git a/Simulator/Scenery/test.cxx b/Simulator/Scenery/test.cxx new file mode 100644 index 000000000..4b97c385c --- /dev/null +++ b/Simulator/Scenery/test.cxx @@ -0,0 +1,68 @@ +// some simple STL tests + +#include +#include +#include +#include +#include + + +main() { + deque < int > mylist; + map < string, int, less > mymap; + string name; + int i, j, size, num, age; + + // printf("max_size = %d\n", mylist.max_size()); + + for ( i = 0; i < 2000; i++ ) { + mylist.push_back(i); + } + + size = mylist.size(); + + deque < int > :: iterator current = mylist.begin(); + deque < int > :: iterator last = mylist.end(); + + /* + for ( i = 0; i < 10000000; i++ ) { + while ( current != last ) { + num = *current++; + } + } + */ + + /* + for ( i = 0; i < 1000; i++ ) { + for ( j = 0; j < size; j++ ) { + num = mylist[j]; + } + } + */ + + mymap["curt"] = 30; + mymap["doug"] = 12; + mymap["doug"] = 28; + mymap["dan"] = 24; + + printf("curt age = %d\n", mymap["curt"]); + printf("doug age = %d\n", mymap["doug"]); + + + map < string, int, less > :: iterator test = mymap.find("dan"); + if ( test == mymap.end() ) { + printf("dan age = not found\n"); + } else { + printf("dan age = %d\n", (*test).second); + } + + map < string, int, less > :: iterator mapcurrent = mymap.begin(); + map < string, int, less > :: iterator maplast = mymap.end(); + while ( mapcurrent != maplast ) { + name = (*mapcurrent).first; + age = (*mapcurrent).second; + cout << name; + printf(" = %d\n", age); + *mapcurrent++; + } +} diff --git a/Simulator/Scenery/tile.cxx b/Simulator/Scenery/tile.cxx index bd95eb6d5..9011ef367 100644 --- a/Simulator/Scenery/tile.cxx +++ b/Simulator/Scenery/tile.cxx @@ -67,6 +67,9 @@ fgTILE::release_fragments() // $Log$ +// Revision 1.1 1999/04/05 21:32:49 curt +// Initial revision +// // Revision 1.16 1999/03/25 19:03:24 curt // Converted to use new bucket routines. // diff --git a/Simulator/Scenery/tile.hxx b/Simulator/Scenery/tile.hxx index 4fd636e17..8c88d543b 100644 --- a/Simulator/Scenery/tile.hxx +++ b/Simulator/Scenery/tile.hxx @@ -162,6 +162,9 @@ private: // $Log$ +// Revision 1.1 1999/04/05 21:32:49 curt +// Initial revision +// // Revision 1.26 1999/03/25 19:03:25 curt // Converted to use new bucket routines. // diff --git a/Simulator/Scenery/tilecache.cxx b/Simulator/Scenery/tilecache.cxx index 8b8c441d7..e0da52806 100644 --- a/Simulator/Scenery/tilecache.cxx +++ b/Simulator/Scenery/tilecache.cxx @@ -181,6 +181,9 @@ fgTILECACHE::~fgTILECACHE( void ) { // $Log$ +// Revision 1.1 1999/04/05 21:32:49 curt +// Initial revision +// // Revision 1.23 1999/03/25 19:03:26 curt // Converted to use new bucket routines. // diff --git a/Simulator/Scenery/tilecache.hxx b/Simulator/Scenery/tilecache.hxx index 49e7c0c79..7863be75d 100644 --- a/Simulator/Scenery/tilecache.hxx +++ b/Simulator/Scenery/tilecache.hxx @@ -104,6 +104,9 @@ extern fgTILECACHE global_tile_cache; // $Log$ +// Revision 1.1 1999/04/05 21:32:49 curt +// Initial revision +// // Revision 1.14 1999/03/25 19:03:27 curt // Converted to use new bucket routines. // diff --git a/Simulator/Scenery/tilemgr.cxx b/Simulator/Scenery/tilemgr.cxx index 5c8e9b2c6..6f7017c81 100644 --- a/Simulator/Scenery/tilemgr.cxx +++ b/Simulator/Scenery/tilemgr.cxx @@ -763,6 +763,9 @@ void fgTileMgrRender( void ) { // $Log$ +// Revision 1.1 1999/04/05 21:32:49 curt +// Initial revision +// // Revision 1.55 1999/03/25 19:03:28 curt // Converted to use new bucket routines. // diff --git a/Simulator/Scenery/tilemgr.hxx b/Simulator/Scenery/tilemgr.hxx index d35958c88..19a3449eb 100644 --- a/Simulator/Scenery/tilemgr.hxx +++ b/Simulator/Scenery/tilemgr.hxx @@ -59,6 +59,9 @@ void fgTileMgrRender( void ); // $Log$ +// Revision 1.1 1999/04/05 21:32:49 curt +// Initial revision +// // Revision 1.8 1999/03/25 19:03:29 curt // Converted to use new bucket routines. // diff --git a/Simulator/Time/event.cxx b/Simulator/Time/event.cxx index d1c622ead..2b43a4460 100644 --- a/Simulator/Time/event.cxx +++ b/Simulator/Time/event.cxx @@ -306,6 +306,9 @@ fgEVENT_MGR::~fgEVENT_MGR( void ) { // $Log$ +// Revision 1.1 1999/04/05 21:32:47 curt +// Initial revision +// // Revision 1.17 1999/01/27 04:50:18 curt // Move sun/solaris specific stuff to compiler.h // diff --git a/Simulator/Time/event.hxx b/Simulator/Time/event.hxx index 69ad7217e..e72df5cc8 100644 --- a/Simulator/Time/event.hxx +++ b/Simulator/Time/event.hxx @@ -166,6 +166,9 @@ extern fgEVENT_MGR global_events; // $Log$ +// Revision 1.1 1999/04/05 21:32:47 curt +// Initial revision +// // Revision 1.18 1999/03/02 01:03:33 curt // Tweaks for building with native SGI compilers. // diff --git a/Simulator/Time/fg_time.cxx b/Simulator/Time/fg_time.cxx index ac6eb9f32..2cef15af1 100644 --- a/Simulator/Time/fg_time.cxx +++ b/Simulator/Time/fg_time.cxx @@ -399,6 +399,9 @@ void fgTimeUpdate(FGInterface *f, fgTIME *t) { // $Log$ +// Revision 1.1 1999/04/05 21:32:47 curt +// Initial revision +// // Revision 1.32 1999/02/26 22:10:10 curt // Added initial support for native SGI compilers. // diff --git a/Simulator/Time/fg_time.hxx b/Simulator/Time/fg_time.hxx index a784531fe..af81e6976 100644 --- a/Simulator/Time/fg_time.hxx +++ b/Simulator/Time/fg_time.hxx @@ -105,6 +105,9 @@ void fgTimeUpdate(FGInterface *f, fgTIME *t); // $Log$ +// Revision 1.1 1999/04/05 21:32:47 curt +// Initial revision +// // Revision 1.14 1999/02/05 21:29:19 curt // Modifications to incorporate Jon S. Berndts flight model code. // diff --git a/Simulator/Time/fg_timer.cxx b/Simulator/Time/fg_timer.cxx index 074d90f5b..aeeabf3b0 100644 --- a/Simulator/Time/fg_timer.cxx +++ b/Simulator/Time/fg_timer.cxx @@ -119,6 +119,9 @@ int fgGetTimeInterval( void ) { // $Log$ +// Revision 1.1 1999/04/05 21:32:47 curt +// Initial revision +// // Revision 1.6 1999/01/09 13:37:45 curt // Convert fgTIMESTAMP to FGTimeStamp which holds usec instead of ms. // diff --git a/Simulator/Time/fg_timer.hxx b/Simulator/Time/fg_timer.hxx index 7cfd10632..26eb68a1f 100644 --- a/Simulator/Time/fg_timer.hxx +++ b/Simulator/Time/fg_timer.hxx @@ -49,11 +49,14 @@ int fgGetTimeInterval( void ); /* $Log$ -/* Revision 1.1 1998/04/24 00:52:30 curt -/* Wrapped "#include " in "#ifdef HAVE_CONFIG_H" -/* Fog color fixes. -/* Separated out lighting calcs into their own file. +/* Revision 1.1 1999/04/05 21:32:47 curt +/* Initial revision /* + * Revision 1.1 1998/04/24 00:52:30 curt + * Wrapped "#include " in "#ifdef HAVE_CONFIG_H" + * Fog color fixes. + * Separated out lighting calcs into their own file. + * * Revision 1.5 1998/04/21 17:01:45 curt * Fixed a problems where a pointer to a function was being passed around. In * one place this functions arguments were defined as ( void ) while in another diff --git a/Simulator/Time/light.cxx b/Simulator/Time/light.cxx index f7e06ea48..0d1fa73a1 100644 --- a/Simulator/Time/light.cxx +++ b/Simulator/Time/light.cxx @@ -221,6 +221,9 @@ fgLIGHT::~fgLIGHT( void ) { // $Log$ +// Revision 1.1 1999/04/05 21:32:47 curt +// Initial revision +// // Revision 1.27 1999/04/05 02:14:40 curt // Fixed a fog coloring bug. // diff --git a/Simulator/Time/light.hxx b/Simulator/Time/light.hxx index 1ae4eb55e..56a3b2104 100644 --- a/Simulator/Time/light.hxx +++ b/Simulator/Time/light.hxx @@ -151,6 +151,9 @@ extern fgLIGHT cur_light_params; // $Log$ +// Revision 1.1 1999/04/05 21:32:47 curt +// Initial revision +// // Revision 1.9 1999/03/22 02:08:17 curt // Changes contributed by Durk Talsma: // diff --git a/Simulator/Time/moonpos.cxx b/Simulator/Time/moonpos.cxx index 7247cbebf..827e36300 100644 --- a/Simulator/Time/moonpos.cxx +++ b/Simulator/Time/moonpos.cxx @@ -437,6 +437,9 @@ void fgUpdateMoonPos( void ) { // $Log$ +// Revision 1.1 1999/04/05 21:32:47 curt +// Initial revision +// // Revision 1.1 1999/03/22 12:08:57 curt // Initial revision. // diff --git a/Simulator/Time/sunpos.cxx b/Simulator/Time/sunpos.cxx index 024258828..a87ce36ce 100644 --- a/Simulator/Time/sunpos.cxx +++ b/Simulator/Time/sunpos.cxx @@ -342,6 +342,9 @@ void fgUpdateSunPos( void ) { // $Log$ +// Revision 1.1 1999/04/05 21:32:47 curt +// Initial revision +// // Revision 1.21 1999/03/22 02:08:18 curt // Changes contributed by Durk Talsma: // diff --git a/Simulator/Time/test_event.c b/Simulator/Time/test_event.c new file mode 100644 index 000000000..bf7f09409 --- /dev/null +++ b/Simulator/Time/test_event.c @@ -0,0 +1,38 @@ +#include + +#include "event.h" + +void a() { + printf("Function a()\n"); + system("date"); +} + + +void b() { + printf("Function b()\n"); + system("date"); +} + + +void c() { + printf("Function c()\n"); + fgEventPrintStats(); +} + + +void d() { +} + + +main() { + fgEventInit(); + + fgEventRegister("Function b()", b, FG_EVENT_READY, 1000); + fgEventRegister("Function a()", a, FG_EVENT_READY, 2500); + fgEventRegister("Function d()", d, FG_EVENT_READY, 500); + fgEventRegister("Function c()", c, FG_EVENT_READY, 10000); + + while ( 1 ) { + fgEventProcess(); + } +} diff --git a/Simulator/Time/timestamp.hxx b/Simulator/Time/timestamp.hxx index dbd9acddc..37c0e42d7 100644 --- a/Simulator/Time/timestamp.hxx +++ b/Simulator/Time/timestamp.hxx @@ -167,6 +167,9 @@ inline long operator - (const FGTimeStamp& a, const FGTimeStamp& b) // $Log$ +// Revision 1.1 1999/04/05 21:32:47 curt +// Initial revision +// // Revision 1.5 1999/02/02 20:13:43 curt // MSVC++ portability changes by Bernie Bright: // diff --git a/Simulator/Time/ttest.c b/Simulator/Time/ttest.c new file mode 100644 index 000000000..6a45c7f28 --- /dev/null +++ b/Simulator/Time/ttest.c @@ -0,0 +1,86 @@ +#include +#include +#include + +int main() { + time_t cur_time, start, start_gmt, now, now_gmt; + struct tm *gmt, mt; + long int offset; + double diff, part, days, hours, lon, lst; + int i; + + cur_time = time(NULL); + + printf("Time = %ld\n", cur_time); + + gmt = gmtime(&cur_time); + + printf("GMT = %d/%d/%2d %d:%02d:%02d\n", + gmt->tm_mon, gmt->tm_mday, gmt->tm_year, + gmt->tm_hour, gmt->tm_min, gmt->tm_sec); + + mt.tm_mon = 2; + mt.tm_mday = 21; + mt.tm_year = 98; + mt.tm_hour = 12; + mt.tm_min = 0; + mt.tm_sec = 0; + + start = mktime(&mt); + + offset = -(timezone / 3600 - daylight); + + printf("Raw time zone offset = %ld\n", timezone); + printf("Daylight Savings = %d\n", daylight); + + printf("Local hours from GMT = %d\n", offset); + + start_gmt = start - timezone + (daylight * 3600); + + printf("March 21 noon (CST) = %ld\n", start); + printf("March 21 noon (GMT) = %ld\n", start_gmt); + + for ( i = 0; i < 12; i++ ) { + mt.tm_mon = i; + mt.tm_mday = 21; + mt.tm_year = gmt->tm_year; + mt.tm_hour = 12; + mt.tm_min = 0; + mt.tm_sec = 0; + + now = mktime(&mt); + + offset = -(timezone / 3600 - daylight); + + printf("Raw time zone offset = %ld\n", timezone); + printf("Daylight Savings = %d\n", daylight); + + printf("Local hours from GMT = %d\n", offset); + + now_gmt = now - timezone + (daylight * 3600); + + printf("%d/%d/%d noon (CST) = %ld\n", i+1, 21, 97, now); + printf("%d/%d/%d noon (GMT) = %ld\n", i+1, 21, 97, now_gmt); + + diff = (now_gmt - start_gmt) / (3600.0 * 24.0); + + printf("Time since 3/21/%2d GMT = %.2f\n", gmt->tm_year, diff); + + part = fmod(diff, 1.0); + days = diff - part; + /* hours = gmt->tm_hour + gmt->tm_min/60.0 + gmt->tm_sec/3600.0; */ + hours = 12; + lon = -112; + + lst = (days + lon)/15.0 + hours - 12; + + while ( lst < 0.0 ) { + lst += 24.0; + } + + printf("days = %.1f hours = %.2f lon = %.2f lst = %.2f\n", + days, hours, lon, lst); + } + + return(0); +} diff --git a/Simulator/Time/win32test.c b/Simulator/Time/win32test.c new file mode 100644 index 000000000..9b1383b70 --- /dev/null +++ b/Simulator/Time/win32test.c @@ -0,0 +1,65 @@ +#include + +#include +#include +#include + +int main() { + SYSTEMTIME st; + TIME_ZONE_INFORMATION tzinfo; + DWORD t; + int i; + + GetSystemTime(&st); + printf("System Time = %d %d %d %d %d %d %d %d\n", + st.wYear, + st.wMonth, + st.wDayOfWeek, + st.wDay, + st.wHour, + st.wMinute, + st.wSecond, + st.wMilliseconds + ); + + t = GetTimeZoneInformation( &tzinfo ); + + printf("time zone info return = %d\n", t); + + printf("Bias = %ld\n", tzinfo.Bias); + + printf("Standard Name = "); + i = 0; + while ( tzinfo.StandardName[i] != 0 ) { + printf("%c", tzinfo.StandardName[i]); + i++; + } + printf("\n"); + + printf("System Time = %d %d %d %d %d %d %d %d\n", + tzinfo.StandardDate.wYear, + tzinfo.StandardDate.wMonth, + tzinfo.StandardDate.wDayOfWeek, + tzinfo.StandardDate.wDay, + tzinfo.StandardDate.wHour, + tzinfo.StandardDate.wMinute, + tzinfo.StandardDate.wSecond, + tzinfo.StandardDate.wMilliseconds + ); + + printf("Standard Bias = %d\n", tzinfo.StandardBias); + + printf("Daylight Name = "); + i = 0; + while ( tzinfo.DaylightName[i] != 0 ) { + printf("%c", tzinfo.DaylightName[i]); + i++; + } + printf("\n"); + + printf("Daylight Date = %d\n", tzinfo.DaylightDate); + + printf("Daylight Bias = %ld\n", tzinfo.DaylightBias); + + return(1); +} diff --git a/Simulator/Simulator/Todo b/Simulator/Todo similarity index 100% rename from Simulator/Simulator/Todo rename to Simulator/Todo diff --git a/Simulator/Weather/weather.cxx b/Simulator/Weather/weather.cxx index 7a1b50c11..a577742bf 100644 --- a/Simulator/Weather/weather.cxx +++ b/Simulator/Weather/weather.cxx @@ -79,6 +79,9 @@ void FGWeather::Update( void ) { // $Log$ +// Revision 1.1 1999/04/05 21:32:48 curt +// Initial revision +// // Revision 1.6 1999/02/05 21:29:21 curt // Modifications to incorporate Jon S. Berndts flight model code. // diff --git a/Simulator/Weather/weather.hxx b/Simulator/Weather/weather.hxx index e17e1f2f5..1df88f8a2 100644 --- a/Simulator/Weather/weather.hxx +++ b/Simulator/Weather/weather.hxx @@ -69,6 +69,9 @@ extern FGWeather current_weather; // $Log$ +// Revision 1.1 1999/04/05 21:32:48 curt +// Initial revision +// // Revision 1.2 1998/12/06 13:51:27 curt // Turned "struct fgWEATHER" into "class FGWeather". // diff --git a/Tools/Areas/Makefile.am b/Tools/Areas/Makefile.am index 7c6106189..18bc60aef 100644 --- a/Tools/Areas/Makefile.am +++ b/Tools/Areas/Makefile.am @@ -37,6 +37,9 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib #--------------------------------------------------------------------------- # $Log$ +# Revision 1.1 1999/04/05 21:32:44 curt +# Initial revision +# # Revision 1.3 1998/11/04 23:01:43 curt # Changes to the automake/autoconf system to reduce the number of libraries # that are unnecessarily linked into the various executables. diff --git a/Tools/Areas/area.cxx b/Tools/Areas/area.cxx index 2dabe331d..038f019d6 100644 --- a/Tools/Areas/area.cxx +++ b/Tools/Areas/area.cxx @@ -155,6 +155,9 @@ void gen_runway_area( double lon, double lat, double heading, // $Log$ +// Revision 1.1 1999/04/05 21:32:44 curt +// Initial revision +// // Revision 1.1 1998/07/20 12:54:05 curt // Initial revision. // diff --git a/Tools/Areas/area.hxx b/Tools/Areas/area.hxx index 584e5f6a0..3e47e8c35 100644 --- a/Tools/Areas/area.hxx +++ b/Tools/Areas/area.hxx @@ -51,6 +51,9 @@ void gen_runway_area( double lon, double lat, double heading, // $Log$ +// Revision 1.1 1999/04/05 21:32:44 curt +// Initial revision +// // Revision 1.1 1998/07/20 12:54:05 curt // Initial revision. // diff --git a/Tools/AssemTris/Makefile.am b/Tools/AssemTris/Makefile.am deleted file mode 100644 index 5e830c88b..000000000 --- a/Tools/AssemTris/Makefile.am +++ /dev/null @@ -1,62 +0,0 @@ -#--------------------------------------------------------------------------- -# Makefile -# -# Written by Curtis Olson, started January 1998. -# -# Copyright (C) 1998 Curtis L. Olson - curt@me.umn.edu -# -# 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. -# -# $Id$ -# (Log is kept at end of this file) -#--------------------------------------------------------------------------- - - -bin_PROGRAMS = assemtris - -assemtris_SOURCES = assemtris.cxx assemtris.hxx - -assemtris_LDADD = \ - $(top_builddir)/Lib/Bucket/libBucket.a \ - $(base_LIBS) - -INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib - - -#--------------------------------------------------------------------------- -# $Log$ -# Revision 1.5 1998/11/04 23:01:45 curt -# Changes to the automake/autoconf system to reduce the number of libraries -# that are unnecessarily linked into the various executables. -# -# Revision 1.4 1998/09/25 19:35:25 curt -# Renamed assemtris.[ch] to assemtris.[ch]xx -# -# Revision 1.3 1998/07/30 23:49:23 curt -# Removed libtool support. -# -# Revision 1.2 1998/04/14 02:25:59 curt -# Code reorganizations. Added a Lib/ directory for more general libraries. -# -# Revision 1.1 1998/04/08 22:54:57 curt -# Adopted Gnu automake/autoconf system. -# -# Revision 1.2 1998/01/21 02:55:46 curt -# Incorporated new make system from Bob Kuehne . -# -# Revision 1.1 1998/01/15 02:45:25 curt -# Initial revision. -# - diff --git a/Tools/AssemTris/assemtris.cxx b/Tools/AssemTris/assemtris.cxx deleted file mode 100644 index 1c87851e3..000000000 --- a/Tools/AssemTris/assemtris.cxx +++ /dev/null @@ -1,600 +0,0 @@ -// assemtris.cxx -- reassemble the pieces produced by splittris -// -// Written by Curtis Olson, started January 1998. -// -// Copyright (C) 1997 Curtis L. Olson - curt@me.umn.edu -// -// 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. -// -// $Id$ -// (Log is kept at end of this file) - - -#include -#include -#include // for atoi() -#include -#include // for stat() -#include // for stat() - -#include "assemtris.hxx" - -#include -#include - - -// #define OFFSET_LON 0.1 -// #define OFFSET_LAT 0.1 - -#define OFFSET_LON 0.0 -#define OFFSET_LAT 0.0 - -int nodecount = 0; -int excount = 0; - -static double nodes[MAX_NODES][3]; -static double exnodes[MAX_NODES][3]; - - -fgBUCKET my_index; -fgBUCKET ne_index, nw_index, sw_index, se_index; -fgBUCKET north_index, south_index, east_index, west_index; - - -// return the file base name ( foo/bar/file.ext = file.ext ) -void extract_file(char *in, char *base) { - int len, i; - - len = strlen(in); - - i = len - 1; - while ( (i >= 0) && (in[i] != '/') ) { - i--; - } - - in += (i + 1); - strcpy(base, in); -} - - -// return the file path name ( foo/bar/file.ext = foo/bar ) -void extract_path(char *in, char *base) { - int len, i; - - len = strlen(in); - strcpy(base, in); - - i = len - 1; - while ( (i >= 0) && (in[i] != '/') ) { - i--; - } - - base[i] = '\0'; -} - - -// check to see if specified node is in the extra list -int is_extra_node(double *n) { - int i; - - for ( i = 1; i <= excount; i++ ) { - // we only check lon/lat in case the height got fooled with - // along the way - if ( (fabs(n[0] - exnodes[i][0]) < FG_EPSILON) && - (fabs(n[1] - exnodes[i][1]) < FG_EPSILON) ) { - return(i); - } - } - - return(0); -} - -// Read all the extra nodes. These typically define inner areas to -// exclude from triangulations. There will be a .poly file that -// refers to these by position number which assumes all the extra -// nodes come first in the generated .node file. -void read_extra_nodes(char *exfile) { - FILE *fd; - int i, junk1, junk2, junk3; - - // load extra nodes if they exist - excount = 0; - if ( (fd = fopen(exfile, "r")) != NULL ) { - printf("Found and 'extra' node file = %s\n", exfile); - fscanf(fd, "%d %d %d %d", &excount, &junk1, &junk2, &junk3); - - if ( excount > MAX_NODES - 1 ) { - printf("Error, too many 'extra' nodes, increase array size\n"); - exit(-1); - } else { - printf(" Expecting %d 'extra' nodes\n", excount); - } - - for ( i = 1; i <= excount; i++ ) { - fscanf(fd, "%d %lf %lf %lf\n", &junk1, - &exnodes[i][0], &exnodes[i][1], &exnodes[i][2]); - printf("(extra) %d %.2f %.2f %.2f\n", - i, exnodes[i][0], exnodes[i][1], exnodes[i][2]); - } - fclose(fd); - } -} - - -// check if a file exists -int file_exists(char *file) { - struct stat stat_buf; - int result; - - printf("checking %s ... ", file); - - result = stat(file, &stat_buf); - - if ( result != 0 ) { - // stat failed, no file - printf("not found.\n"); - return(0); - } else { - // stat succeeded, file exists - printf("exists.\n"); - return(1); - } -} - - -// check to see if a shared object exists -int shared_object_exists(char *basepath, char *ext, char *file) { - char scene_path[256]; - long int index; - - if ( strcmp(ext, ".sw") == 0 ) { - fgBucketGenBasePath(&my_index, scene_path); - index = fgBucketGenIndex(&my_index); - sprintf(file, "%s/%s/%ld.1.sw", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - fgBucketGenBasePath(&west_index, scene_path); - index = fgBucketGenIndex(&west_index); - sprintf(file, "%s/%s/%ld.1.se", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - fgBucketGenBasePath(&sw_index, scene_path); - index = fgBucketGenIndex(&sw_index); - sprintf(file, "%s/%s/%ld.1.ne", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - fgBucketGenBasePath(&south_index, scene_path); - index = fgBucketGenIndex(&south_index); - sprintf(file, "%s/%s/%ld.1.nw", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - } - - if ( strcmp(ext, ".se") == 0 ) { - fgBucketGenBasePath(&my_index, scene_path); - index = fgBucketGenIndex(&my_index); - sprintf(file, "%s/%s/%ld.1.se", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - fgBucketGenBasePath(&east_index, scene_path); - index = fgBucketGenIndex(&east_index); - sprintf(file, "%s/%s/%ld.1.sw", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - fgBucketGenBasePath(&se_index, scene_path); - index = fgBucketGenIndex(&se_index); - sprintf(file, "%s/%s/%ld.1.nw", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - fgBucketGenBasePath(&south_index, scene_path); - index = fgBucketGenIndex(&south_index); - sprintf(file, "%s/%s/%ld.1.ne", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - } - - if ( strcmp(ext, ".ne") == 0 ) { - fgBucketGenBasePath(&my_index, scene_path); - index = fgBucketGenIndex(&my_index); - sprintf(file, "%s/%s/%ld.1.ne", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - fgBucketGenBasePath(&east_index, scene_path); - index = fgBucketGenIndex(&east_index); - sprintf(file, "%s/%s/%ld.1.nw", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - fgBucketGenBasePath(&ne_index, scene_path); - index = fgBucketGenIndex(&ne_index); - sprintf(file, "%s/%s/%ld.1.sw", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - fgBucketGenBasePath(&north_index, scene_path); - index = fgBucketGenIndex(&north_index); - sprintf(file, "%s/%s/%ld.1.se", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - } - - if ( strcmp(ext, ".nw") == 0 ) { - fgBucketGenBasePath(&my_index, scene_path); - index = fgBucketGenIndex(&my_index); - sprintf(file, "%s/%s/%ld.1.nw", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - fgBucketGenBasePath(&west_index, scene_path); - index = fgBucketGenIndex(&west_index); - sprintf(file, "%s/%s/%ld.1.ne", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - fgBucketGenBasePath(&nw_index, scene_path); - index = fgBucketGenIndex(&nw_index); - sprintf(file, "%s/%s/%ld.1.se", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - fgBucketGenBasePath(&north_index, scene_path); - index = fgBucketGenIndex(&north_index); - sprintf(file, "%s/%s/%ld.1.sw", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - } - - if ( strcmp(ext, ".south") == 0 ) { - fgBucketGenBasePath(&my_index, scene_path); - index = fgBucketGenIndex(&my_index); - sprintf(file, "%s/%s/%ld.1.south", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - fgBucketGenBasePath(&south_index, scene_path); - index = fgBucketGenIndex(&south_index); - sprintf(file, "%s/%s/%ld.1.north", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - } - - if ( strcmp(ext, ".north") == 0 ) { - fgBucketGenBasePath(&my_index, scene_path); - index = fgBucketGenIndex(&my_index); - sprintf(file, "%s/%s/%ld.1.north", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - fgBucketGenBasePath(&north_index, scene_path); - index = fgBucketGenIndex(&north_index); - sprintf(file, "%s/%s/%ld.1.south", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - } - - if ( strcmp(ext, ".west") == 0 ) { - fgBucketGenBasePath(&my_index, scene_path); - index = fgBucketGenIndex(&my_index); - sprintf(file, "%s/%s/%ld.1.west", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - fgBucketGenBasePath(&west_index, scene_path); - index = fgBucketGenIndex(&west_index); - sprintf(file, "%s/%s/%ld.1.east", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - } - - if ( strcmp(ext, ".east") == 0 ) { - fgBucketGenBasePath(&my_index, scene_path); - index = fgBucketGenIndex(&my_index); - sprintf(file, "%s/%s/%ld.1.east", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - fgBucketGenBasePath(&east_index, scene_path); - index = fgBucketGenIndex(&east_index); - sprintf(file, "%s/%s/%ld.1.west", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - } - - if ( strcmp(ext, ".body") == 0 ) { - fgBucketGenBasePath(&my_index, scene_path); - index = fgBucketGenIndex(&my_index); - sprintf(file, "%s/%s/%ld.1.body", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - } - - return(0); -} - - -// my custom file opening routine ... don't open if a shared edge or -// vertex alread exists -FILE *my_open(char *basename, char *basepath, char *ext) { - FILE *fp; - char filename[256]; - - // check if a shared object already exists - if ( shared_object_exists(basepath, ext, filename) ) { - // not an actual file open error, but we've already got the - // shared edge, so we don't want to create another one - fp = fopen(filename, "r"); - printf("Opening %s\n", filename); - return(fp); - } else { - // open the file - printf("not opening\n"); - return(NULL); - } -} - - -// given a file pointer, read all the gdn (geodetic nodes from it.) -// The specified offset values (in arcsec) are used to overlap the -// edges of the tile slightly to cover gaps induced by floating point -// precision problems. 1 arcsec == about 100 feet so 0.01 arcsec == -// about 1 foot -void read_nodes(FILE *fp, double offset_lon, double offset_lat) { - double n[3]; - char line[256]; - int ex_index; - - offset_lon = offset_lat = 0.0; - - while ( fgets(line, 250, fp) != NULL ) { - if ( strncmp(line, "gdn ", 4) == 0 ) { - sscanf(line, "gdn %lf %lf %lf\n", &n[0], &n[1], &n[2]); - - ex_index = is_extra_node(n); - - if ( ex_index == 0 ) { - // not an extra node - nodes[nodecount][0] = n[0] + offset_lon; - nodes[nodecount][1] = n[1] + offset_lat; - nodes[nodecount][2] = n[2]; - - // printf("read_nodes(%d) %.2f %.2f %.2f %s", nodecount, - // nodes[nodecount][0], nodes[nodecount][1], - // nodes[nodecount][2], line); - - - nodecount++; - } else { - // is an extra node - printf("found extra node %.2f %.2f %.2f\n", n[0], n[1], n[2]); - // preserve the DEM altitude for now - exnodes[ex_index][2] = n[2]; - } - } - } -} - - -// load in nodes from the various split and shared pieces to -// reconstruct a tile -void build_node_list(char *basename, char *basepath) { - char exfile[256]; - FILE *ne, *nw, *se, *sw, *north, *south, *east, *west, *body; - - // load extra nodes if they exist - strcpy(exfile, basename); - strcat(exfile, ".node.ex"); - read_extra_nodes(exfile); - - ne = my_open(basename, basepath, ".ne"); - read_nodes(ne, OFFSET_LON, OFFSET_LAT); - fclose(ne); - - nw = my_open(basename, basepath, ".nw"); - read_nodes(nw, -1.0 * OFFSET_LON, OFFSET_LAT); - fclose(nw); - - se = my_open(basename, basepath, ".se"); - read_nodes(se, OFFSET_LON, -1.0 * OFFSET_LAT); - fclose(se); - - sw = my_open(basename, basepath, ".sw"); - read_nodes(sw, -1.0 * OFFSET_LON, -1.0 * OFFSET_LAT); - fclose(sw); - - north = my_open(basename, basepath, ".north"); - read_nodes(north, 0.0, OFFSET_LAT); - fclose(north); - - south = my_open(basename, basepath, ".south"); - read_nodes(south, 0.0, -1.0 * OFFSET_LAT); - fclose(south); - - east = my_open(basename, basepath, ".east"); - read_nodes(east, OFFSET_LON, 0.0); - fclose(east); - - west = my_open(basename, basepath, ".west"); - read_nodes(west, -1.0 * OFFSET_LON, 0.0); - fclose(west); - - body = my_open(basename, basepath, ".body"); - read_nodes(body, 0.0, 0.0); - fclose(body); -} - - -// dump in WaveFront .obj format -void dump_nodes(char *basename) { - char file[256]; - FILE *fd; - int i; - - // generate output file name - strcpy(file, basename); - // len = strlen(file); - // file[len-2] = '\0'; - strcat(file, ".node"); - - // dump vertices - printf("Creating node file: %s\n", file); - printf(" writing vertices in .node format.\n"); - fd = fopen(file, "w"); - - fprintf(fd, "%d 2 1 0\n", excount + nodecount); - - // now write out extra node data - for ( i = 1; i <= excount; i++ ) { - fprintf(fd, "%d %.2f %.2f %.2f 0\n", - i, exnodes[i][0], exnodes[i][1], exnodes[i][2]); - } - - // now write out actual node data - for ( i = 0; i < nodecount; i++ ) { - fprintf(fd, "%d %.2f %.2f %.2f 0\n", excount + i + 1, - nodes[i][0], nodes[i][1], nodes[i][2]); - } - - fclose(fd); -} - - -int main(int argc, char **argv) { - char basename[256], basepath[256], temp[256]; - long int tmp_index; - int len; - - // derive base name - strcpy(basename, argv[1]); - len = strlen(basename); - - // find the base path of the file - extract_path(basename, basepath); - extract_path(basepath, basepath); - extract_path(basepath, basepath); - printf("%s\n", basepath); - - // find the index of the current file - extract_file(basename, temp); - // len = strlen(temp); - // if ( len >= 2 ) { - // temp[len-2] = '\0'; - // } - tmp_index = atoi(temp); - printf("%ld\n", tmp_index); - fgBucketParseIndex(tmp_index, &my_index); - - printf("bucket = %d %d %d %d\n", - my_index.lon, my_index.lat, my_index.x, my_index.y); - // generate the indexes of the neighbors - fgBucketOffset(&my_index, &ne_index, 1, 1); - fgBucketOffset(&my_index, &nw_index, -1, 1); - fgBucketOffset(&my_index, &se_index, 1, -1); - fgBucketOffset(&my_index, &sw_index, -1, -1); - - fgBucketOffset(&my_index, &north_index, 0, 1); - fgBucketOffset(&my_index, &south_index, 0, -1); - fgBucketOffset(&my_index, &east_index, 1, 0); - fgBucketOffset(&my_index, &west_index, -1, 0); - - // printf("Corner indexes = %ld %ld %ld %ld\n", - // ne_index, nw_index, sw_index, se_index); - // printf("Edge indexes = %ld %ld %ld %ld\n", - // north_index, south_index, east_index, west_index); - - - // load the input data files - build_node_list(basename, basepath); - - // dump in WaveFront .obj format - dump_nodes(basename); - - return(0); -} - - -// $Log$ -// Revision 1.3 1998/11/02 18:25:40 curt -// Check for __CYGWIN__ (b20) as well as __CYGWIN32__ (pre b20 compilers) -// Other misc. tweaks. -// -// Revision 1.2 1998/09/25 19:38:01 curt -// Minor tweaks so that this actually compiles. -// -// Revision 1.1 1998/09/25 19:35:29 curt -// Renamed assemtris.[ch] to assemtris.[ch]xx -// -// Revision 1.13 1998/09/21 20:56:30 curt -// Changes to avoid setting airport area nodes back to their original -// elevations if they have been changed. -// -// -// Revision 1.12 1998/09/09 16:24:51 curt -// Fixed a bug in the handling of exclude files which was causing -// a crash by calling fclose() on an invalid file handle. -// Removed overlapping offsets. -// -// Revision 1.11 1998/08/06 12:47:59 curt -// Removed overlap in tiles as a test. -// -// Revision 1.10 1998/07/21 04:34:20 curt -// Mods to handle extra nodes (i.e. preserve cutouts). -// -// Revision 1.9 1998/07/04 00:55:39 curt -// typedef'd struct fgBUCKET. -// -// Revision 1.8 1998/06/01 17:58:19 curt -// Added a slight border overlap to try to minimize pixel wide gaps between -// tiles due to round off error. This is not a perfect solution, but helps. -// -// Revision 1.7 1998/04/14 02:26:00 curt -// Code reorganizations. Added a Lib/ directory for more general libraries. -// -// Revision 1.6 1998/04/08 22:54:58 curt -// Adopted Gnu automake/autoconf system. -// -// Revision 1.5 1998/03/03 16:00:52 curt -// More c++ compile tweaks. -// -// Revision 1.4 1998/01/31 00:41:23 curt -// Made a few changes converting floats to doubles. -// -// Revision 1.3 1998/01/27 18:37:00 curt -// Lots of updates to get back in sync with changes made over in .../Src/ -// -// Revision 1.2 1998/01/15 21:33:36 curt -// Assembling triangles and building a new .node file with the proper shared -// vertices now works. Now we just have to use the shared normals and we'll -// be all set. -// -// Revision 1.1 1998/01/15 02:45:26 curt -// Initial revision. -// - diff --git a/Tools/AssemTris/assemtris.hxx b/Tools/AssemTris/assemtris.hxx deleted file mode 100644 index 3c96881f4..000000000 --- a/Tools/AssemTris/assemtris.hxx +++ /dev/null @@ -1,51 +0,0 @@ -// splittris.hxx -- reassemble the pieces produced by splittris -// -// Written by Curtis Olson, started January 1998. -// -// Copyright (C) 1997 Curtis L. Olson - curt@me.umn.edu -// -// 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. -// -// $Id$ -// (Log is kept at end of this file) - - - -#ifndef ASSEMTRIS_H -#define ASSEMTRIS_H - - -#include -#include - - -#define MAX_NODES 200000 -#define MAX_TRIS 400000 - - -#endif // SPLITTRIS_H - - -// $Log$ -// Revision 1.2 1998/09/25 19:38:03 curt -// Minor tweaks so that this actually compiles. -// -// Revision 1.1 1998/09/25 19:35:31 curt -// Renamed assemtris.[ch] to assemtris.[ch]xx -// -// Revision 1.1 1998/01/15 02:45:26 curt -// Initial revision. -// - diff --git a/Tools/CVSROOT/checkoutlist b/Tools/CVSROOT/checkoutlist deleted file mode 100644 index b04b3501f..000000000 --- a/Tools/CVSROOT/checkoutlist +++ /dev/null @@ -1,13 +0,0 @@ -# The "checkoutlist" file is used to support additional version controlled -# administrative files in $CVSROOT/CVSROOT, such as template files. -# -# The first entry on a line is a filename which will be checked out from -# the corresponding RCS file in the $CVSROOT/CVSROOT directory. -# The remainder of the line is an error message to use if the file cannot -# be checked out. -# -# File format: -# -# [] -# -# comment lines begin with '#' diff --git a/Tools/CVSROOT/commitinfo b/Tools/CVSROOT/commitinfo deleted file mode 100644 index b19e7b7a6..000000000 --- a/Tools/CVSROOT/commitinfo +++ /dev/null @@ -1,15 +0,0 @@ -# The "commitinfo" file is used to control pre-commit checks. -# The filter on the right is invoked with the repository and a list -# of files to check. A non-zero exit of the filter program will -# cause the commit to be aborted. -# -# The first entry on a line is a regular expression which is tested -# against the directory that the change is being committed to, relative -# to the $CVSROOT. For the first match that is found, then the remainder -# of the line is the name of the filter to run. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. -# -# If the name "ALL" appears as a regular expression it is always used -# in addition to the first matching regex or "DEFAULT". diff --git a/Tools/CVSROOT/cvswrappers b/Tools/CVSROOT/cvswrappers deleted file mode 100644 index 5047bf1c5..000000000 --- a/Tools/CVSROOT/cvswrappers +++ /dev/null @@ -1,22 +0,0 @@ -# This file describes wrappers and other binary files to CVS. -# -# Wrappers are the concept where directories of files are to be -# treated as a single file. The intended use is to wrap up a wrapper -# into a single tar such that the tar archive can be treated as a -# single binary file in CVS. -# -# To solve the problem effectively, it was also necessary to be able to -# prevent rcsmerge from merging these files. -# -# Format of wrapper file ($CVSROOT/CVSROOT/cvswrappers or .cvswrappers) -# -# wildcard [option value][option value]... -# -# where option is one of -# -f from cvs filter value: path to filter -# -t to cvs filter value: path to filter -# -m update methodology value: MERGE or COPY -# -# and value is a single-quote delimited value. -# -# For example: diff --git a/Tools/CVSROOT/editinfo b/Tools/CVSROOT/editinfo deleted file mode 100644 index d78886c15..000000000 --- a/Tools/CVSROOT/editinfo +++ /dev/null @@ -1,21 +0,0 @@ -# The "editinfo" file is used to allow verification of logging -# information. It works best when a template (as specified in the -# rcsinfo file) is provided for the logging procedure. Given a -# template with locations for, a bug-id number, a list of people who -# reviewed the code before it can be checked in, and an external -# process to catalog the differences that were code reviewed, the -# following test can be applied to the code: -# -# Making sure that the entered bug-id number is correct. -# Validating that the code that was reviewed is indeed the code being -# checked in (using the bug-id number or a seperate review -# number to identify this particular code set.). -# -# If any of the above test failed, then the commit would be aborted. -# -# Actions such as mailing a copy of the report to each reviewer are -# better handled by an entry in the loginfo file. -# -# One thing that should be noted is the the ALL keyword is not -# supported. There can be only one entry that matches a given -# repository. diff --git a/Tools/CVSROOT/loginfo b/Tools/CVSROOT/loginfo deleted file mode 100644 index 226e93771..000000000 --- a/Tools/CVSROOT/loginfo +++ /dev/null @@ -1,19 +0,0 @@ -# The "loginfo" file is used to control where "cvs commit" log information is -# sent. The first entry on a line is a regular expression which is tested -# against the directory that the change is being made to, relative to the -# $CVSROOT. For the first match that is found, the remainder of the line is a -# filter program that should expect log information on its standard input -# -# If the repository name does not match any of the regular expressions in the -# first field of this file, the "DEFAULT" line is used, if it is specified. -# -# If the name "ALL" appears as a regular expression it is always used -# in addition to the first matching regex or "DEFAULT". -# -# The filter program may use one and only one "%s" modifier (ala printf). If -# such a "%s" is specified in the filter program, a brief title is included -# (as one argument, enclosed in single quotes) showing the relative directory -# name and listing the modified file names. -# -# For example: -#DEFAULT (echo ""; who am i; echo %s; date; cat) >> $CVSROOT/CVSROOT/commitlog diff --git a/Tools/CVSROOT/modules b/Tools/CVSROOT/modules deleted file mode 100644 index cb9e9efc9..000000000 --- a/Tools/CVSROOT/modules +++ /dev/null @@ -1,26 +0,0 @@ -# Three different line formats are valid: -# key -a aliases... -# key [options] directory -# key [options] directory files... -# -# Where "options" are composed of: -# -i prog Run "prog" on "cvs commit" from top-level of module. -# -o prog Run "prog" on "cvs checkout" of module. -# -e prog Run "prog" on "cvs export" of module. -# -t prog Run "prog" on "cvs rtag" of module. -# -u prog Run "prog" on "cvs update" of module. -# -d dir Place module in directory "dir" instead of module name. -# -l Top-level directory only -- do not recurse. -# -# NOTE: If you change any of the "Run" options above, you'll have to -# release and re-checkout any working directories of these modules. -# -# And "directory" is a path to a directory relative to $CVSROOT. -# -# The "-a" option specifies an alias. An alias is interpreted as if -# everything on the right of the "-a" had been typed on the command line. -# -# You can encode a module within a module by using the special '&' -# character to interpose another module into the current module. This -# can be useful for creating a module that consists of many directories -# spread out over the entire source repository. diff --git a/Tools/CVSROOT/notify b/Tools/CVSROOT/notify deleted file mode 100644 index 34f0bc288..000000000 --- a/Tools/CVSROOT/notify +++ /dev/null @@ -1,12 +0,0 @@ -# The "notify" file controls where notifications from watches set by -# "cvs watch add" or "cvs edit" are sent. The first entry on a line is -# a regular expression which is tested against the directory that the -# change is being made to, relative to the $CVSROOT. If it matches, -# then the remainder of the line is a filter program that should contain -# one occurrence of %s for the user to notify, and information on its -# standard input. -# -# "ALL" or "DEFAULT" can be used in place of the regular expression. -# -# For example: -#ALL mail %s -s "CVS notification" diff --git a/Tools/CVSROOT/rcsinfo b/Tools/CVSROOT/rcsinfo deleted file mode 100644 index 49e59f4d0..000000000 --- a/Tools/CVSROOT/rcsinfo +++ /dev/null @@ -1,13 +0,0 @@ -# The "rcsinfo" file is used to control templates with which the editor -# is invoked on commit and import. -# -# The first entry on a line is a regular expression which is tested -# against the directory that the change is being made to, relative to the -# $CVSROOT. For the first match that is found, then the remainder of the -# line is the name of the file that contains the template. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. -# -# If the name "ALL" appears as a regular expression it is always used -# in addition to the first matching regex or "DEFAULT". diff --git a/Tools/CVSROOT/taginfo b/Tools/CVSROOT/taginfo deleted file mode 100644 index 274a46dd5..000000000 --- a/Tools/CVSROOT/taginfo +++ /dev/null @@ -1,20 +0,0 @@ -# The "taginfo" file is used to control pre-tag checks. -# The filter on the right is invoked with the following arguments: -# -# $1 -- tagname -# $2 -- operation "add" for tag, "mov" for tag -F, and "del" for tag -d -# $3 -- repository -# $4-> file revision [file revision ...] -# -# A non-zero exit of the filter program will cause the tag to be aborted. -# -# The first entry on a line is a regular expression which is tested -# against the directory that the change is being committed to, relative -# to the $CVSROOT. For the first match that is found, then the remainder -# of the line is the name of the filter to run. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. -# -# If the name "ALL" appears as a regular expression it is always used -# in addition to the first matching regex or "DEFAULT". diff --git a/Tools/Array/Makefile.am b/Tools/Construct/Array/Makefile.am similarity index 100% rename from Tools/Array/Makefile.am rename to Tools/Construct/Array/Makefile.am diff --git a/Tools/Array/array.cxx b/Tools/Construct/Array/array.cxx similarity index 99% rename from Tools/Array/array.cxx rename to Tools/Construct/Array/array.cxx index 2b7d2a625..ec99b8803 100644 --- a/Tools/Array/array.cxx +++ b/Tools/Construct/Array/array.cxx @@ -577,6 +577,9 @@ FGArray::~FGArray( void ) { // $Log$ +// Revision 1.1 1999/04/05 21:32:43 curt +// Initial revision +// // Revision 1.8 1999/04/05 02:15:23 curt // Make dem fitting more robust in cases when no dem file available. // diff --git a/Tools/Array/array.hxx b/Tools/Construct/Array/array.hxx similarity index 98% rename from Tools/Array/array.hxx rename to Tools/Construct/Array/array.hxx index 2ec9e2a51..22eb157d8 100644 --- a/Tools/Array/array.hxx +++ b/Tools/Construct/Array/array.hxx @@ -123,6 +123,9 @@ public: // $Log$ +// Revision 1.1 1999/04/05 21:32:43 curt +// Initial revision +// // Revision 1.6 1999/04/05 02:15:24 curt // Make dem fitting more robust in cases when no dem file available. // diff --git a/Tools/Array/testarray.cxx b/Tools/Construct/Array/testarray.cxx similarity index 100% rename from Tools/Array/testarray.cxx rename to Tools/Construct/Array/testarray.cxx diff --git a/Tools/Clipper/Makefile.am b/Tools/Construct/Clipper/Makefile.am similarity index 100% rename from Tools/Clipper/Makefile.am rename to Tools/Construct/Clipper/Makefile.am diff --git a/Tools/Clipper/clipper.cxx b/Tools/Construct/Clipper/clipper.cxx similarity index 99% rename from Tools/Clipper/clipper.cxx rename to Tools/Construct/Clipper/clipper.cxx index a088f0ffb..35526f3e9 100644 --- a/Tools/Clipper/clipper.cxx +++ b/Tools/Construct/Clipper/clipper.cxx @@ -273,6 +273,9 @@ bool FGClipper::clip_all(const point2d& min, const point2d& max) { // $Log$ +// Revision 1.1 1999/04/05 21:32:43 curt +// Initial revision +// // Revision 1.9 1999/03/31 23:46:38 curt // Debuggin output tweaks. // diff --git a/Tools/Clipper/clipper.hxx b/Tools/Construct/Clipper/clipper.hxx similarity index 97% rename from Tools/Clipper/clipper.hxx rename to Tools/Construct/Clipper/clipper.hxx index 469691a2a..598805631 100644 --- a/Tools/Clipper/clipper.hxx +++ b/Tools/Construct/Clipper/clipper.hxx @@ -109,6 +109,9 @@ public: // $Log$ +// Revision 1.1 1999/04/05 21:32:43 curt +// Initial revision +// // Revision 1.5 1999/03/19 00:26:19 curt // Fixed a clipping bug (polygons specified in wrong order). // Touched up a few compiler warnings. diff --git a/Tools/Clipper/testclipper.cxx b/Tools/Construct/Clipper/testclipper.cxx similarity index 97% rename from Tools/Clipper/testclipper.cxx rename to Tools/Construct/Clipper/testclipper.cxx index 2a0477b48..51d5a79fb 100644 --- a/Tools/Clipper/testclipper.cxx +++ b/Tools/Construct/Clipper/testclipper.cxx @@ -110,6 +110,9 @@ int main( int argc, char **argv ) { } // $Log$ +// Revision 1.1 1999/04/05 21:32:43 curt +// Initial revision +// // Revision 1.1 1999/03/13 23:51:36 curt // Renamed main.cxx to testclipper.cxx // Converted clipper routines to a class FGClipper. diff --git a/Tools/Combine/Makefile.am b/Tools/Construct/Combine/Makefile.am similarity index 100% rename from Tools/Combine/Makefile.am rename to Tools/Construct/Combine/Makefile.am diff --git a/Tools/Combine/genfans.cxx b/Tools/Construct/Combine/genfans.cxx similarity index 99% rename from Tools/Combine/genfans.cxx rename to Tools/Construct/Combine/genfans.cxx index 856a3d79c..e57d6563e 100644 --- a/Tools/Combine/genfans.cxx +++ b/Tools/Construct/Combine/genfans.cxx @@ -244,6 +244,9 @@ double FGGenFans::ave_size() { // $Log$ +// Revision 1.1 1999/04/05 21:32:43 curt +// Initial revision +// // Revision 1.6 1999/04/05 02:16:02 curt // Fixed a compiler warning. // diff --git a/Tools/Combine/genfans.hxx b/Tools/Construct/Combine/genfans.hxx similarity index 97% rename from Tools/Combine/genfans.hxx rename to Tools/Construct/Combine/genfans.hxx index 55af05d70..12c1367e0 100644 --- a/Tools/Combine/genfans.hxx +++ b/Tools/Construct/Combine/genfans.hxx @@ -80,6 +80,9 @@ public: // $Log$ +// Revision 1.1 1999/04/05 21:32:43 curt +// Initial revision +// // Revision 1.1 1999/03/29 13:08:35 curt // Initial revision. // diff --git a/Tools/GenOutput/Makefile.am b/Tools/Construct/GenOutput/Makefile.am similarity index 100% rename from Tools/GenOutput/Makefile.am rename to Tools/Construct/GenOutput/Makefile.am diff --git a/Tools/GenOutput/genobj.cxx b/Tools/Construct/GenOutput/genobj.cxx similarity index 99% rename from Tools/GenOutput/genobj.cxx rename to Tools/Construct/GenOutput/genobj.cxx index fc3cc3b68..dfe83a14d 100644 --- a/Tools/GenOutput/genobj.cxx +++ b/Tools/Construct/GenOutput/genobj.cxx @@ -432,6 +432,9 @@ int FGGenOutput::write( const string& base, const FGBucket& b ) { // $Log$ +// Revision 1.1 1999/04/05 21:32:43 curt +// Initial revision +// // Revision 1.10 1999/03/31 23:46:57 curt // Debugging output tweaks. // diff --git a/Tools/GenOutput/genobj.hxx b/Tools/Construct/GenOutput/genobj.hxx similarity index 98% rename from Tools/GenOutput/genobj.hxx rename to Tools/Construct/GenOutput/genobj.hxx index 55f984452..18f9dfb2a 100644 --- a/Tools/GenOutput/genobj.hxx +++ b/Tools/Construct/GenOutput/genobj.hxx @@ -131,6 +131,9 @@ public: // $Log$ +// Revision 1.1 1999/04/05 21:32:43 curt +// Initial revision +// // Revision 1.9 1999/03/31 23:46:58 curt // Debugging output tweaks. // diff --git a/Tools/Main/Makefile.am b/Tools/Construct/Main/Makefile.am similarity index 100% rename from Tools/Main/Makefile.am rename to Tools/Construct/Main/Makefile.am diff --git a/Tools/Main/construct_types.hxx b/Tools/Construct/Main/construct_types.hxx similarity index 96% rename from Tools/Main/construct_types.hxx rename to Tools/Construct/Main/construct_types.hxx index 095e48c56..c29fdcf75 100644 --- a/Tools/Main/construct_types.hxx +++ b/Tools/Construct/Main/construct_types.hxx @@ -53,6 +53,9 @@ typedef point_list::const_iterator const_point_list_iterator; // $Log$ +// Revision 1.1 1999/04/05 21:32:43 curt +// Initial revision +// // Revision 1.1 1999/03/29 13:19:44 curt // Initial revision. // diff --git a/Tools/Triangulate/Makefile.am b/Tools/Construct/Triangulate/Makefile.am similarity index 100% rename from Tools/Triangulate/Makefile.am rename to Tools/Construct/Triangulate/Makefile.am diff --git a/Tools/Triangulate/triangle.cxx b/Tools/Construct/Triangulate/triangle.cxx similarity index 99% rename from Tools/Triangulate/triangle.cxx rename to Tools/Construct/Triangulate/triangle.cxx index 38b8bf1ac..36dcde477 100644 --- a/Tools/Triangulate/triangle.cxx +++ b/Tools/Construct/Triangulate/triangle.cxx @@ -405,6 +405,9 @@ int FGTriangle::run_triangulate() { // $Log$ +// Revision 1.1 1999/04/05 21:32:43 curt +// Initial revision +// // Revision 1.16 1999/04/05 02:17:11 curt // Dynamically update "error" until the resulting tile data scales within // a lower and upper bounds. diff --git a/Tools/Triangulate/triangle.hxx b/Tools/Construct/Triangulate/triangle.hxx similarity index 98% rename from Tools/Triangulate/triangle.hxx rename to Tools/Construct/Triangulate/triangle.hxx index 676f5056c..997cd9e56 100644 --- a/Tools/Triangulate/triangle.hxx +++ b/Tools/Construct/Triangulate/triangle.hxx @@ -93,6 +93,9 @@ public: // $Log$ +// Revision 1.1 1999/04/05 21:32:43 curt +// Initial revision +// // Revision 1.11 1999/04/05 02:17:12 curt // Dynamically update "error" until the resulting tile data scales within // a lower and upper bounds. diff --git a/Tools/Triangulate/trieles.cxx b/Tools/Construct/Triangulate/trieles.cxx similarity index 93% rename from Tools/Triangulate/trieles.cxx rename to Tools/Construct/Triangulate/trieles.cxx index 406a19a91..f97a526a0 100644 --- a/Tools/Triangulate/trieles.cxx +++ b/Tools/Construct/Triangulate/trieles.cxx @@ -26,6 +26,9 @@ // $Log$ +// Revision 1.1 1999/04/05 21:32:43 curt +// Initial revision +// // Revision 1.1 1999/03/22 23:58:57 curt // Initial revision. // diff --git a/Tools/Triangulate/trieles.hxx b/Tools/Construct/Triangulate/trieles.hxx similarity index 97% rename from Tools/Triangulate/trieles.hxx rename to Tools/Construct/Triangulate/trieles.hxx index 2d22c7db5..2a3fcc7cb 100644 --- a/Tools/Triangulate/trieles.hxx +++ b/Tools/Construct/Triangulate/trieles.hxx @@ -75,6 +75,9 @@ typedef triele_list::const_iterator const_triele_list_iterator; // $Log$ +// Revision 1.1 1999/04/05 21:32:43 curt +// Initial revision +// // Revision 1.3 1999/03/27 05:30:14 curt // Handle corner nodes separately from the rest of the fitted nodes. // Add fitted nodes in after corners and polygon nodes since the fitted nodes diff --git a/Tools/Triangulate/trinodes.cxx b/Tools/Construct/Triangulate/trinodes.cxx similarity index 98% rename from Tools/Triangulate/trinodes.cxx rename to Tools/Construct/Triangulate/trinodes.cxx index 50e7df7ee..2270c2712 100644 --- a/Tools/Triangulate/trinodes.cxx +++ b/Tools/Construct/Triangulate/trinodes.cxx @@ -99,6 +99,9 @@ int FGTriNodes::course_add( const Point3D& p ) { // $Log$ +// Revision 1.1 1999/04/05 21:32:43 curt +// Initial revision +// // Revision 1.6 1999/03/27 05:30:15 curt // Handle corner nodes separately from the rest of the fitted nodes. // Add fitted nodes in after corners and polygon nodes since the fitted nodes diff --git a/Tools/Triangulate/trinodes.hxx b/Tools/Construct/Triangulate/trinodes.hxx similarity index 98% rename from Tools/Triangulate/trinodes.hxx rename to Tools/Construct/Triangulate/trinodes.hxx index f7c5fdd55..af4d0d9c0 100644 --- a/Tools/Triangulate/trinodes.hxx +++ b/Tools/Construct/Triangulate/trinodes.hxx @@ -118,6 +118,9 @@ inline bool FGTriNodes::course_close_enough( const Point3D& p1, // $Log$ +// Revision 1.1 1999/04/05 21:32:43 curt +// Initial revision +// // Revision 1.8 1999/04/05 02:17:13 curt // Dynamically update "error" until the resulting tile data scales within // a lower and upper bounds. diff --git a/Tools/Triangulate/tripoly.cxx b/Tools/Construct/Triangulate/tripoly.cxx similarity index 98% rename from Tools/Triangulate/tripoly.cxx rename to Tools/Construct/Triangulate/tripoly.cxx index d01bb8b40..376ba93dc 100644 --- a/Tools/Triangulate/tripoly.cxx +++ b/Tools/Construct/Triangulate/tripoly.cxx @@ -180,6 +180,9 @@ void FGTriPoly::calc_point_inside( const FGTriNodes& trinodes ) { // $Log$ +// Revision 1.1 1999/04/05 21:32:43 curt +// Initial revision +// // Revision 1.2 1999/03/29 13:11:11 curt // Shuffled stl type names a bit. // Began adding support for tri-fanning (or maybe other arrangments too.) diff --git a/Tools/Triangulate/tripoly.hxx b/Tools/Construct/Triangulate/tripoly.hxx similarity index 97% rename from Tools/Triangulate/tripoly.hxx rename to Tools/Construct/Triangulate/tripoly.hxx index 0e156dbae..34c59491d 100644 --- a/Tools/Triangulate/tripoly.hxx +++ b/Tools/Construct/Triangulate/tripoly.hxx @@ -82,6 +82,9 @@ typedef tripoly_list::const_iterator const_tripoly_list_iterator; // $Log$ +// Revision 1.1 1999/04/05 21:32:43 curt +// Initial revision +// // Revision 1.5 1999/03/29 13:11:12 curt // Shuffled stl type names a bit. // Began adding support for tri-fanning (or maybe other arrangments too.) diff --git a/Tools/Triangulate/trisegs.cxx b/Tools/Construct/Triangulate/trisegs.cxx similarity index 98% rename from Tools/Triangulate/trisegs.cxx rename to Tools/Construct/Triangulate/trisegs.cxx index d05c6ccf1..4f44b13a6 100644 --- a/Tools/Triangulate/trisegs.cxx +++ b/Tools/Construct/Triangulate/trisegs.cxx @@ -179,6 +179,9 @@ void FGTriSegments::unique_divide_and_add( const point_list& nodes, // $Log$ +// Revision 1.1 1999/04/05 21:32:43 curt +// Initial revision +// // Revision 1.6 1999/04/03 05:22:59 curt // Found a bug in dividing and adding unique verticle segments which could // cause the triangulator to end up in an infinite loop. Basically the code diff --git a/Tools/Triangulate/trisegs.hxx b/Tools/Construct/Triangulate/trisegs.hxx similarity index 98% rename from Tools/Triangulate/trisegs.hxx rename to Tools/Construct/Triangulate/trisegs.hxx index 2766bcf15..85f9a230e 100644 --- a/Tools/Triangulate/trisegs.hxx +++ b/Tools/Construct/Triangulate/trisegs.hxx @@ -118,6 +118,9 @@ public: // $Log$ +// Revision 1.1 1999/04/05 21:32:43 curt +// Initial revision +// // Revision 1.4 1999/04/05 02:17:14 curt // Dynamically update "error" until the resulting tile data scales within // a lower and upper bounds. diff --git a/Tools/FixNode/Makefile.am b/Tools/FixNode/Makefile.am deleted file mode 100644 index a245e6ac0..000000000 --- a/Tools/FixNode/Makefile.am +++ /dev/null @@ -1,95 +0,0 @@ -#--------------------------------------------------------------------------- -# Makefile -# -# Written by Curtis Olson, started October 1997. -# -# Copyright (C) 1997 - 1998 Curtis L. Olson - curt@me.umn.edu -# -# 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. -# -# $Id$ -# (Log is kept at end of this file) -#--------------------------------------------------------------------------- - - -bin_PROGRAMS = fixnode - -fixnode_SOURCES = \ - fixnode.cxx fixnode.hxx \ - main.cxx - -fixnode_LDADD = \ - $(top_builddir)/Tools/Lib/DEM/libDEM.a \ - $(top_builddir)/Lib/Bucket/libBucket.a \ - $(top_builddir)/Lib/Misc/libMisc.a \ - $(top_builddir)/Lib/zlib/libz.a \ - $(base_LIBS) - -INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib -I$(top_builddir)/Tools/Lib - -# We can't build this with "-O2" (optimization) since this causes a seg fault -# I haven't found a way to strip this out of the CXXFLAGS, so I'm just -# setting it to "-g" -# CXXFLAGS = -g - - -#--------------------------------------------------------------------------- -# $Log$ -# Revision 1.10 1999/03/17 23:50:59 curt -# Removed forced -g compiler flag. -# -# Revision 1.9 1999/03/08 22:00:45 curt -# Lots of directory layout reorganization. -# -# Revision 1.8 1999/02/01 21:09:30 curt -# Moving location of Lib/DEM/ to Tools/DEM/ -# -# Revision 1.7 1998/11/04 23:01:51 curt -# Changes to the automake/autoconf system to reduce the number of libraries -# that are unnecessarily linked into the various executables. -# -# Revision 1.6 1998/09/19 20:43:50 curt -# C++-ified and STL-ified the code. Combined triload.* and fixnode.* into -# a single file. -# -# Revision 1.5 1998/09/19 18:01:26 curt -# Support for changes to libDEM.a -# -# Revision 1.4 1998/07/30 23:49:24 curt -# Removed libtool support. -# -# Revision 1.3 1998/04/18 04:02:54 curt -# Added zlib support in placed and other misc. tweaks. -# -# Revision 1.2 1998/04/14 02:26:02 curt -# Code reorganizations. Added a Lib/ directory for more general libraries. -# -# Revision 1.1 1998/04/08 23:05:54 curt -# Adopted Gnu automake/autoconf system. -# -# Revision 1.4 1998/04/06 21:09:44 curt -# Additional win32 support. -# Fixed a bad bug in dem file parsing that was causing the output to be -# flipped about x = y. -# -# Revision 1.3 1998/03/19 02:50:19 curt -# Updated to support -lDEM class. -# -# Revision 1.2 1998/01/21 02:55:50 curt -# Incorporated new make system from Bob Kuehne . -# -# Revision 1.1 1997/11/27 00:17:32 curt -# Initial revision. -# diff --git a/Tools/FixNode/fixnode.cxx b/Tools/FixNode/fixnode.cxx deleted file mode 100644 index 5269ac459..000000000 --- a/Tools/FixNode/fixnode.cxx +++ /dev/null @@ -1,161 +0,0 @@ -// fixnode.cxx -- traverse the node file and fix the elevation of all the new -// interpolated points. -// -// Written by Curtis Olson, started November 1997. -// -// Copyright (C) 1997 Curtis L. Olson - curt@me.umn.edu -// -// 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. -// -// $Id$ -// (Log is kept at end of this file) - - - -#include -#include -#include -#include - -#ifdef HAVE_STDLIB_H -# include -#endif // HAVE_STDLIB_H - -#include - -#include "fixnode.hxx" - - -// load extra nodes -void load_extra(const string& filename, container& extra_list) { -} - - -// load the node information -void load_nodes(const string& filename, container& node_list) { - Point3D node; - int dim, junk1, junk2; - int i, nodecount; - - cout << "Loading node file: " << filename << " ...\n"; - - fg_gzifstream in( filename ); - if ( !in ) { - cout << "Cannot open " + filename + "\n"; - // exit immediately assuming an airport file for this tile - // doesn't exist. - exit(-1); - } - - // Read header line - in >> nodecount >> dim >> junk1 >> junk2; - cout << " Expecting " << nodecount << " nodes\n"; - - // start with an empty list :-) - node_list.erase( node_list.begin(), node_list.end() ); - - in >> skipcomment; - while ( ! in.eof() ) { - in >> junk1 >> node >> junk2; - in >> skipcomment; - node_list.push_back(node); - } -} - - -// fix the node elevations -void fix_nodes( const string& filename, fgDEM& dem, container& node_list ) -{ - string toname; - FILE *fd; - int i; - - cout << "Fixing up node elevations\n"; - - iterator current; - iterator last = node_list.end(); - for ( current = node_list.begin() ; current != last ; ++current ) { - // printf("Current: %d %.2f %.2f %.2f\n", i, nodes[i][0], - // nodes[i][1], nodes[i][2]); - - (*current).setz( - dem.interpolate_altitude( (*current).x(), - (*current).y() ) ); - - // printf("Fixed: %d %.2f %.2f %.2f\n", i, nodes[i][0], - // nodes[i][1], nodes[i][2]); - } - - - toname = filename + ".orig"; - cout << "Moving " + filename + " to " + toname + "\n"; - rename( filename.c_str(), toname.c_str() ); - - cout << "Saving new node file: " + filename + "\n"; - - fd = fopen(filename.c_str(), "w"); - - fprintf( fd, "%d 2 1 0\n", node_list.size() ); - - i = 1; - for ( current = node_list.begin() ; current != last ; ++current ) { - fprintf( fd, "%d %.2f %.2f %.2f 0\n", i, - (*current).x(), (*current).y(), (*current).z() ); - ++i; - } - - fclose(fd); -} - - -// $Log$ -// Revision 1.7 1998/11/06 21:33:55 curt -// Updates to go along with changes in fgstream. -// -// Revision 1.6 1998/10/20 15:49:22 curt -// Converted to Point3D class. -// -// Revision 1.5 1998/09/22 23:49:10 curt -// eliminated a left over #include -// -// Revision 1.4 1998/09/19 20:43:52 curt -// C++-ified and STL-ified the code. Combined triload.* and fixnode.* into -// a single file. -// -// Revision 1.3 1998/07/22 21:46:40 curt -// Fixed a bug that was triggering a seg fault. -// -// Revision 1.2 1998/04/14 02:26:03 curt -// Code reorganizations. Added a Lib/ directory for more general libraries. -// -// Revision 1.1 1998/04/08 23:05:56 curt -// Adopted Gnu automake/autoconf system. -// -// Revision 1.5 1998/03/19 02:50:19 curt -// Updated to support -lDEM class. -// -// Revision 1.4 1998/03/03 16:00:57 curt -// More c++ compile tweaks. -// -// Revision 1.3 1998/01/09 23:03:08 curt -// Restructured to split 1deg x 1deg dem's into 64 subsections. -// -// Revision 1.2 1997/12/02 13:12:07 curt -// Updated to fix every node. -// -// Revision 1.1 1997/11/27 00:17:33 curt -// Initial revision. -// - diff --git a/Tools/FixNode/fixnode.hxx b/Tools/FixNode/fixnode.hxx deleted file mode 100644 index 80b6eb2b6..000000000 --- a/Tools/FixNode/fixnode.hxx +++ /dev/null @@ -1,95 +0,0 @@ -// fixnode.hxx -- traverse the node file and fix the elevation of all the new -// interpolated points. -// -// Written by Curtis Olson, started November 1997. -// -// Copyright (C) 1997 Curtis L. Olson - curt@infoplane.com -// -// 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. -// -// $Id$ -// (Log is kept at end of this file) -// - - -#ifndef _FIXNODE_H -#define _FIXNODE_H - - -#include -#include -#include - -#include -#include "Include/fg_stl_config.h" - -#ifdef NEEDNAMESPACESTD -using namespace std; -#endif - -#include -#include - - -typedef vector < Point3D > container; -typedef container::iterator iterator; -typedef container::const_iterator const_iterator; - - -// Initialize a new mesh structure -void load_nodes(const string& basename, container& node_list); - - -// load the extra nodes. These are always the first n nodes of the -// .node file. (??? These will be tagged with a code indicating what -// needs to be done with this node's elevation such as adjust to local -// DEM elevation, or massage the local DEM points to match this -// elevation point. ???) -void load_extra_nodes(const string& filename, container& node_list); - - -// fix the node elevations -void fix_nodes( const string& basename, fgDEM& dem, container& node_list ); - - -#endif // _FIXNODE_H - - -// $Log$ -// Revision 1.4 1998/10/20 15:49:23 curt -// Converted to Point3D class. -// -// Revision 1.3 1998/09/19 20:43:53 curt -// C++-ified and STL-ified the code. Combined triload.* and fixnode.* into -// a single file. -// -// Revision 1.2 1998/07/22 21:46:41 curt -// Fixed a bug that was triggering a seg fault. -// -// Revision 1.1 1998/04/08 23:05:56 curt -// Adopted Gnu automake/autoconf system. -// -// Revision 1.4 1998/03/19 02:50:19 curt -// Updated to support -lDEM class. -// -// Revision 1.3 1998/03/03 16:00:58 curt -// More c++ compile tweaks. -// -// Revision 1.2 1997/12/02 13:12:07 curt -// Updated to fix every node. -// -// Revision 1.1 1997/11/27 00:17:33 curt -// Initial revision. -// diff --git a/Tools/FixNode/main.cxx b/Tools/FixNode/main.cxx deleted file mode 100644 index 68e540802..000000000 --- a/Tools/FixNode/main.cxx +++ /dev/null @@ -1,146 +0,0 @@ -// main.cxx -- read in a .node file and fix the z values of the interpolated -// points -// -// Written by Curtis Olson, started November 1997. -// -// Copyright (C) 1997 Curtis L. Olson - curt@infoplane.com -// -// 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. -// -// $Id$ -// (Log is kept at end of this file) -// - - -#include -#include -// #include -#include -#include - -#ifdef HAVE_STDLIB_H -# include -#endif // HAVE_STDLIB_H - -#include - -#include "fixnode.hxx" - - -// find all the matching files in the specified directory and fix them -void process_files(const string& root_path, fgDEM& dem) { - container node_list; - DIR *d; - struct dirent *de; - string file_path; - char *ptr; - int len; - - if ( (d = opendir( root_path.c_str() )) == NULL ) { - cout << "cannot open directory " + root_path + "\n"; - exit(-1); - } - - while ( (de = readdir(d)) != NULL ) { - len = strlen(de->d_name); - if ( len > 7 ) { - ptr = de->d_name; - ptr += (len - 7); - // printf("--> %s \n", ptr); - - if ( strcmp(ptr, ".1.node") == 0 ) { - file_path = root_path + "/" + de->d_name; - cout << "File = " + file_path + "\n"; - - // load the input data files - load_nodes(file_path, node_list); - - fix_nodes(file_path, dem, node_list); - } - } - } -} - - -// main -int main(int argc, char **argv) { - fgDEM dem; - string demfile, root_path; - - if ( argc != 3 ) { - cout << "Usage " << argv[0] << " demfile root_path\n"; - exit(-1); - } - - cout << "Starting fixnode\n"; - - demfile = argv[1]; - root_path = argv[2]; - - // load the corresponding dem file so we can interpolate elev values - dem.open(demfile); - dem.parse(); - dem.close(); - - // process all the *.1.node files in the specified directory - process_files(root_path, dem); - - return(0); -} - - -// $Log$ -// Revision 1.7 1998/09/19 20:43:54 curt -// C++-ified and STL-ified the code. Combined triload.* and fixnode.* into -// a single file. -// -// Revision 1.6 1998/09/19 18:01:27 curt -// Support for changes to libDEM.a -// -// Revision 1.5 1998/07/22 21:46:41 curt -// Fixed a bug that was triggering a seg fault. -// -// Revision 1.4 1998/06/27 16:55:24 curt -// Changed include order for -// -// Revision 1.3 1998/04/26 05:02:06 curt -// Added #ifdef HAVE_STDLIB_H -// -// Revision 1.2 1998/04/14 02:26:04 curt -// Code reorganizations. Added a Lib/ directory for more general libraries. -// -// Revision 1.1 1998/04/08 23:05:57 curt -// Adopted Gnu automake/autoconf system. -// -// Revision 1.6 1998/04/06 21:09:44 curt -// Additional win32 support. -// Fixed a bad bug in dem file parsing that was causing the output to be -// flipped about x = y. -// -// Revision 1.5 1998/03/19 02:50:20 curt -// Updated to support -lDEM class. -// -// Revision 1.4 1998/03/03 16:00:58 curt -// More c++ compile tweaks. -// -// Revision 1.3 1998/01/09 23:03:08 curt -// Restructured to split 1deg x 1deg dem's into 64 subsections. -// -// Revision 1.2 1997/12/02 13:12:07 curt -// Updated to fix every node. -// -// Revision 1.1 1997/11/27 00:17:34 curt -// Initial revision. -// diff --git a/Tools/FixObj/Makefile.am b/Tools/FixObj/Makefile.am deleted file mode 100644 index 7ced91cc9..000000000 --- a/Tools/FixObj/Makefile.am +++ /dev/null @@ -1,69 +0,0 @@ -#--------------------------------------------------------------------------- -# Makefile -# -# Written by Curtis Olson, started October 1997. -# -# Copyright (C) 1997 - 1998 Curtis L. Olson - curt@me.umn.edu -# -# 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. -# -# $Id$ -# (Log is kept at end of this file) -#--------------------------------------------------------------------------- - - -bin_PROGRAMS = fixobj - -fixobj_SOURCES = main.cxx obj.cxx obj.hxx - -fixobj_LDADD = \ - $(top_builddir)/Lib/Math/libMath.a \ - $(top_builddir)/Lib/Debug/libDebug.a \ - $(top_builddir)/Lib/zlib/libz.a \ - $(base_LIBS) - -INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib - - -#--------------------------------------------------------------------------- -# $Log$ -# Revision 1.7 1998/11/04 23:01:53 curt -# Changes to the automake/autoconf system to reduce the number of libraries -# that are unnecessarily linked into the various executables. -# -# Revision 1.6 1998/07/30 23:49:25 curt -# Removed libtool support. -# -# Revision 1.5 1998/06/08 17:11:44 curt -# Renamed *.[ch] to *.[ch]xx -# -# Revision 1.4 1998/04/24 00:44:05 curt -# Added zlib support. -# -# Revision 1.3 1998/04/18 04:01:02 curt -# Now use libMath rather than having local copies of math routines. -# -# Revision 1.2 1998/04/14 02:26:05 curt -# Code reorganizations. Added a Lib/ directory for more general libraries. -# -# Revision 1.1 1998/04/08 23:19:35 curt -# Adopted Gnu automake/autoconf system. -# -# Revision 1.2 1998/01/21 02:55:53 curt -# Incorporated new make system from Bob Kuehne . -# -# Revision 1.1 1997/12/08 19:28:54 curt -# Initial revision. -# diff --git a/Tools/FixObj/main.cxx b/Tools/FixObj/main.cxx deleted file mode 100644 index bf117a10c..000000000 --- a/Tools/FixObj/main.cxx +++ /dev/null @@ -1,57 +0,0 @@ -// main.cxx -- read and fix the stripping order of a .obj file -// -// Written by Curtis Olson, started December 1997. -// -// Copyright (C) 1997 - 1998 Curtis L. Olson - curt@me.umn.edu -// -// 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. -// -// $Id$ -// (Log is kept at end of this file) - - -#include - -#include "obj.hxx" - - -int main(int argc, char **argv) { - char infile[256], outfile[256]; - - if ( argc != 3 ) { - printf("Usage %s: infile outfile\n", argv[0]); - } - - strcpy(infile, argv[1]); - strcpy(outfile, argv[2]); - - // load the input data files - obj_fix(infile, outfile); - - return(0); -} - - -// $Log$ -// Revision 1.1 1998/06/08 17:11:45 curt -// Renamed *.[ch] to *.[ch]xx -// -// Revision 1.2 1998/01/09 23:03:12 curt -// Restructured to split 1deg x 1deg dem's into 64 subsections. -// -// Revision 1.1 1997/12/08 19:28:54 curt -// Initial revision. -// - diff --git a/Tools/FixObj/obj.cxx b/Tools/FixObj/obj.cxx deleted file mode 100644 index 4239a1891..000000000 --- a/Tools/FixObj/obj.cxx +++ /dev/null @@ -1,647 +0,0 @@ -// obj.cxx -- routines to handle WaveFront .obj format files. -// -// Written by Curtis Olson, started October 1997. -// -// Copyright (C) 1997 - 1998 Curtis L. Olson - curt@me.umn.edu -// -// 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. -// -// $Id$ -// (Log is kept at end of this file) - - -#include -#include -#include - -#include -#include "Include/compiler.h" - -#ifdef NEEDNAMESPACESTD -using namespace std; -#endif - -#include "obj.hxx" - -#include -#include - - -typedef vector < Point3D > container3; -typedef container3::iterator iterator3; -typedef container3::const_iterator const_iterator3; - - -// what do ya' know, here's some global variables -container3 nodes; -container3 normals; -static int faces[MAXNODES][3]; -int vncount, fcount; - -static int ccw_list[MAXNODES]; -int ccw_list_ptr; - -static int cw_list[MAXNODES]; -int cw_list_ptr; - -FILE *in, *out; - -Point3D ref; - - -// some simple list routines - -// reset the list -void list_init(int *list_ptr) { - *list_ptr = 0; -} - - -// add to list -void list_add(int *list, int *list_ptr, int node) { - if ( *list_ptr >= MAXNODES ) { - printf("ERROR: list overflow in list_add()\n"); - exit(-1); - } - - list[*list_ptr] = node; - *list_ptr += 1; - - // printf("list pointer = %d adding %d\n", *list_ptr, node); -} - - -// fix the cw list and append to ccw_list -void fix_cw_list(int *list, int list_ptr) { - int i, j, len; - - if ( list_ptr < 3 ) { - printf("List is empty ... skipping\n"); - return; - } - - printf("Fixing cw list, size = %d\n", list_ptr); - - i = 0; - while ( i < list_ptr ) { - // do next strip - - // find length - len = 0; - // scan rest of strip (until -1) - while ( ((i+len) < list_ptr) && (list[i+len] != -1) ) { - // printf("len = %d item = %d\n", len, list[i+len] ); - len++; - } - // printf(" Final length = %d\n", len); - - if ( (len % 2) != 0 ) { - // if length is odd, just reverse order of nodes to - // reverse winding - if ( ccw_list_ptr ) { - list_add(ccw_list, &ccw_list_ptr, -1); - } - for ( j = i + len - 1; j >= i; j-- ) { - // printf(" odd -> item = %d\n", list[j] ); - list_add(ccw_list, &ccw_list_ptr, list[j]); - } - } else { - // if length is even, reverse order of (n-1) nodes to - // reverse winding, and create an orphan triangle for the - // last "nth" node - if ( ccw_list_ptr ) { - list_add(ccw_list, &ccw_list_ptr, -1); - } - for ( j = i + len - 2; j >= i; j-- ) { - // printf(" even -> item = %d\n", list[j] ); - list_add(ccw_list, &ccw_list_ptr, list[j]); - } - - // printf(" even bonus -> item = %d\n", list[i + len - 1] ); - // printf(" even bonus -> item = %d\n", list[i + len - 2] ); - // printf(" even bonus -> item = %d\n", list[i + len - 3] ); - list_add(ccw_list, &ccw_list_ptr, -1); - list_add(ccw_list, &ccw_list_ptr, list[i + len - 3]); - list_add(ccw_list, &ccw_list_ptr, list[i + len - 2]); - list_add(ccw_list, &ccw_list_ptr, list[i + len - 1]); - } - - i += len + 1; - } -} - - -void dump_global_bounds( void ) { - double dist_squared, radius, radius_squared; - - radius = 0.0; - - fprintf(out, "\n"); - - - iterator3 current = nodes.begin(); - iterator3 last = nodes.end(); - - // skip first dummy node - ++current; - - for ( ; current != last; ++current ) { - dist_squared = ref.distance3Dsquared(*current); - // cout << "node = " << *current << " dist = " << dist_squared << endl; - - if ( dist_squared > radius_squared ) { - radius_squared = dist_squared; - } - } - - radius = sqrt(radius_squared); - - fprintf( out, - "gbs %.5f %.5f %.5f %.2f\n", - ref.x(), ref.y(), ref.z(), radius); -} - - -// dump nodes -void dump_nodes( void ) { - Point3D p; - - fprintf(out, "\n"); - - iterator3 current = nodes.begin(); - iterator3 last = nodes.end(); - - // skip first dummy node - ++current; - - for ( ; current != last; ++current ) { - p = *current - ref; - fprintf( out, "v %.5f %.5f %.5f\n", p.x(), p.y(), p.z() ); - } -} - - -// dump normals -void dump_normals( void ) { - Point3D p; - - fprintf(out, "\n"); - - iterator3 current = normals.begin(); - iterator3 last = normals.end(); - - // skip first dummy normal - ++current; - - for ( ; current != last; ++current ) { - p = *current; - fprintf(out, "vn %.5f %.5f %.5f\n", p.x(), p.y(), p.z() ); - } -} - - -// dump faces -void dump_faces( void ) { - Point3D p; - int i, n1, n2, n3; - double xmax, xmin, ymax, ymin, zmax, zmin, dist, radius; - - fprintf(out, "\n"); - for ( i = 1; i < fcount; i++ ) { - n1 = faces[i][0]; - n2 = faces[i][1]; - n3 = faces[i][2]; - - // calc center of face - xmin = xmax = nodes[n1].x(); - ymin = ymax = nodes[n1].y(); - zmin = zmax = nodes[n1].z(); - - if ( nodes[n2].x() < xmin ) { xmin = nodes[n2].x(); } - if ( nodes[n2].x() > xmax ) { xmax = nodes[n2].x(); } - if ( nodes[n2].y() < ymin ) { ymin = nodes[n2].y(); } - if ( nodes[n2].y() > ymax ) { ymax = nodes[n2].y(); } - if ( nodes[n2].z() < zmin ) { zmin = nodes[n2].z(); } - if ( nodes[n2].z() > zmax ) { zmax = nodes[n2].z(); } - - if ( nodes[n3].x() < xmin ) { xmin = nodes[n3].x(); } - if ( nodes[n3].x() > xmax ) { xmax = nodes[n3].x(); } - if ( nodes[n3].y() < ymin ) { ymin = nodes[n3].y(); } - if ( nodes[n3].y() > ymax ) { ymax = nodes[n3].y(); } - if ( nodes[n3].z() < zmin ) { zmin = nodes[n3].z(); } - if ( nodes[n3].z() > zmax ) { zmax = nodes[n3].z(); } - - p = Point3D( (xmin + xmax) / 2.0, - (ymin + ymax) / 2.0, - (zmin + zmax) / 2.0 ); - - // calc bounding radius - radius = p.distance3D(nodes[n1]); - - dist = p.distance3D(nodes[n2]); - if ( dist > radius ) { radius = dist; } - - dist = p.distance3D(nodes[n3]); - if ( dist > radius ) { radius = dist; } - - // output data - fprintf(out, "bs %.2f %.2f %.2f %.2f\n", p.x(), p.y(), p.z(), radius); - fprintf(out, "f %d %d %d\n", n1, n2, n3); - } -} - - -// dump list -void dump_list(int *list, int list_ptr) { - Point3D p; - double xmax, xmin, ymax, ymin, zmax, zmin, dist_squared, radius_squared; - double radius; - int i, j, len, n; - - if ( list_ptr < 3 ) { - printf("List is empty ... skipping\n"); - return; - } - - printf("Dumping list, size = %d\n", list_ptr); - - i = 0; - while ( i < list_ptr ) { - // do next strip - - if ( (i % 2) == 0 ) { - fprintf(out, "\nusemtl desert1\n"); - } else { - fprintf(out, "\nusemtl desert2\n"); - } - - // find length of next tri strip - len = 0; - // scan rest of strip (until -1) - while ( ((i+len) < list_ptr) && (list[i+len] != -1) ) { - // printf("len = %d item = %d\n", len, list[i+len] ); - len++; - } - // printf("strip length = %d\n", len); - - // calc center of face - n = list[i]; - xmin = xmax = nodes[n].x(); - ymin = ymax = nodes[n].y(); - zmin = zmax = nodes[n].z(); - // printf("%.2f %.2f %.2f\n", nodes[n].x(), nodes[n].y(), nodes[n].z()); - - for ( j = i + 1; j < i + len; j++ ) { - // printf("j = %d\n", j); - n = list[j]; - if ( nodes[n].x() < xmin ) { xmin = nodes[n].x(); } - if ( nodes[n].x() > xmax ) { xmax = nodes[n].x(); } - if ( nodes[n].y() < ymin ) { ymin = nodes[n].y(); } - if ( nodes[n].y() > ymax ) { ymax = nodes[n].y(); } - if ( nodes[n].z() < zmin ) { zmin = nodes[n].z(); } - if ( nodes[n].z() > zmax ) { zmax = nodes[n].z(); } - // printf("%.2f %.2f %.2f\n", nodes[n].x(), nodes[n].y(), nodes[n].z()); - } - p = Point3D( (xmin + xmax) / 2.0, - (ymin + ymax) / 2.0, - (zmin + zmax) / 2.0 ); - // printf("center = %.2f %.2f %.2f\n", p.x(), p.y(), p.z()); - - // calc bounding radius - n = list[i]; - radius_squared = p.distance3Dsquared(nodes[n]); - - for ( j = i + 1; j < i + len; j++ ) { - n = list[j]; - dist_squared = p.distance3Dsquared(nodes[n]); - if ( dist_squared > radius_squared ) { - radius_squared = dist_squared; - } - } - radius = sqrt(radius_squared); - - // printf("radius = %.2f\n", radius); - - // dump bounding sphere and header - fprintf(out, "bs %.2f %.2f %.2f %.2f\n", p.x(), p.y(), p.z(), radius); - fprintf(out, "t %d %d %d\n", list[i], list[i+1], list[i+2]); - // printf("t %d %d %d\n", list[i], list[i+1], list[i+2]); - i += 3; - - // dump rest of strip (until -1) - while ( (i < list_ptr) && (list[i] != -1) ) { - fprintf(out, "q %d", list[i]); - i++; - if ( (i < list_ptr) && (list[i] != -1) ) { - fprintf(out, " %d", list[i]); - i++; - } - fprintf(out, "\n"); - } - - i++; - } -} - - -// Check the direction the current triangle faces, compared to it's -// pregenerated normal. Returns the dot product between the target -// normal and actual normal. If the dot product is close to 1.0, they -// nearly match. If the are close to -1.0, the are nearly opposite. -double check_cur_face(int n1, int n2, int n3) { - double v1[3], v2[3], approx_normal[3], dot_prod, temp; - - // check for the proper rotation by calculating an approximate - // normal and seeing if it is close to the precalculated normal - v1[0] = nodes[n2].x() - nodes[n1].x(); - v1[1] = nodes[n2].y() - nodes[n1].y(); - v1[2] = nodes[n2].z() - nodes[n1].z(); - v2[0] = nodes[n3].x() - nodes[n1].x(); - v2[1] = nodes[n3].y() - nodes[n1].y(); - v2[2] = nodes[n3].z() - nodes[n1].z(); - - MAT3cross_product(approx_normal, v1, v2); - MAT3_NORMALIZE_VEC(approx_normal,temp); - dot_prod = MAT3_DOT_PRODUCT(normals[n1], approx_normal); - - // not first triangle - // if ( ((dot_prod < -0.5) && !is_backwards) || - // ((dot_prod > 0.5) && is_backwards) ) { - // printf(" Approx normal = %.2f %.2f %.2f\n", approx_normal[0], - // approx_normal[1], approx_normal[2]); - // printf(" Dot product = %.4f\n", dot_prod); - // } - // angle = acos(dot_prod); - // printf("Normal ANGLE = %.3f rads.\n", angle); - - return(dot_prod); -} - - -// Load a .obj file -void obj_fix(char *infile, char *outfile) { - Point3D node, normal; - char line[256]; - double dot_prod; - int first, n1, n2, n3, n4; - double x, y, z, xmax, xmin, ymax, ymin, zmax, zmin; - int is_ccw; - - if ( (in = fopen(infile, "r")) == NULL ) { - printf("Cannot open file: %s\n", infile); - exit(-1); - } - - if ( (out = fopen(outfile, "w")) == NULL ) { - printf("Cannot open file: %s\n", outfile); - exit(-1); - } - - // push dummy records onto the lists since we start counting with "1" - node = Point3D(0.0, 0.0, 0.0); - nodes.push_back(node); - - normal = Point3D(0.0, 0.0, 0.0); - normals.push_back(normal); - - // initialize other lists - list_init(&ccw_list_ptr); - list_init(&cw_list_ptr); - - // I start counting at one because that is how the triangle - // program refers to nodes and normals - first = 1; - vncount = 1; - fcount = 1; - - printf("Reading file: %s\n", infile); - - while ( fgets(line, 250, in) != NULL ) { - if ( line[0] == '#' ) { - // pass along the comments verbatim - fprintf(out, "%s", line); - } else if ( strlen(line) <= 1 ) { - // don't pass along empty lines - // fprintf(out, "%s", line); - } else if ( strncmp(line, "v ", 2) == 0 ) { - // save vertex to memory and output to file - // printf("vertex = %s", line); - sscanf(line, "v %lf %lf %lf\n", &x, &y, &z); - - if ( nodes.size() == 1 ) { - // first time through set min's and max'es - xmin = x; - xmax = x; - ymin = y; - ymax = y; - zmin = z; - zmax = z; - } else { - // update min/max vertex values - if ( x < xmin ) xmin = x; - if ( x > xmax ) xmax = x; - if ( y < ymin ) ymin = y; - if ( y > ymax ) ymax = y; - if ( z < zmin ) zmin = z; - if ( z > zmax ) zmax = z; - } - - node = Point3D(x, y, z); - nodes.push_back(node); - // fprintf(out, "v %.2f %.2f %.2f\n", - // node.x(), node.y(), node.z()); - } else if ( strncmp(line, "vn ", 3) == 0 ) { - // save vertex normals to memory and output to file - // printf("vertex normal = %s", line); - sscanf(line, "vn %lf %lf %lf\n", &x, &y, &z); - normal = Point3D(x, y, z); - normals.push_back(normal); - } else if ( line[0] == 't' ) { - // starting a new triangle strip - - printf("Starting a new triangle strip\n"); - - n1 = n2 = n3 = n4 = 0; - - printf("new tri strip = %s", line); - sscanf(line, "t %d %d %d %d\n", &n1, &n2, &n3, &n4); - - // special cases to handle bugs in our beloved tri striper - if ( (n1 == 4) && (n2 == 2) && (n3 == 2) && (n4 == 1) ) { - n2 = 3; - } - if ( (n1 == 3) && (n2 == 1) && (n3 == 1) && (n4 == 0) ) { - n3 = 4; - } - - dot_prod = check_cur_face(n1, n2, n3); - if ( dot_prod < 0.0 ) { - // this stripe is backwards (CW) - is_ccw = 0; - printf(" -> Starting a backwards stripe\n"); - } else { - // this stripe is normal (CCW) - is_ccw = 1; - } - - if ( is_ccw ) { - if ( ccw_list_ptr ) { - list_add(ccw_list, &ccw_list_ptr, -1); - } - - list_add(ccw_list, &ccw_list_ptr, n1); - list_add(ccw_list, &ccw_list_ptr, n2); - list_add(ccw_list, &ccw_list_ptr, n3); - } else { - if ( cw_list_ptr ) { - list_add(cw_list, &cw_list_ptr, -1); - } - - list_add(cw_list, &cw_list_ptr, n1); - list_add(cw_list, &cw_list_ptr, n2); - list_add(cw_list, &cw_list_ptr, n3); - } - - if ( n4 > 0 ) { - if ( is_ccw ) { - list_add(ccw_list, &ccw_list_ptr, n4); - } else { - list_add(cw_list, &cw_list_ptr, n4); - } - } - } else if ( line[0] == 'f' ) { - if ( fcount < MAXNODES ) { - // pass along the unoptimized faces verbatim - sscanf(line, "f %d %d %d\n", &n1, &n2, &n3); - faces[fcount][0] = n1; - faces[fcount][1] = n2; - faces[fcount][2] = n3; - - fcount++; - } else { - printf("Read too many unoptimized faces ... dying :-(\n"); - exit(-1); - } - - // fprintf(out, "%s", line); - } else if ( line[0] == 'q' ) { - // continue a triangle strip - n1 = n2 = 0; - - // printf("continued tri strip = %s ", line); - sscanf(line, "q %d %d\n", &n1, &n2); - - if ( is_ccw ) { - list_add(ccw_list, &ccw_list_ptr, n1); - } else { - list_add(cw_list, &cw_list_ptr, n1); - } - - if ( n2 > 0 ) { - if ( is_ccw ) { - list_add(ccw_list, &ccw_list_ptr, n2); - } else { - list_add(cw_list, &cw_list_ptr, n2); - } - } - } else { - printf("Unknown line in %s = %s\n", infile, line); - } - } - - // reference point is the "center" - ref = Point3D( (xmin + xmax) / 2.0, - (ymin + ymax) / 2.0, - (zmin + zmax) / 2.0 ); - - // convert the cw_list to ccw add append to ccw_list - fix_cw_list(cw_list, cw_list_ptr); - - dump_global_bounds(); - dump_nodes(); - dump_normals(); - if ( fcount > 1 ) { - dump_faces(); - } - - dump_list(ccw_list, ccw_list_ptr); - - fclose(in); - fclose(out); -} - - -// $Log$ -// Revision 1.3 1999/02/01 21:09:40 curt -// Optimizations from Norman Vine. -// -// Revision 1.2 1998/10/21 14:55:55 curt -// Converted to Point3D class. -// -// Revision 1.1 1998/06/08 17:11:46 curt -// Renamed *.[ch] to *.[ch]xx -// -// Revision 1.16 1998/05/27 02:27:22 curt -// Commented out a couple of debugging messages. -// -// Revision 1.15 1998/05/24 02:47:47 curt -// For each strip, specify a default material property and calculate a center -// and bounding sphere. -// -// Revision 1.14 1998/05/23 15:19:49 curt -// Output more digits after the decimal place. -// -// Revision 1.13 1998/05/20 20:55:19 curt -// Fixed arbitrary polygon winding problem here so all tristrips are passed -// to runtime simulator with a consistant counter clockwise winding. -// -// Revision 1.12 1998/05/16 13:11:26 curt -// Fixed an off by one error in node, normal, and face counters. -// -// Revision 1.11 1998/04/27 15:59:24 curt -// Fixed an off by one error. -// -// Revision 1.10 1998/04/27 03:33:11 curt -// Code now calculates a center reference points and outputs everything -// relative to that. This is useful in the rendering engine to keep everything -// close to (0, 0, 0) where we can avoid many GLfloat precision problems. -// -// Revision 1.9 1998/04/18 04:01:03 curt -// Now use libMath rather than having local copies of math routines. -// -// Revision 1.8 1998/04/08 23:19:37 curt -// Adopted Gnu automake/autoconf system. -// -// Revision 1.7 1998/03/19 02:51:41 curt -// Added special case handling to compensate for bugs in our beloved tri striper -// -// Revision 1.6 1998/03/03 15:36:12 curt -// Tweaks for compiling with g++ -// -// Revision 1.5 1998/03/03 03:37:03 curt -// Cumulative tweaks. -// -// Revision 1.4 1998/01/31 00:41:25 curt -// Made a few changes converting floats to doubles. -// -// Revision 1.3 1998/01/19 19:51:07 curt -// A couple final pre-release tweaks. -// -// Revision 1.2 1998/01/09 23:03:12 curt -// Restructured to split 1deg x 1deg dem's into 64 subsections. -// -// Revision 1.1 1997/12/08 19:28:54 curt -// Initial revision. -// diff --git a/Tools/FixObj/obj.hxx b/Tools/FixObj/obj.hxx deleted file mode 100644 index 59a362c8d..000000000 --- a/Tools/FixObj/obj.hxx +++ /dev/null @@ -1,60 +0,0 @@ -// obj.hxx -- routines to handle WaveFront .obj format files. -// -// Written by Curtis Olson, started October 1997. -// -// Copyright (C) 1997 - 1998 Curtis L. Olson - curt@me.umn.edu -// -// 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. -// -// $Id$ -// (Log is kept at end of this file) - - -#ifndef OBJ_HXX -#define OBJ_HXX - - -#ifndef __cplusplus -# error This library requires C++ -#endif - - -#define MAXNODES 100000 - - -// Load a .obj file -void obj_fix(char *infile, char *outfile); - - -#endif // OBJ_HXX - - -// $Log$ -// Revision 1.1 1998/06/08 17:11:46 curt -// Renamed *.[ch] to *.[ch]xx -// -// Revision 1.4 1998/03/03 15:36:13 curt -// Tweaks for compiling with g++ -// -// Revision 1.3 1998/01/31 00:41:25 curt -// Made a few changes converting floats to doubles. -// -// Revision 1.2 1998/01/09 23:03:13 curt -// Restructured to split 1deg x 1deg dem's into 64 subsections. -// -// Revision 1.1 1997/12/08 19:28:55 curt -// Initial revision. -// - diff --git a/Tools/DEM/Makefile.am b/Tools/Lib/DEM/Makefile.am similarity index 100% rename from Tools/DEM/Makefile.am rename to Tools/Lib/DEM/Makefile.am diff --git a/Tools/DEM/dem.cxx b/Tools/Lib/DEM/dem.cxx similarity index 99% rename from Tools/DEM/dem.cxx rename to Tools/Lib/DEM/dem.cxx index e4661a3c7..8b4265d83 100644 --- a/Tools/DEM/dem.cxx +++ b/Tools/Lib/DEM/dem.cxx @@ -865,6 +865,9 @@ FGDem::~FGDem( void ) { // $Log$ +// Revision 1.1 1999/04/05 21:32:41 curt +// Initial revision +// // Revision 1.27 1999/03/25 19:04:36 curt // Minor tweaks related to FGBucket usage. // diff --git a/Tools/DEM/dem.hxx b/Tools/Lib/DEM/dem.hxx similarity index 98% rename from Tools/DEM/dem.hxx rename to Tools/Lib/DEM/dem.hxx index 46849e3a4..20427d03e 100644 --- a/Tools/DEM/dem.hxx +++ b/Tools/Lib/DEM/dem.hxx @@ -154,6 +154,9 @@ public: // $Log$ +// Revision 1.1 1999/04/05 21:32:41 curt +// Initial revision +// // Revision 1.13 1999/03/13 17:40:39 curt // Moved point interpolation and least squares fitting to contruction program // area. diff --git a/Tools/Polygon/Makefile.am b/Tools/Lib/Polygon/Makefile.am similarity index 100% rename from Tools/Polygon/Makefile.am rename to Tools/Lib/Polygon/Makefile.am diff --git a/Tools/Polygon/index.cxx b/Tools/Lib/Polygon/index.cxx similarity index 96% rename from Tools/Polygon/index.cxx rename to Tools/Lib/Polygon/index.cxx index 34352aacd..70bc4edaa 100644 --- a/Tools/Polygon/index.cxx +++ b/Tools/Lib/Polygon/index.cxx @@ -71,6 +71,9 @@ long int poly_index_next() { // $Log$ +// Revision 1.1 1999/04/05 21:32:42 curt +// Initial revision +// // Revision 1.2 1999/03/19 00:27:30 curt // Use long int for index instead of just int. // diff --git a/Tools/Polygon/index.hxx b/Tools/Lib/Polygon/index.hxx similarity index 95% rename from Tools/Polygon/index.hxx rename to Tools/Lib/Polygon/index.hxx index 0ea6b5c06..8bfe05f27 100644 --- a/Tools/Polygon/index.hxx +++ b/Tools/Lib/Polygon/index.hxx @@ -43,6 +43,9 @@ long int poly_index_next(); // $Log$ +// Revision 1.1 1999/04/05 21:32:42 curt +// Initial revision +// // Revision 1.2 1999/03/19 00:27:31 curt // Use long int for index instead of just int. // diff --git a/Tools/Polygon/names.cxx b/Tools/Lib/Polygon/names.cxx similarity index 98% rename from Tools/Polygon/names.cxx rename to Tools/Lib/Polygon/names.cxx index 2633d19a6..d3ce4a6d8 100644 --- a/Tools/Polygon/names.cxx +++ b/Tools/Lib/Polygon/names.cxx @@ -116,6 +116,9 @@ string get_area_name( AreaType area ) { // $Log$ +// Revision 1.1 1999/04/05 21:32:42 curt +// Initial revision +// // Revision 1.7 1999/04/01 13:52:13 curt // Version 0.6.0 // Shape name tweak. diff --git a/Tools/Polygon/names.hxx b/Tools/Lib/Polygon/names.hxx similarity index 97% rename from Tools/Polygon/names.hxx rename to Tools/Lib/Polygon/names.hxx index 0a919a5ed..658fa6db0 100644 --- a/Tools/Polygon/names.hxx +++ b/Tools/Lib/Polygon/names.hxx @@ -67,6 +67,9 @@ string get_area_name( AreaType area ); // $Log$ +// Revision 1.1 1999/04/05 21:32:42 curt +// Initial revision +// // Revision 1.5 1999/03/27 05:31:25 curt // Make 0 the default area type since this corresponds well with the conventions // used by the triangulator. diff --git a/Tools/Triangle/A.poly b/Tools/Lib/Triangle/A.poly similarity index 100% rename from Tools/Triangle/A.poly rename to Tools/Lib/Triangle/A.poly diff --git a/Tools/Triangle/Makefile.am b/Tools/Lib/Triangle/Makefile.am similarity index 100% rename from Tools/Triangle/Makefile.am rename to Tools/Lib/Triangle/Makefile.am diff --git a/Tools/Triangle/README b/Tools/Lib/Triangle/README similarity index 100% rename from Tools/Triangle/README rename to Tools/Lib/Triangle/README diff --git a/Tools/Triangle/showme.c b/Tools/Lib/Triangle/showme.c similarity index 100% rename from Tools/Triangle/showme.c rename to Tools/Lib/Triangle/showme.c diff --git a/Tools/Triangle/triangle.c b/Tools/Lib/Triangle/triangle.c similarity index 100% rename from Tools/Triangle/triangle.c rename to Tools/Lib/Triangle/triangle.c diff --git a/Tools/Triangle/triangle.doc b/Tools/Lib/Triangle/triangle.doc similarity index 100% rename from Tools/Triangle/triangle.doc rename to Tools/Lib/Triangle/triangle.doc diff --git a/Tools/Triangle/triangle.h b/Tools/Lib/Triangle/triangle.h similarity index 100% rename from Tools/Triangle/triangle.h rename to Tools/Lib/Triangle/triangle.h diff --git a/Tools/Triangle/tricall.c b/Tools/Lib/Triangle/tricall.c similarity index 100% rename from Tools/Triangle/tricall.c rename to Tools/Lib/Triangle/tricall.c diff --git a/Tools/Main/construct.cxx b/Tools/Main/construct.cxx deleted file mode 100644 index 1c5c117a9..000000000 --- a/Tools/Main/construct.cxx +++ /dev/null @@ -1,373 +0,0 @@ -// main.cxx -- top level construction routines -// -// Written by Curtis Olson, started March 1999. -// -// Copyright (C) 1999 Curtis L. Olson - curt@flightgear.org -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 2 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -// -// $Id$ -// (Log is kept at end of this file) - - -#include // for directory reading -#include // for directory reading - -#include -#include - -#include -#include -#include -#include -#include - - -// load regular grid of elevation data (dem based), return list of -// fitted nodes -int load_dem(const string& work_base, FGBucket& b, FGArray& array) { - point_list result; - string base = b.gen_base_path(); - - string dem_path = work_base + ".dem" + "/Scenery/" + base - + "/" + b.gen_index_str() + ".dem"; - cout << "dem_path = " << dem_path << endl; - - if ( ! array.open(dem_path) ) { - cout << "ERROR: cannot open " << dem_path << endl; - } - - array.parse( b ); - - return 1; -} - -// fit dem nodes, return number of fitted nodes -int fit_dem(FGArray& array, int error) { - return array.fit( error ); -} - - -// do actual scan of directory and loading of files -int actual_load_polys( const string& dir, FGBucket& b, FGClipper& clipper ) { - int counter = 0; - string base = b.gen_base_path(); - string tile_str = b.gen_index_str(); - string ext; - - DIR *d; - struct dirent *de; - - if ( (d = opendir( dir.c_str() )) == NULL ) { - cout << "cannot open directory " << dir << "\n"; - return 0; - } - - // load all matching polygon files - string file, f_index, full_path; - int pos; - while ( (de = readdir(d)) != NULL ) { - file = de->d_name; - pos = file.find("."); - f_index = file.substr(0, pos); - - if ( tile_str == f_index ) { - ext = file.substr(pos + 1); - cout << file << " " << f_index << " '" << ext << "'" << endl; - full_path = dir + "/" + file; - if ( (ext == "dem") || (ext == "dem.gz") ) { - // skip - } else { - cout << "ext = '" << ext << "'" << endl; - clipper.load_polys( full_path ); - ++counter; - } - } - } - - return counter; -} - - -// load all 2d polygons matching the specified base path and clip -// against each other to resolve any overlaps -int load_polys( const string& work_base, FGBucket& b, FGClipper& clipper) { - string base = b.gen_base_path(); - int result; - - // initialize clipper - clipper.init(); - - // load airports - string poly_path = work_base + ".apt" + "/Scenery/" + base; - cout << "poly_path = " << poly_path << endl; - result = actual_load_polys( poly_path, b, clipper ); - cout << " loaded " << result << " polys" << endl; - - // load hydro - poly_path = work_base + ".hydro" + "/Scenery/" + base; - cout << "poly_path = " << poly_path << endl; - result = actual_load_polys( poly_path, b, clipper ); - cout << " loaded " << result << " polys" << endl; - - point2d min, max; - min.x = b.get_center_lon() - 0.5 * b.get_width(); - min.y = b.get_center_lat() - 0.5 * b.get_height(); - max.x = b.get_center_lon() + 0.5 * b.get_width(); - max.y = b.get_center_lat() + 0.5 * b.get_height(); - - // do clipping - cout << "clipping polygons" << endl; - clipper.clip_all(min, max); - - return 1; -} - - -// triangulate the data for each polygon -void do_triangulate( const FGArray& array, const FGClipper& clipper, - FGTriangle& t ) { - // first we need to consolidate the points of the DEM fit list and - // all the polygons into a more "Triangle" friendly format - - point_list corner_list = array.get_corner_node_list(); - point_list fit_list = array.get_fit_node_list(); - FGgpcPolyList gpc_polys = clipper.get_polys_clipped(); - - cout << "ready to build node list and polygons" << endl; - t.build( corner_list, fit_list, gpc_polys ); - cout << "done building node list and polygons" << endl; - - cout << "ready to do triangulation" << endl; - t.run_triangulate(); - cout << "finished triangulation" << endl; -} - - -// generate the flight gear scenery file -void do_output( const string& base, const FGBucket &b, const FGTriangle& t, - const FGArray& array, FGGenOutput& output ) { - output.build( array, t ); - output.write( base, b ); -} - - -void construct_tile( const string& work_base, const string& output_base, - FGBucket& b ) -{ - cout << "Construct tile, bucket = " << b << endl; - - // fit with ever increasing error tolerance until we produce <= - // 80% of max nodes. We should really have the sim end handle - // arbitrarily complex tiles. - - const int min_nodes = 50; - const int max_nodes = (int)(MAX_NODES * 0.8); - - bool acceptable = false; - double error = 200.0; - int count = 0; - - // load and fit grid of elevation data - FGArray array; - load_dem( work_base, b, array ); - - FGTriangle t; - - while ( ! acceptable ) { - // fit the data - array.fit( error ); - - // load and clip 2d polygon data - FGClipper clipper; - load_polys( work_base, b, clipper ); - - // triangulate the data for each polygon - do_triangulate( array, clipper, t ); - - acceptable = true; - - count = t.get_out_nodes_size(); - - if ( (count < min_nodes) && (error >= 25.0) ) { - // reduce error tolerance until number of points exceeds the - // minimum threshold - cout << "produced too few nodes ..." << endl; - - acceptable = false; - - error /= 1.5; - cout << "Setting error to " << error << " and retrying fit." - << endl; - } - - if ( (count > max_nodes) && (error <= 1000.0) ) { - // increase error tolerance until number of points drops below - // the maximum threshold - cout << "produced too many nodes ..." << endl; - - acceptable = false; - - error *= 1.5; - cout << "Setting error to " << error << " and retrying fit." - << endl; - } - } - - cout << "finished fit with error = " << error << " node count = " - << count << endl; - - // generate the output - FGGenOutput output; - do_output( output_base, b, t, array, output ); -} - - -main(int argc, char **argv) { - double lon, lat; - - fglog().setLogLevels( FG_ALL, FG_DEBUG ); - - if ( argc != 3 ) { - cout << "Usage: " << argv[0] << " " << endl; - exit(-1); - } - - string work_base = argv[1]; - string output_base = argv[2]; - - // lon = -146.248360; lat = 61.133950; // PAVD (Valdez, AK) - // lon = -110.664244; lat = 33.352890; // P13 - // lon = -93.211389; lat = 45.145000; // KANE - // lon = -92.486188; lat = 44.590190; // KRGK - // lon = -89.744682312011719; lat= 29.314495086669922; - // lon = -122.488090; lat = 42.743183; // 64S - // lon = -114.861097; lat = 35.947480; // 61B - // lon = -112.012175; lat = 41.195944; // KOGD - // lon = -90.757128; lat = 46.790212; // WI32 - // lon = -122.220717; lat = 37.721291; // KOAK - // lon = -111.721477; lat = 40.215641; // KPVU - // lon = -122.309313; lat = 47.448982; // KSEA - lon = -148.798131; lat = 63.645099; // AK06 (Danali, AK) - - double min_x = lon - 3; - double min_y = lat - 1; - FGBucket b_min( min_x, min_y ); - FGBucket b_max( lon + 3, lat + 1 ); - - FGBucket b_omit(550314L); - // FGBucket b(517745L); - // FGBucket b(-146.248360, 61.133950); - // construct_tile( work_base, output_base, b ); - // exit(0); - - if ( b_min == b_max ) { - construct_tile( work_base, output_base, b_min ); - } else { - FGBucket b_cur; - int dx, dy, i, j; - - fgBucketDiff(b_min, b_max, &dx, &dy); - cout << " construction area spans tile boundaries" << endl; - cout << " dx = " << dx << " dy = " << dy << endl; - - for ( j = 0; j <= dy; j++ ) { - for ( i = 0; i <= dx; i++ ) { - b_cur = fgBucketOffset(min_x, min_y, i, j); - - if ( b_cur != b_omit ) { - construct_tile( work_base, output_base, b_cur ); - } - } - } - // string answer; cin >> answer; - } -} - - -// $Log$ -// Revision 1.18 1999/04/05 02:16:51 curt -// Dynamically update "error" until the resulting tile data scales within -// a lower and upper bounds. -// -// Revision 1.17 1999/04/03 05:22:57 curt -// Found a bug in dividing and adding unique verticle segments which could -// cause the triangulator to end up in an infinite loop. Basically the code -// was correct, but the verticle line test was a bit to selective. -// -// Revision 1.16 1999/04/01 13:52:12 curt -// Version 0.6.0 -// Shape name tweak. -// Removing tool: FixNode -// -// Revision 1.15 1999/03/31 23:47:02 curt -// Debugging output tweaks. -// -// Revision 1.14 1999/03/31 13:26:41 curt -// Debugging output tweeaks. -// -// Revision 1.13 1999/03/31 05:35:06 curt -// Fixed bug in genfans (deleting the wrong triangles from the available pool.) -// -// Revision 1.12 1999/03/30 23:51:14 curt -// fiddling ... -// -// Revision 1.11 1999/03/29 13:11:06 curt -// Shuffled stl type names a bit. -// Began adding support for tri-fanning (or maybe other arrangments too.) -// -// Revision 1.10 1999/03/27 05:25:02 curt -// Fit with a value of 200 rather than 100. -// Handle corner nodes separately from the rest of the fitted nodes. -// Write scenery file to correct location. -// First hack at generating scenery for multiple tiles in one invocation. -// -// Revision 1.9 1999/03/25 19:04:31 curt -// Preparations for outputing scenery file to correct location. -// Minor tweaks related to FGBucket usage. -// -// Revision 1.8 1999/03/23 22:02:17 curt -// Worked on creating data to output ... normals, bounding spheres, etc. -// -// Revision 1.7 1999/03/22 23:48:29 curt -// Added GenOutput/ -// -// Revision 1.6 1999/03/21 15:48:01 curt -// Removed Dem2node from the Tools fold. -// Tweaked the triangulator options to add quality mesh refinement. -// -// Revision 1.5 1999/03/21 14:02:05 curt -// Added a mechanism to dump out the triangle structures for viewing. -// Fixed a couple bugs in first pass at triangulation. -// - needed to explicitely initialize the polygon accumulator in triangle.cxx -// before each polygon rather than depending on the default behavior. -// - Fixed a problem with region attribute propagation where I wasn't generating -// the hole points correctly. -// -// Revision 1.4 1999/03/20 20:32:54 curt -// First mostly successful tile triangulation works. There's plenty of tweaking -// to do, but we are marching in the right direction. -// -// Revision 1.3 1999/03/19 00:26:52 curt -// Minor tweaks ... -// -// Revision 1.2 1999/03/17 23:49:52 curt -// Started work on Triangulate/ section. -// -// Revision 1.1 1999/03/14 00:03:24 curt -// Initial revision. -// - - diff --git a/Tools/Tools/Makefile.am b/Tools/Makefile.am similarity index 100% rename from Tools/Tools/Makefile.am rename to Tools/Makefile.am diff --git a/Tools/DemChop/Makefile.am b/Tools/Prep/DemChop/Makefile.am similarity index 96% rename from Tools/DemChop/Makefile.am rename to Tools/Prep/DemChop/Makefile.am index 9103e673b..89b5472e9 100644 --- a/Tools/DemChop/Makefile.am +++ b/Tools/Prep/DemChop/Makefile.am @@ -47,6 +47,9 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib -I$(top_builddir)/Tools/Lib #--------------------------------------------------------------------------- # $Log$ +# Revision 1.1 1999/04/05 21:32:42 curt +# Initial revision +# # Revision 1.3 1999/03/17 23:51:07 curt # Removed forced -g compiler flag. # diff --git a/Tools/DemChop/demchop.cxx b/Tools/Prep/DemChop/demchop.cxx similarity index 97% rename from Tools/DemChop/demchop.cxx rename to Tools/Prep/DemChop/demchop.cxx index 8182c8d8e..9f8439d6e 100644 --- a/Tools/DemChop/demchop.cxx +++ b/Tools/Prep/DemChop/demchop.cxx @@ -102,6 +102,9 @@ int main(int argc, char **argv) { // $Log$ +// Revision 1.1 1999/04/05 21:32:42 curt +// Initial revision +// // Revision 1.3 1999/03/12 22:53:46 curt // First working version! // diff --git a/Tools/DemChop/point2d.cxx b/Tools/Prep/DemChop/point2d.cxx similarity index 95% rename from Tools/DemChop/point2d.cxx rename to Tools/Prep/DemChop/point2d.cxx index 817015f8a..f3d13ed7f 100644 --- a/Tools/DemChop/point2d.cxx +++ b/Tools/Prep/DemChop/point2d.cxx @@ -39,6 +39,9 @@ point2d cart_to_polar_2d(point2d in) { // $Log$ +// Revision 1.1 1999/04/05 21:32:42 curt +// Initial revision +// // Revision 1.1 1999/03/10 01:02:54 curt // Initial revision. // diff --git a/Tools/DemChop/point2d.hxx b/Tools/Prep/DemChop/point2d.hxx similarity index 95% rename from Tools/DemChop/point2d.hxx rename to Tools/Prep/DemChop/point2d.hxx index e4df44488..e9d9db33c 100644 --- a/Tools/DemChop/point2d.hxx +++ b/Tools/Prep/DemChop/point2d.hxx @@ -53,6 +53,9 @@ point2d cart_to_polar_2d(point2d in); // $Log$ +// Revision 1.1 1999/04/05 21:32:42 curt +// Initial revision +// // Revision 1.1 1999/03/10 16:09:45 curt // Hacking towards the first working version. // diff --git a/Tools/DemInfo/Makefile.am b/Tools/Prep/DemInfo/Makefile.am similarity index 97% rename from Tools/DemInfo/Makefile.am rename to Tools/Prep/DemInfo/Makefile.am index b3d8d3aa7..c3fcdd02d 100644 --- a/Tools/DemInfo/Makefile.am +++ b/Tools/Prep/DemInfo/Makefile.am @@ -46,6 +46,9 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib -I$(top_builddir)/Tools/Lib #--------------------------------------------------------------------------- # $Log$ +# Revision 1.1 1999/04/05 21:32:43 curt +# Initial revision +# # Revision 1.7 1999/03/17 23:51:14 curt # Removed forced -g compiler flag. # diff --git a/Tools/DemInfo/deminfo.cxx b/Tools/Prep/DemInfo/deminfo.cxx similarity index 96% rename from Tools/DemInfo/deminfo.cxx rename to Tools/Prep/DemInfo/deminfo.cxx index 75f9c2f55..6b7716717 100644 --- a/Tools/DemInfo/deminfo.cxx +++ b/Tools/Prep/DemInfo/deminfo.cxx @@ -67,6 +67,9 @@ int main(int argc, char **argv) { // $Log$ +// Revision 1.1 1999/04/05 21:32:42 curt +// Initial revision +// // Revision 1.3 1999/03/12 22:54:04 curt // Convert fgDEM to FGDem ... // diff --git a/Tools/DemInfo/gather-dem-info.pl b/Tools/Prep/DemInfo/gather-dem-info.pl similarity index 96% rename from Tools/DemInfo/gather-dem-info.pl rename to Tools/Prep/DemInfo/gather-dem-info.pl index 746d7120e..8618af508 100755 --- a/Tools/DemInfo/gather-dem-info.pl +++ b/Tools/Prep/DemInfo/gather-dem-info.pl @@ -56,6 +56,9 @@ while ( $dir = shift(@ARGV) ) { #--------------------------------------------------------------------------- # $Log$ +# Revision 1.1 1999/04/05 21:32:43 curt +# Initial revision +# # Revision 1.1 1998/06/04 19:18:06 curt # Initial revision. # diff --git a/Tools/DemRaw2ascii/Makefile.am b/Tools/Prep/DemRaw2ascii/Makefile.am similarity index 96% rename from Tools/DemRaw2ascii/Makefile.am rename to Tools/Prep/DemRaw2ascii/Makefile.am index b638e2e96..da71e803b 100644 --- a/Tools/DemRaw2ascii/Makefile.am +++ b/Tools/Prep/DemRaw2ascii/Makefile.am @@ -35,6 +35,9 @@ INCLUDES += #--------------------------------------------------------------------------- # $Log$ +# Revision 1.1 1999/04/05 21:32:42 curt +# Initial revision +# # Revision 1.3 1998/11/04 23:01:50 curt # Changes to the automake/autoconf system to reduce the number of libraries # that are unnecessarily linked into the various executables. diff --git a/Tools/DemRaw2ascii/main.c b/Tools/Prep/DemRaw2ascii/main.c similarity index 97% rename from Tools/DemRaw2ascii/main.c rename to Tools/Prep/DemRaw2ascii/main.c index 8cc0f2ffa..0fb032a4f 100644 --- a/Tools/DemRaw2ascii/main.c +++ b/Tools/Prep/DemRaw2ascii/main.c @@ -78,6 +78,9 @@ int main(int argc, char **argv) { /* $Log$ +/* Revision 1.1 1999/04/05 21:32:42 curt +/* Initial revision +/* /* Revision 1.3 1998/03/03 21:54:50 curt /* Changes to process 30 arcsec binary DEM files. /* diff --git a/Tools/DemRaw2ascii/rawdem.c b/Tools/Prep/DemRaw2ascii/rawdem.c similarity index 99% rename from Tools/DemRaw2ascii/rawdem.c rename to Tools/Prep/DemRaw2ascii/rawdem.c index 8411035bd..697393638 100644 --- a/Tools/DemRaw2ascii/rawdem.c +++ b/Tools/Prep/DemRaw2ascii/rawdem.c @@ -462,6 +462,9 @@ void rawProcessStrip( fgRAWDEM *raw, int lat_degrees, char *path ) { /* $Log$ +/* Revision 1.1 1999/04/05 21:32:42 curt +/* Initial revision +/* /* Revision 1.6 1998/04/27 03:32:03 curt /* Wrapped rint()'s in #ifdef HAVE_RINT /* diff --git a/Tools/DemRaw2ascii/rawdem.h b/Tools/Prep/DemRaw2ascii/rawdem.h similarity index 97% rename from Tools/DemRaw2ascii/rawdem.h rename to Tools/Prep/DemRaw2ascii/rawdem.h index 8877b2eaa..a0be7c23d 100644 --- a/Tools/DemRaw2ascii/rawdem.h +++ b/Tools/Prep/DemRaw2ascii/rawdem.h @@ -76,6 +76,9 @@ void rawProcessStrip( fgRAWDEM *raw, int lat_degrees, char *path ); /* $Log$ +/* Revision 1.1 1999/04/05 21:32:42 curt +/* Initial revision +/* /* Revision 1.2 1998/03/03 13:10:30 curt /* Close to a working version. /* diff --git a/Tools/GenAirports/Makefile.am b/Tools/Prep/GenAirports/Makefile.am similarity index 97% rename from Tools/GenAirports/Makefile.am rename to Tools/Prep/GenAirports/Makefile.am index 86c8ecb16..b6a1e2a21 100644 --- a/Tools/GenAirports/Makefile.am +++ b/Tools/Prep/GenAirports/Makefile.am @@ -45,6 +45,9 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib -I$(top_builddir)/Tools/Lib #--------------------------------------------------------------------------- # $Log$ +# Revision 1.1 1999/04/05 21:32:43 curt +# Initial revision +# # Revision 1.6 1999/03/08 22:00:47 curt # Lots of directory layout reorganization. # diff --git a/Tools/GenAirports/area.cxx b/Tools/Prep/GenAirports/area.cxx similarity index 99% rename from Tools/GenAirports/area.cxx rename to Tools/Prep/GenAirports/area.cxx index 75d785377..fe73d4b8a 100644 --- a/Tools/GenAirports/area.cxx +++ b/Tools/Prep/GenAirports/area.cxx @@ -218,6 +218,9 @@ gen_runway_area( double lon, double lat, double heading, // $Log$ +// Revision 1.1 1999/04/05 21:32:43 curt +// Initial revision +// // Revision 1.5 1998/10/20 15:49:54 curt // tweak ... // diff --git a/Tools/GenAirports/area.hxx b/Tools/Prep/GenAirports/area.hxx similarity index 95% rename from Tools/GenAirports/area.hxx rename to Tools/Prep/GenAirports/area.hxx index a1bbd342e..b08d05651 100644 --- a/Tools/GenAirports/area.hxx +++ b/Tools/Prep/GenAirports/area.hxx @@ -42,6 +42,9 @@ gen_runway_area( double lon, double lat, double heading, // $Log$ +// Revision 1.1 1999/04/05 21:32:43 curt +// Initial revision +// // Revision 1.2 1998/09/04 23:04:49 curt // Beginning of convex hull genereration routine. // diff --git a/Tools/GenAirports/convex_hull.cxx b/Tools/Prep/GenAirports/convex_hull.cxx similarity index 99% rename from Tools/GenAirports/convex_hull.cxx rename to Tools/Prep/GenAirports/convex_hull.cxx index 0cdff1dcb..e87811b2f 100644 --- a/Tools/GenAirports/convex_hull.cxx +++ b/Tools/Prep/GenAirports/convex_hull.cxx @@ -256,6 +256,9 @@ list_container convex_hull( list_container input_list ) // $Log$ +// Revision 1.1 1999/04/05 21:32:43 curt +// Initial revision +// // Revision 1.5 1999/02/25 21:32:48 curt // Modified to adhere to new polygon naming convention, and also to read the // new Robin Peel aiport format. diff --git a/Tools/GenAirports/convex_hull.hxx b/Tools/Prep/GenAirports/convex_hull.hxx similarity index 96% rename from Tools/GenAirports/convex_hull.hxx rename to Tools/Prep/GenAirports/convex_hull.hxx index 42bf0db83..43ec49afd 100644 --- a/Tools/GenAirports/convex_hull.hxx +++ b/Tools/Prep/GenAirports/convex_hull.hxx @@ -51,6 +51,9 @@ list_container convex_hull( list_container input_list ); // $Log$ +// Revision 1.1 1999/04/05 21:32:43 curt +// Initial revision +// // Revision 1.2 1998/09/09 16:26:33 curt // Continued progress in implementing the convex hull algorithm. // diff --git a/Tools/GenAirports/main.cxx b/Tools/Prep/GenAirports/main.cxx similarity index 99% rename from Tools/GenAirports/main.cxx rename to Tools/Prep/GenAirports/main.cxx index 7ad07f6db..14e10ac9c 100644 --- a/Tools/GenAirports/main.cxx +++ b/Tools/Prep/GenAirports/main.cxx @@ -344,6 +344,9 @@ int main( int argc, char **argv ) { // $Log$ +// Revision 1.1 1999/04/05 21:32:43 curt +// Initial revision +// // Revision 1.11 1999/03/19 00:27:38 curt // Use long int for index instead of just int. // diff --git a/Tools/GenAirports/point2d.cxx b/Tools/Prep/GenAirports/point2d.cxx similarity index 95% rename from Tools/GenAirports/point2d.cxx rename to Tools/Prep/GenAirports/point2d.cxx index 755224477..2b26a46b5 100644 --- a/Tools/GenAirports/point2d.cxx +++ b/Tools/Prep/GenAirports/point2d.cxx @@ -39,6 +39,9 @@ point2d cart_to_polar_2d(point2d in) { // $Log$ +// Revision 1.1 1999/04/05 21:32:43 curt +// Initial revision +// // Revision 1.1 1998/09/04 23:04:53 curt // Beginning of convex hull genereration routine. // diff --git a/Tools/GenAirports/point2d.hxx b/Tools/Prep/GenAirports/point2d.hxx similarity index 95% rename from Tools/GenAirports/point2d.hxx rename to Tools/Prep/GenAirports/point2d.hxx index 199524047..72083178a 100644 --- a/Tools/GenAirports/point2d.hxx +++ b/Tools/Prep/GenAirports/point2d.hxx @@ -53,6 +53,9 @@ point2d cart_to_polar_2d(point2d in); // $Log$ +// Revision 1.1 1999/04/05 21:32:43 curt +// Initial revision +// // Revision 1.1 1998/09/04 23:04:53 curt // Beginning of convex hull genereration routine. // diff --git a/Tools/ShapeFile/Makefile.am b/Tools/Prep/ShapeFile/Makefile.am similarity index 100% rename from Tools/ShapeFile/Makefile.am rename to Tools/Prep/ShapeFile/Makefile.am diff --git a/Tools/ShapeFile/main.cxx b/Tools/Prep/ShapeFile/main.cxx similarity index 99% rename from Tools/ShapeFile/main.cxx rename to Tools/Prep/ShapeFile/main.cxx index b0e629575..9b1df9c74 100644 --- a/Tools/ShapeFile/main.cxx +++ b/Tools/Prep/ShapeFile/main.cxx @@ -306,6 +306,9 @@ int main( int argc, char **argv ) { // $Log$ +// Revision 1.1 1999/04/05 21:32:42 curt +// Initial revision +// // Revision 1.8 1999/03/22 23:49:36 curt // Moved AreaType get_shapefile_type(GDBFile *dbf, int rec) to where it // belongs in ShapeFile/ diff --git a/Tools/ShapeFile/shape.cxx b/Tools/Prep/ShapeFile/shape.cxx similarity index 98% rename from Tools/ShapeFile/shape.cxx rename to Tools/Prep/ShapeFile/shape.cxx index badef8823..f812e7d4f 100644 --- a/Tools/ShapeFile/shape.cxx +++ b/Tools/Prep/ShapeFile/shape.cxx @@ -244,6 +244,9 @@ void free_shape(gpc_polygon *shape) { // $Log$ +// Revision 1.1 1999/04/05 21:32:42 curt +// Initial revision +// // Revision 1.3 1999/03/19 00:27:41 curt // Use long int for index instead of just int. // diff --git a/Tools/ShapeFile/shape.hxx b/Tools/Prep/ShapeFile/shape.hxx similarity index 96% rename from Tools/ShapeFile/shape.hxx rename to Tools/Prep/ShapeFile/shape.hxx index 6a59b77e3..3f9786377 100644 --- a/Tools/ShapeFile/shape.hxx +++ b/Tools/Prep/ShapeFile/shape.hxx @@ -56,6 +56,9 @@ void free_shape(gpc_polygon *shape); // $Log$ +// Revision 1.1 1999/04/05 21:32:42 curt +// Initial revision +// // Revision 1.2 1999/02/25 21:31:09 curt // First working version??? // diff --git a/Tools/Tools/README b/Tools/README similarity index 100% rename from Tools/Tools/README rename to Tools/README diff --git a/Tools/SplitTris/Makefile.am b/Tools/SplitTris/Makefile.am deleted file mode 100644 index e8f64e5b9..000000000 --- a/Tools/SplitTris/Makefile.am +++ /dev/null @@ -1,77 +0,0 @@ -#--------------------------------------------------------------------------- -# Makefile -# -# Written by Curtis Olson, started January 1998. -# -# Copyright (C) 1998 Curtis L. Olson - curt@me.umn.edu -# -# 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. -# -# $Id$ -# (Log is kept at end of this file) -#--------------------------------------------------------------------------- - - -bin_PROGRAMS = splittris - -splittris_SOURCES = splittris.cxx splittris.hxx - -splittris_LDADD = \ - $(top_builddir)/Lib/Bucket/libBucket.a \ - $(top_builddir)/Lib/Math/libMath.a \ - $(top_builddir)/Lib/Debug/libDebug.a \ - $(top_builddir)/Lib/Misc/libMisc.a \ - $(top_builddir)/Lib/zlib/libz.a \ - $(base_LIBS) - -INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib - - -#--------------------------------------------------------------------------- -# $Log$ -# Revision 1.8 1998/11/04 23:01:57 curt -# Changes to the automake/autoconf system to reduce the number of libraries -# that are unnecessarily linked into the various executables. -# -# Revision 1.7 1998/10/18 01:17:25 curt -# Point3D tweaks. -# -# Revision 1.6 1998/07/30 23:49:26 curt -# Removed libtool support. -# -# Revision 1.5 1998/07/08 14:49:13 curt -# tweaks. -# -# Revision 1.4 1998/04/24 00:44:06 curt -# Added zlib support. -# -# Revision 1.3 1998/04/18 04:01:17 curt -# Now use libMath rather than having local copies of math routines. -# -# Revision 1.2 1998/04/14 02:26:06 curt -# Code reorganizations. Added a Lib/ directory for more general libraries. -# -# Revision 1.1 1998/04/08 23:21:10 curt -# Adopted Gnu automake/autoconf system. -# -# Revision 1.3 1998/01/21 02:55:55 curt -# Incorporated new make system from Bob Kuehne . -# -# Revision 1.2 1998/01/14 15:54:42 curt -# Initial revision completed. -# -# Revision 1.1 1998/01/14 02:11:30 curt -# Initial revision. -# diff --git a/Tools/SplitTris/splittris.cxx b/Tools/SplitTris/splittris.cxx deleted file mode 100644 index 20e26e7a9..000000000 --- a/Tools/SplitTris/splittris.cxx +++ /dev/null @@ -1,673 +0,0 @@ -// splittris.cxx -- read in a .ele/.node file pair generated by the -// triangle program and output a simple Wavefront .obj -// file for the north, south, east, and west edge -// verticies ... including the normals. -// -// Written by Curtis Olson, started January 1998. -// -// Copyright (C) 1997 Curtis L. Olson - curt@infoplane.com -// -// 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. -// -// $Id$ -// (Log is kept at end of this file) - - -#include -#include -#include // for atoi() -#include -#include // for stat() -#include // for stat() - -#include "splittris.hxx" - -#include -#include -#include -#include -#include -#include -#include - -// int nodecount, tricount; -double xmin, xmax, ymin, ymax; - -// static double nodes_orig[MAX_NODES][3]; -// static Point3D nodes_cart[MAX_NODES]; -// static int tris[MAX_TRIS][3]; - -container_3d nodes_orig; -container_3d nodes_cart; -container_tri tri_list; - -fgBUCKET ne_index, nw_index, sw_index, se_index; -fgBUCKET north_index, south_index, east_index, west_index; - - -// given three points defining a triangle, calculate the normal -void calc_normal(const Point3D& p1, const Point3D& p2, - const Point3D& p3, double normal[3]) -{ - double v1[3], v2[3]; - double temp; - - v1[0] = p2.x() - p1.x(); v1[1] = p2.y() - p1.y(); v1[2] = p2.z() - p1.z(); - v2[0] = p3.x() - p1.x(); v2[1] = p3.y() - p1.y(); v2[2] = p3.z() - p1.z(); - - MAT3cross_product(normal, v1, v2); - MAT3_NORMALIZE_VEC(normal,temp); - - // printf(" Normal = %.2f %.2f %.2f\n", normal[0], normal[1], normal[2]); -} - - -// return the file base name ( foo/bar/file.ext = file.ext ) -string extract_file(const string& input) { - int pos; - - pos = input.rfind("/"); - ++pos; - - return input.substr(pos); -} - - -// return the file path name ( foo/bar/file.ext = foo/bar ) -string extract_path(const string& input) { - int pos; - - pos = input.rfind("/"); - - return input.substr(0, pos); -} - - -// return the index of all triangles containing the specified node -void find_tris(int n, int *t1, int *t2, int *t3, int *t4, int *t5) { - int i; - - *t1 = *t2 = *t3 = *t4 = *t5 = 0; - - i = 1; - iterator_tri last = tri_list.end(); - iterator_tri current = tri_list.begin(); - - // skip first null record - ++current; - - for ( ; current != last; ++current ) - { - if ( (n == (*current).n1) || (n == (*current).n2) || - (n == (*current).n3) ) - { - if ( *t1 == 0 ) { - *t1 = i; - } else if ( *t2 == 0 ) { - *t2 = i; - } else if ( *t3 == 0 ) { - *t3 = i; - } else if ( *t4 == 0 ) { - *t4 = i; - } else { - *t5 = i; - } - } - ++i; - } -} - - -// Initialize a new mesh structure -void triload(const string& basename) { - string nodename, elename; - Point3D node1, node2, p; - triangle tri; - int nodecount, tricount, dim, junk1, junk2; - int i; - - nodename = basename + ".node"; - elename = basename + ".ele"; - - cout << "Loading node file: " + nodename + " ...\n"; - - fg_gzifstream node_in( nodename ); - if ( !node_in ) { - cout << "Cannot open file " + nodename + "\n"; - exit(-1); - } - - // the triangle program starts counting at 1 by default which is - // pretty obnoxious. Let's just push null record zero's onto our - // list to compensate - nodes_orig.push_back(node1); - nodes_cart.push_back(node1); - tri_list.push_back(tri); - - node_in >> nodecount >> dim >> junk1 >> junk2; - cout << " Expecting " << nodecount << " nodes\n"; - - for ( i = 1; i <= nodecount; i++ ) { - node_in >> junk1 >> node1 >> junk2; - nodes_orig.push_back(node1); - // printf("%d %.2f %.2f %.2f\n", junk1, node1.x, node1.y, node1.z); - - // convert to radians (before we can convert to cartesian) - p = Point3D( node1.x() * ARCSEC_TO_RAD, - node1.y() * ARCSEC_TO_RAD, - node1.z() ); - - node2 = fgGeodToCart(p); - nodes_cart.push_back(node2); - // printf("%d %.2f %.2f %.2f\n", junk1, node2.x, node2.y, node2.z); - - if ( i == 1 ) { - xmin = xmax = node1.x(); - ymin = ymax = node1.y(); - } else { - if ( node1.x() < xmin ) { - xmin = node1.x(); - } - if ( node1.x() > xmax ) { - xmax = node1.x(); - } - if ( node1.y() < ymin ) { - ymin = node1.y(); - } - if ( node1.y() > ymax ) { - ymax = node1.y(); - } - } - } - - cout << "Loading element file: " + elename + " ...\n"; - fg_gzifstream ele_in( elename ); - if ( !ele_in ) { - cout << "Cannot open file " + elename + "\n"; - exit(-1); - } - - ele_in >> tricount >> junk1 >> junk2; - cout << " Expecting " << tricount << " elements\n"; - - for ( i = 1; i <= tricount; i++ ) { - // fscanf(ele_file, "%d %d %d %d\n", &junk1, - // &(tri.n1), &(tri.n2), &(tri.n3)); - ele_in >> junk1 >> tri.n1 >> tri.n2 >> tri.n3; - // printf("%d %d %d %d\n", junk1, tri.n1, tri.n2, tri.n3); - tri_list.push_back(tri); - } -} - - -// check if a file exists -int file_exists(char *file) { - struct stat stat_buf; - int result; - - cout << "checking " << file << " ... "; - - result = stat(file, &stat_buf); - - if ( result != 0 ) { - // stat failed, no file - cout << "not found.\n"; - return 0; - } else { - // stat succeeded, file exists - cout << "exists.\n"; - return 1; - } -} - - -// check to see if a shared object exists -int shared_object_exists(const char *basepath, const string& ext) { - char file[256], scene_path[256]; - long int index; - - if ( ext == ".sw" ) { - fgBucketGenBasePath(&west_index, scene_path); - index = fgBucketGenIndex(&west_index); - sprintf(file, "%s/%s/%ld.1.se", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - fgBucketGenBasePath(&sw_index, scene_path); - index = fgBucketGenIndex(&sw_index); - sprintf(file, "%s/%s/%ld.1.ne", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - fgBucketGenBasePath(&south_index, scene_path); - index = fgBucketGenIndex(&south_index); - sprintf(file, "%s/%s/%ld.1.nw", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - } - - if ( ext == ".se" ) { - fgBucketGenBasePath(&east_index, scene_path); - index = fgBucketGenIndex(&east_index); - sprintf(file, "%s/%s/%ld.1.sw", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - fgBucketGenBasePath(&se_index, scene_path); - index = fgBucketGenIndex(&se_index); - sprintf(file, "%s/%s/%ld.1.nw", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - fgBucketGenBasePath(&south_index, scene_path); - index = fgBucketGenIndex(&south_index); - sprintf(file, "%s/%s/%ld.1.ne", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - } - - if ( ext == ".ne" ) { - fgBucketGenBasePath(&east_index, scene_path); - index = fgBucketGenIndex(&east_index); - sprintf(file, "%s/%s/%ld.1.nw", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - fgBucketGenBasePath(&ne_index, scene_path); - index = fgBucketGenIndex(&ne_index); - sprintf(file, "%s/%s/%ld.1.sw", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - fgBucketGenBasePath(&north_index, scene_path); - index = fgBucketGenIndex(&north_index); - sprintf(file, "%s/%s/%ld.1.se", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - } - - if ( ext == ".nw" ) { - fgBucketGenBasePath(&west_index, scene_path); - index = fgBucketGenIndex(&west_index); - sprintf(file, "%s/%s/%ld.1.ne", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - fgBucketGenBasePath(&nw_index, scene_path); - index = fgBucketGenIndex(&nw_index); - sprintf(file, "%s/%s/%ld.1.se", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - fgBucketGenBasePath(&north_index, scene_path); - index = fgBucketGenIndex(&north_index); - sprintf(file, "%s/%s/%ld.1.sw", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - } - - if ( ext == ".south" ) { - fgBucketGenBasePath(&south_index, scene_path); - index = fgBucketGenIndex(&south_index); - sprintf(file, "%s/%s/%ld.1.north", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - } - - if ( ext == ".north" ) { - fgBucketGenBasePath(&north_index, scene_path); - index = fgBucketGenIndex(&north_index); - sprintf(file, "%s/%s/%ld.1.south", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - } - - if ( ext == ".west" ) { - fgBucketGenBasePath(&west_index, scene_path); - index = fgBucketGenIndex(&west_index); - sprintf(file, "%s/%s/%ld.1.east", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - } - - if ( ext == ".east" ) { - fgBucketGenBasePath(&east_index, scene_path); - index = fgBucketGenIndex(&east_index); - sprintf(file, "%s/%s/%ld.1.west", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - } - - return(0); -} - - -// my custom file opening routine ... don't open if a shared edge or -// vertex alread exists -FILE *my_open(const string& basename, const string& basepath, - const string& ext) -{ - FILE *fp; - string filename; - - // create the output file name - filename = basename + ext; - - // check if a shared object already exist from a different tile - - if ( shared_object_exists(basepath.c_str(), ext) ) { - // not an actual file open error, but we've already got the - // shared edge, so we don't want to create another one - cout << "not opening\n"; - return(NULL); - } else { - // open the file - fp = fopen(filename.c_str(), "w"); - cout << "Opening " + filename + "\n"; - return(fp); - } -} - - -// dump in WaveFront .obj format -void dump_obj(const string& basename, const string& basepath) { - Point3D node; - double n1[3], n2[3], n3[3], n4[3], n5[3], norm[3], temp; - FILE *fp, *sw, *se, *ne, *nw, *north, *south, *east, *west, *body; - int i, t1, t2, t3, t4, t5, count, size; - double x, y, z; - - sw = my_open(basename, basepath, ".sw"); - se = my_open(basename, basepath, ".se"); - ne = my_open(basename, basepath, ".ne"); - nw = my_open(basename, basepath, ".nw"); - - north = my_open(basename, basepath, ".north"); - south = my_open(basename, basepath, ".south"); - east = my_open(basename, basepath, ".east"); - west = my_open(basename, basepath, ".west"); - - body = my_open(basename, basepath, ".body"); - - cout << "Dumping edges file basename: " + basename + " ...\n"; - - // dump vertices - cout << " writing vertices\n"; - - iterator_3d last = nodes_orig.end(); - iterator_3d current = nodes_orig.begin(); - ++current; - for ( ; current != last; ++current) { - node = *current; - - if ( (fabs(node.y() - ymin) < FG_EPSILON) && - (fabs(node.x() - xmin) < FG_EPSILON) ) { - fp = sw; - } else if ( (fabs(node.y() - ymin) < FG_EPSILON) && - (fabs(node.x() - xmax) < FG_EPSILON) ) { - fp = se; - } else if ( (fabs(node.y() - ymax) < FG_EPSILON) && - (fabs(node.x() - xmax) < FG_EPSILON)) { - fp = ne; - } else if ( (fabs(node.y() - ymax) < FG_EPSILON) && - (fabs(node.x() - xmin) < FG_EPSILON) ) { - fp = nw; - } else if ( fabs(node.x() - xmin) < FG_EPSILON ) { - fp = west; - } else if ( fabs(node.x() - xmax) < FG_EPSILON ) { - fp = east; - } else if ( fabs(node.y() - ymin) < FG_EPSILON ) { - fp = south; - } else if ( fabs(node.y() - ymax) < FG_EPSILON ) { - fp = north; - } else { - fp = body; - } - - x = node.x(); - y = node.y(); - z = node.z(); - - if ( fp != NULL ) { - fprintf(fp, "gdn %.2f %.2f %.2f\n", x, y, z); - } - } - - cout << " calculating and writing normals\n"; - - // calculate and generate normals - size = nodes_orig.size(); - for ( i = 1; i < size; i++ ) { - // printf("Finding normal\n"); - - find_tris(i, &t1, &t2, &t3, &t4, &t5); - - n1[0] = n1[1] = n1[2] = 0.0; - n2[0] = n2[1] = n2[2] = 0.0; - n3[0] = n3[1] = n3[2] = 0.0; - n4[0] = n4[1] = n4[2] = 0.0; - n5[0] = n5[1] = n5[2] = 0.0; - - count = 1; - calc_normal(nodes_cart[tri_list[t1].n1], - nodes_cart[tri_list[t1].n2], - nodes_cart[tri_list[t1].n3], - n1); - - if ( t2 > 0 ) { - calc_normal(nodes_cart[tri_list[t2].n1], - nodes_cart[tri_list[t2].n2], - nodes_cart[tri_list[t2].n3], - n2); - count = 2; - } - - if ( t3 > 0 ) { - calc_normal(nodes_cart[tri_list[t3].n1], - nodes_cart[tri_list[t3].n2], - nodes_cart[tri_list[t3].n3], - n3); - count = 3; - } - - if ( t4 > 0 ) { - calc_normal(nodes_cart[tri_list[t4].n1], - nodes_cart[tri_list[t4].n2], - nodes_cart[tri_list[t4].n3], - n4); - count = 4; - } - - if ( t5 > 0 ) { - calc_normal(nodes_cart[tri_list[t5].n1], - nodes_cart[tri_list[t5].n2], - nodes_cart[tri_list[t5].n3], - n5); - count = 5; - } - - // printf(" norm[2] = %.2f %.2f %.2f\n", n1[2], n2[2], n3[2]); - - norm[0] = ( n1[0] + n2[0] + n3[0] + n4[0] + n5[0] ) / (double)count; - norm[1] = ( n1[1] + n2[1] + n3[1] + n4[1] + n5[1] ) / (double)count; - norm[2] = ( n1[2] + n2[2] + n3[2] + n4[2] + n5[2] ) / (double)count; - - // printf(" count = %d\n", count); - // printf(" Ave. normal = %.4f %.4f %.4f\n", norm[0], norm[1], - // norm[2]); - MAT3_NORMALIZE_VEC(norm, temp); - // printf(" Normalized ave. normal = %.4f %.4f %.4f\n", - // norm[0], norm[1], norm[2]); - - fp = NULL; - - if ( (fabs(nodes_orig[i].y() - ymin) < FG_EPSILON) && - (fabs(nodes_orig[i].x() - xmin) < FG_EPSILON) ) { - fp = sw; - } else if ( (fabs(nodes_orig[i].y() - ymin) < FG_EPSILON) && - (fabs(nodes_orig[i].x() - xmax) < FG_EPSILON) ) { - fp = se; - } else if ( (fabs(nodes_orig[i].y() - ymax) < FG_EPSILON) && - (fabs(nodes_orig[i].x() - xmax) < FG_EPSILON)) { - fp = ne; - } else if ( (fabs(nodes_orig[i].y() - ymax) < FG_EPSILON) && - (fabs(nodes_orig[i].x() - xmin) < FG_EPSILON) ) { - fp = nw; - } else if ( fabs(nodes_orig[i].x() - xmin) < FG_EPSILON ) { - fp = west; - } else if ( fabs(nodes_orig[i].x() - xmax) < FG_EPSILON ) { - fp = east; - } else if ( fabs(nodes_orig[i].y() - ymin) < FG_EPSILON ) { - fp = south; - } else if ( fabs(nodes_orig[i].y() - ymax) < FG_EPSILON ) { - fp = north; - } - if ( fp != NULL ) { - fprintf(fp, "vn %.4f %.4f %.4f\n", norm[0], norm[1], norm[2]); - } - } - - if ( sw ) { fclose(sw); } - if ( se ) { fclose(se); } - if ( ne ) { fclose(ne); } - if ( nw ) { fclose(nw); } - - if ( north ) { fclose(north); } - if ( south ) { fclose(south); } - if ( east ) { fclose(east); } - if ( west ) { fclose(west); } - - if ( body ) { fclose(body); } -} - - -int main(int argc, char **argv) { - string basename, basepath, temp; - fgBUCKET p; - long int index; - int len; - - basename = argv[1]; - - // find the base path of the file - basepath = extract_path(basename); - basepath = extract_path(basepath); - basepath = extract_path(basepath); - cout << "basepath = " + basepath + "\n"; - - // find the index of the current file - temp = extract_file(basename); - len = temp.length(); - if ( len >= 2 ) { - temp = temp.substr(0, len-2); - } - index = atoi( temp.c_str() ); - cout << "index = " << index << "\n"; - fgBucketParseIndex(index, &p); - - cout << "bucket = " << p.lon << " " << p.lat << " " << - p.x << " " << p.y << "\n"; - - // generate the indexes of the neighbors - fgBucketOffset(&p, &ne_index, 1, 1); - fgBucketOffset(&p, &nw_index, -1, 1); - fgBucketOffset(&p, &se_index, 1, -1); - fgBucketOffset(&p, &sw_index, -1, -1); - - fgBucketOffset(&p, &north_index, 0, 1); - fgBucketOffset(&p, &south_index, 0, -1); - fgBucketOffset(&p, &east_index, 1, 0); - fgBucketOffset(&p, &west_index, -1, 0); - - // printf("Corner indexes = %ld %ld %ld %ld\n", - // ne_index, nw_index, sw_index, se_index); - // printf("Edge indexes = %ld %ld %ld %ld\n", - // north_index, south_index, east_index, west_index); - - - // load the input data files - triload(basename); - - // dump in WaveFront .obj format - dump_obj(basename, basepath); - - return(0); -} - - -// $Log$ -// Revision 1.7 1998/11/06 21:33:57 curt -// Updates to go along with changes in fgstream. -// -// Revision 1.6 1998/10/21 14:56:20 curt -// Fixed a units conversion bug. -// -// Revision 1.5 1998/10/20 15:50:33 curt -// whitespace tweak. -// -// Revision 1.4 1998/10/18 01:17:27 curt -// Point3D tweaks. -// -// Revision 1.3 1998/09/22 23:49:56 curt -// C++-ified, STL-ified, and string-ified. -// -// Revision 1.2 1998/09/21 23:16:23 curt -// Converted to c++ style comments. -// -// Revision 1.1 1998/07/08 14:59:13 curt -// *.[ch] renamed to *.[ch]xx -// -// Revision 1.11 1998/07/04 00:56:40 curt -// typedef'd struct fgBUCKET. -// -// Revision 1.10 1998/05/02 01:54:37 curt -// Converting to polar3d.h routines. -// -// Revision 1.9 1998/04/18 04:01:20 curt -// Now use libMath rather than having local copies of math routines. -// -// Revision 1.8 1998/04/14 02:26:08 curt -// Code reorganizations. Added a Lib/ directory for more general libraries. -// -// Revision 1.7 1998/04/08 23:21:13 curt -// Adopted Gnu automake/autoconf system. -// -// Revision 1.6 1998/03/03 15:36:13 curt -// Tweaks for compiling with g++ -// -// Revision 1.5 1998/03/03 03:37:04 curt -// Cumulative tweaks. -// -// Revision 1.4 1998/01/31 00:41:26 curt -// Made a few changes converting floats to doubles. -// -// Revision 1.3 1998/01/27 18:37:04 curt -// Lots of updates to get back in sync with changes made over in .../Src/ -// -// Revision 1.2 1998/01/14 15:54:43 curt -// Initial revision completed. -// -// Revision 1.1 1998/01/14 02:11:31 curt -// Initial revision. -// - diff --git a/Tools/SplitTris/splittris.hxx b/Tools/SplitTris/splittris.hxx deleted file mode 100644 index 12787872d..000000000 --- a/Tools/SplitTris/splittris.hxx +++ /dev/null @@ -1,89 +0,0 @@ -// splittris.hxx -- read in a .ele/.node file pair generated by the triangle -// program and output edge vertices w/ normals. -// -// Written by Curtis Olson, started January 1998. -// -// Copyright (C) 1997 Curtis L. Olson - curt@infoplane.com -// -// 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. -// -// $Id$ -// (Log is kept at end of this file) - - - -#ifndef SPLITTRIS_HXX -#define SPLITTRIS_HXX - - -#include -#include -#include - -#include -#include "Include/fg_stl_config.h" - -#ifdef NEEDNAMESPACESTD -using namespace std; -#endif - -#include - - -// A triangle (indices of the three nodes) -typedef struct { - int n1, n2, n3; -} triangle; - - -typedef vector < Point3D > container_3d; -typedef container_3d::iterator iterator_3d; -typedef container_3d::const_iterator const_iterator_3d; - -typedef vector < triangle > container_tri; -typedef container_tri::iterator iterator_tri; -typedef container_tri::const_iterator const_iterator_tri; - - -// Initialize a new mesh structure -void triload(const string& basename); - - -#endif // SPLITTRIS_HXX - - -// $Log$ -// Revision 1.4 1998/10/18 01:17:28 curt -// Point3D tweaks. -// -// Revision 1.3 1998/09/22 23:49:58 curt -// C++-ified, STL-ified, and string-ified. -// -// Revision 1.2 1998/09/21 23:16:24 curt -// Converted to c++ style comments. -// -// Revision 1.1 1998/07/08 14:59:14 curt -// *.[ch] renamed to *.[ch]xx -// -// Revision 1.3 1998/03/03 15:36:13 curt -// Tweaks for compiling with g++ -// -// Revision 1.2 1998/01/15 02:49:25 curt -// Misc. housekeeping. -// -// Revision 1.1 1998/01/14 02:11:32 curt -// Initial revision. -// - diff --git a/Tools/Stripe_u/Makefile.am b/Tools/Stripe_u/Makefile.am deleted file mode 100644 index 8373ea88b..000000000 --- a/Tools/Stripe_u/Makefile.am +++ /dev/null @@ -1,30 +0,0 @@ -bin_PROGRAMS = strips - -strips_SOURCES = \ - add.c add.h \ - bands.c \ - common.c common.h \ - define.h \ - extend.h \ - free.c free.h \ - global.h \ - glove.h \ - init.c init.h \ - local.c local.h \ - my_global.h \ - newpolve.c \ - options.c options.h \ - output.c output.h \ - outputex.c outputex.h \ - partial.c partial.h \ - polverts.h polvertsex.h \ - queue.c queue.h \ - sgi_triang.c sgi_triangex.c \ - struct.c struct.h \ - structex.c \ - sturcts.h sturctsex.h \ - ties.c ties.h \ - triangulate.h triangulatex.h \ - util.c util.h - -strips_LDADD = $(base_LIBS) diff --git a/Tools/Stripe_u/add.c b/Tools/Stripe_u/add.c deleted file mode 100644 index 7d90357fd..000000000 --- a/Tools/Stripe_u/add.c +++ /dev/null @@ -1,386 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: add.c - This file contains the procedure code that will add information - to our data structures. -*/ -/*---------------------------------------------------------------------*/ - -#include -#include -#include -#include -#include "global.h" -#include "queue.h" -#include "polverts.h" -#include "triangulate.h" -#include "ties.h" -#include "outputex.h" -#include "options.h" -#include "local.h" - -BOOL new_vertex(double difference, int id1,int id2, - struct vert_struct *n) -{ - /* Is the difference between id1 and id2 (2 normal vertices that - mapped to the same vertex) greater than the - threshold that was specified? - */ - struct vert_struct *pn1,*pn2; - double dot_product; - double distance1, distance2,distance; - double rad; - char arg1[100]; - char arg2[100]; - - pn1 = n + id1; - pn2 = n + id2; - - dot_product = ((pn1->x) * (pn2->x)) + - ((pn1->y) * (pn2->y)) + - ((pn1->z) * (pn2->z)); - /* Get the absolute value */ - if (dot_product < 0) - dot_product = dot_product * -1; - - distance1 = sqrt( (pn1->x * pn1->x) + - (pn1->y * pn1->y) + - (pn1->z * pn1->z) ); - distance2 = sqrt( (pn2->x * pn2->x) + - (pn2->y * pn2->y) + - (pn2->z * pn2->z) ); - distance = distance1 * distance2; - - rad = acos((double)dot_product/(double)distance); - /* convert to degrees */ - rad = (180 * rad)/PI; - - if ( rad <= difference) - return FALSE; - - /* double checking because of imprecision with floating - point acos function - */ - sprintf( arg1,"%.5f", rad ); - sprintf( arg2,"%.5f", difference ); - if ( strcmp( arg1, arg2 ) <=0 ) - return( FALSE ); - if ( rad <= difference) - return FALSE; - else - return TRUE; -} - -BOOL Check_VN(int vertex,int normal, struct vert_added *added) -{ - /* Check to see if we already added this vertex and normal */ - register int x,n; - - n = (added+vertex)->num; - for (x = 0; x < n; x++) - { - if (*((added+vertex)->normal+x) == normal) - return TRUE; - } - return FALSE; -} - -BOOL norm_array(int id, int vertex, double normal_difference, - struct vert_struct *n, int num_vert) -{ - static int last; - static struct vert_added *added; - register int x; - static BOOL first = TRUE; - - if (first) - { - /* This is the first time that we are in here, so we will allocate - a structure that will save the vertices that we added, so that we - do not add the same thing twice - */ - first = FALSE; - added = (struct vert_added *) malloc (sizeof (struct vert_added ) * num_vert); - /* The number of vertices added for each vertex must be initialized to - zero - */ - for (x = 0; x < num_vert; x++) - (added+x)->num = 0; - } - - if (vertex) - /* Set the pointer to the vertex, we will be calling again with the - normal to fill it with - */ - last = id; - else - { - /* Fill the pointer with the id of the normal */ - if (*(vert_norms + last) == 0) - *(vert_norms + last) = id; - else if ((*(vert_norms + last) != id) && ((int)normal_difference != 360)) - { - /* difference is big enough, we need to create a new vertex */ - if (new_vertex(normal_difference,id,*(vert_norms + last),n)) - { - /* First check to see if we added this vertex and normal already */ - if (Check_VN(last,id,added)) - return FALSE; - /* OK, create the new vertex, and have its id = the number of vertices - and its normal what we have here - */ - vert_norms = realloc(vert_norms, sizeof(int) * (num_vert + 1)); - if (!vert_norms) - { - printf("Allocation error - aborting\n"); - exit(1); - } - *(vert_norms + num_vert) = id; - /* We created a new vertex, now put it in our added structure so - we do not add the same thing twice - */ - (added+last)->num = (added+last)->num + 1; - if ((added+last)->num == 1) - { - /* First time */ - (added+last)->normal = (int *) malloc (sizeof (int ) * 1); - *((added+last)->normal) = id; - } - else - { - /* Not the first time, reallocate space */ - (added+last)->normal = realloc((added+last)->normal,sizeof(int) * (added+last)->num); - *((added+last)->normal+((added+last)->num-1)) = id; - } - return TRUE; - } - } - } - return FALSE; -} - -void add_texture(int id,BOOL vertex) -{ - /* Save the texture with its vertex for future use when outputting */ - static int last; - - if (vertex) - last = id; - else - *(vert_texture+last) = id; -} - -int add_vert_id(int id, int index_count) -{ - register int x; - - /* Test if degenerate, if so do not add degenerate vertex */ - for (x = 1; x < index_count ; x++) - { - if (ids[x] == id) - return 0; - } - ids[index_count] = id; - return 1; -} - -void add_norm_id(int id, int index_count) -{ - norms[index_count] = id; -} - -void AddNewFace(int ids[MAX1], int vert_count, int face_id, int norms[MAX1]) -{ -PF_FACES pfNode; -int *pTempInt; -int *pnorms; -F_EDGES **pTempVertptr; -int *pTempmarked, *pTempwalked; -register int y,count = 0,sum = 0; - - /* Add a new face into our face data structure */ - - pfNode = (PF_FACES) malloc(sizeof(F_FACES) ); - if ( pfNode ) - { - pfNode->pPolygon = (int*) malloc(sizeof(int) * (vert_count) ); - pfNode->pNorms = (int*) malloc(sizeof(int) * (vert_count) ); - pfNode->VertandId = (F_EDGES**)malloc(sizeof(F_EDGES*) * (vert_count)); - pfNode->marked = (int*)malloc(sizeof(int) * (vert_count)); - pfNode->walked = (int*)malloc(sizeof(int) * (vert_count)); - } - pTempInt =pfNode->pPolygon; - pnorms = pfNode->pNorms; - pTempmarked = pfNode->marked; - pTempwalked = pfNode->walked; - pTempVertptr = pfNode->VertandId; - pfNode->nPolSize = vert_count; - pfNode->seen = -1; - pfNode->seen2 = -1; - for (y=1;y<=vert_count;y++) - { - *(pTempInt + count) = ids[y]; - *(pnorms + count) = norms[y]; - *(pTempmarked + count) = FALSE; - *(pTempwalked + count) = -1; - *(pTempVertptr+count) = NULL; - count++; - } - AddHead(PolFaces[face_id-1],(PLISTINFO) pfNode); -} - - -void CopyFace(int ids[MAX1], int vert_count, int face_id, int norms[MAX1]) -{ -PF_FACES pfNode; -int *pTempInt; -int *pnorms; -F_EDGES **pTempVertptr; -int *pTempmarked, *pTempwalked; -register int y,count = 0,sum = 0; - - /* Copy a face node into a new node, used after the global algorithm - is run, so that we can save whatever is left into a new structure - */ - - pfNode = (PF_FACES) malloc(sizeof(F_FACES) ); - if ( pfNode ) - { - pfNode->pPolygon = (int*) malloc(sizeof(int) * (vert_count) ); - pfNode->pNorms = (int*) malloc(sizeof(int) * (vert_count) ); - pfNode->VertandId = (F_EDGES**)malloc(sizeof(F_EDGES*) * (vert_count)); - pfNode->marked = (int*)malloc(sizeof(int) * (vert_count)); - pfNode->walked = (int*)malloc(sizeof(int) * (vert_count)); - } - pTempInt =pfNode->pPolygon; - pnorms = pfNode->pNorms; - pTempmarked = pfNode->marked; - pTempwalked = pfNode->walked; - pTempVertptr = pfNode->VertandId; - pfNode->nPolSize = vert_count; - pfNode->seen = -1; - pfNode->seen2 = -1; - for (y=0;y v2) - { - t = v1; - v1 = v2; - v2 = t; - } - - pListHead = PolEdges[v1]; - temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count); - if (temp == NULL) - { - printf("Have the wrong edge \n:"); - exit(1); - } - - while (flag) - { - if (v2 == temp->edge[0]) - return; - else - temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,++count); - - } -} - -void Add_AdjEdge(int v1,int v2,int fnum,int index1 ) -{ - PF_EDGES temp = NULL; - PF_FACES temp2 = NULL; - PF_EDGES pfNode; - ListHead *pListHead; - ListHead *pListFace; - BOOL flag = TRUE; - register int count = 0; - register int t,v3 = -1; - - if (v1 > v2) - { - t = v1; - v1 = v2; - v2 = t; - } - pListFace = PolFaces[fnum]; - temp2 = (PF_FACES) PeekList(pListFace,LISTHEAD,0); - pListHead = PolEdges[v1]; - temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count); - if (temp == NULL) - flag = FALSE; - count++; - while (flag) - { - if (v2 == temp->edge[0]) - { - /* If greater than 2 polygons adjacent to an edge, then we will - only save the first 2 that we found. We will have a small performance - hit, but this does not happen often. - */ - if (temp->edge[2] == -1) - temp->edge[2] = fnum; - else - v3 = temp->edge[2]; - flag = FALSE; - } - else - { - temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count); - count++; - if (temp == NULL) - flag = FALSE; - } - } - - /* Did not find it */ - if (temp == NULL) - { - pfNode = (PF_EDGES) malloc(sizeof(F_EDGES) ); - if ( pfNode ) - { - pfNode->edge[0] = v2; - pfNode->edge[1] = fnum; - pfNode->edge[2] = v3; - AddTail( PolEdges[v1], (PLISTINFO) pfNode ); - } - else - { - printf("Out of memory!\n"); - exit(1); - } - - *(temp2->VertandId+index1) = pfNode; - } - else - *(temp2->VertandId+index1) = temp; - -} - - diff --git a/Tools/Stripe_u/add.h b/Tools/Stripe_u/add.h deleted file mode 100644 index 607363e5e..000000000 --- a/Tools/Stripe_u/add.h +++ /dev/null @@ -1,25 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: add.h ------------------------------------------------------------------------*/ - -BOOL new_vertex(); -BOOL Check_VN(); -BOOL norm_array(); -void add_texture(); -int add_vert_id(); -void add_norm_id(); -void AddNewFace(); -void CopyFace(); -void Add_Edge(); -void Add_AdjEdge(); - - - diff --git a/Tools/Stripe_u/bands.c b/Tools/Stripe_u/bands.c deleted file mode 100644 index 14a9fe4c0..000000000 --- a/Tools/Stripe_u/bands.c +++ /dev/null @@ -1,549 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: bands.c - This file contains the main procedure code that will read in the - object and then call the routines that produce the triangle strips. -*/ -/*---------------------------------------------------------------------*/ - - -#include -#include -#include -#include -#include "global.h" -#include "polverts.h" -#include "triangulate.h" -#include "ties.h" -#include "outputex.h" -#include "options.h" -#include "local.h" -#include "init.h" -#include "free.h" -#include "add.h" - -#define MAX1 60 -/* TIMING for Windows */ -#ifdef WIN32 -#include -#include -/* TIMING for UNIX */ -#else -#include -#include -#include -#include -struct timeval tm; -struct timezone tz; -double et; -#define START gettimeofday(&tm,&tz);\ - et = (tm.tv_sec)+ (0.000001* (tm.tv_usec)); - -#define STOP gettimeofday(&tm,&tz);\ - et = (tm.tv_sec)+(0.000001*(tm.tv_usec)) - et; -#endif - - -void get_time() -{ - /* For timing */ - #ifdef WIN32 - struct _timeb timebuffer; - char *timeline; - #else - long timer; - #endif - - - #ifdef WIN32 - _ftime( &timebuffer ); - timeline = ctime( & ( timebuffer.time ) ); - printf( "The time is %.19s.%hu %s", timeline, timebuffer.millitm, &timeline[20] ); - #else - printf("Time for last frame = %lf seconds\n", et); - #endif -} - -/* -** - Here the main program begins. It will start by loading in a .obj file - then it will convert the polygonal model into triangle strips. -** -*/ - -void main (int argc,char *argv[]) -{ - char *fname,*all,buff[255], *ptr, *ptr2; - FILE *file, *bands; - int face_id=0, vert_count, loop, num=0,num2; - float center[3]; - int temp[MAX1],vertex,strips, swaps,tempi,cost,triangles; - int f,t,tr,g; - char *file_open; - int num_vert = 0, - num_faces = 0, - num_nvert = 0, - num_edges = 0, - num_texture = 0, - num_tris = 0; - double fra = 0.0; - BOOL texture, normal, normal_and_texture,quads = FALSE; - - /* Options variables */ - float norm_difference; - - /* Structures for the object */ - struct vert_struct *vertices = NULL, - *nvertices = NULL, - *pvertices = NULL, - *pnvertices = NULL; - - get_time(); - START - - /* File that will contain the triangle strip data */ - bands = fopen("bands.d","w"); - - /* - Scan the file once to find out the number of vertices, - vertice normals, and faces so we can set up some memory - structures - */ - /* Interpret the options specified */ - norm_difference = get_options(argc,argv,&f,&t,&tr,&g); - if (f == BINARY) - file_open = "rb"; - else - file_open = "r"; - - fname = argv[argc-1]; - printf ("File: %s\n",fname); - /*printf ("Scanning...%s ",file_open);*/ - - - /* File can be in binary for faster reading */ - if (file = fopen (fname,file_open)) - { - while (!feof (file)) - { - /* Read a line */ - if (f == BINARY) - fread (buff,sizeof(char) * 255,1, file); - else - fgets (buff, sizeof(char) * 255, file); - num++; - /* At a vertex */ - if (*buff == 'v') - { - /* At a normal */ - if (*(buff+1)=='n') - num_nvert++; - else if (*(buff+1)=='t') - num_texture++; - /* At a regular vertex */ - else - num_vert++; - } - /* At a face */ - else if (*buff == 'f') - { - num_faces++; - strtok(buff, " "); - tempi = 0; - while (strtok(NULL, " ") != NULL) tempi++; - num_tris += tempi - 2; - } - } - fclose (file); - } - - else - { - printf("Error in the file name\n"); - exit(1); - } - - - /* Allocate structures for the information */ - Start_Face_Struct(num_faces); - vertices = (struct vert_struct *) - malloc (sizeof (struct vert_struct) * num_vert); - - if (num_nvert > 0) - { - nvertices = (struct vert_struct *) - malloc (sizeof (struct vert_struct) * num_nvert); - vert_norms = (int *) - malloc (sizeof (int) * num_vert); - /* Initialize entries to zero, in case there are 2 hits - to the same vertex we will know it - used for determining - the normal difference - */ - init_vert_norms(num_vert); - } - else - nvertices = NULL; - - if (num_texture > 0) - { - vert_texture = (int *) malloc (sizeof(int) * num_vert); - init_vert_texture(num_vert); - } - - /* Set up the temporary 'p' pointers - */ - pvertices = vertices; - pnvertices = nvertices; - - /* Load the object into memory */ - /*printf (" Loading...");*/ - - fprintf(bands,"#%s: a triangle strip representation created by STRIPE.\n#This is a .objf file\n#by Francine Evans\n",fname); - - /* File will be put in a list for faster execution if file is in binary */ - if (file = fopen(fname,file_open)) - { - if (f == BINARY) - { - all = (char *) malloc (sizeof(char) * 255 * num); - fread(all,sizeof(char) * 255 * num, 1, file); - ptr = all; - } - else - ptr = (char *) malloc (sizeof(char) * 255 * num); - } - - - while (num > 0) - { - num--; - if (f == ASCII) - fgets (ptr, sizeof(char) * 255, file); - else - ptr = ptr + 255; - - /* Load in vertices/normals */ - if (*ptr == 'v') - { - if (*(ptr+1)=='n') - { - sscanf (ptr+3,"%lf%lf%lf", - &(pnvertices->x), - &(pnvertices->y), - &(pnvertices->z)); - fprintf(bands,"vn %lf %lf %lf\n", - pnvertices->x,pnvertices->y,pnvertices->z); - ++pnvertices; - } - else if (*(ptr+1)=='t') - { - sscanf (ptr+3,"%f%f%f",¢er[0],¢er[1],¢er[2]); - fprintf(bands,"vt %f %f %f\n",center[0],center[1],center[2]); - } - else - { - sscanf (ptr+2,"%lf%lf%lf", - &(pvertices->x), - &(pvertices->y), - &(pvertices->z)); - fprintf(bands,"v %lf %lf %lf\n", - pvertices->x,pvertices->y,pvertices->z); - ++pvertices; - } - } - - else if (*ptr == 'f') - { - /* Read in faces */ - num2 = 0; - face_id++; - ptr2 = ptr+1; - normal = FALSE; texture = FALSE, normal_and_texture = FALSE; - while (*ptr2) - { - if (*ptr2 >='0' && *ptr2 <='9') - { - num2++; - ++ptr2; - while (*ptr2 && (*ptr2!=' ' && *ptr2!='/')) - ptr2++; - /* There are normals in this line */ - if (*ptr2 == '/') - { - if (*(ptr2+1) == '/') - normal = TRUE; - else - texture = TRUE; - } - else if (*ptr2 == ' ') - { - if ((num2 == 3) && (texture)) - normal_and_texture = TRUE; - } - } - else - ++ptr2; - } - - ptr2 = ptr+1; - - /* loop on the number of numbers in this line of face data - */ - vert_count = 0; - - for (loop=0;loop'9') - { - if (*ptr2 == '-') - break; - ptr2++; - } - vertex = atoi(ptr2)-1; - if (vertex < 0) - { - vertex = num_vert + vertex; - *ptr2 = ' '; - ptr2++; - } - /* If there are either normals or textures with the vertices - in this file, the data alternates so we must read it this way - */ - if ( (normal) && (!normal_and_texture)) - { - if (loop%2) - { - add_norm_id(vertex,vert_count); - /* Test here to see if we added a new vertex, since the - vertex has more than one normal and the 2 normals are greater - than the threshold specified - */ - if (norm_array(vertex,0,norm_difference,nvertices,num_vert)) - { - /* Add a new vertex and change the - id of the vertex that we just read to the id of the new - vertex that we just added - */ - /* Put it in the output file, note the added vertices will - be after the normals and separated from the rest of the - vertices. Will not affect our viewer - */ - fprintf(bands,"v %lf %lf %lf\n", - (vertices + temp[vert_count - 1])->x, - (vertices + temp[vert_count - 1])->y, - (vertices + temp[vert_count - 1])->z); - num_vert++; - temp[vert_count - 1] = num_vert - 1; - if (!(add_vert_id(num_vert - 1,vert_count))) - vert_count--; - } - } - /* the vertex */ - else - { - temp[vert_count] = vertex ; - vert_count++; - if (!(add_vert_id(vertex,vert_count))) - vert_count--; - norm_array(vertex,1,norm_difference,nvertices,num_vert); - } - } - - /* Else there are vertices and textures with the data */ - else if (normal_and_texture) - { - if( !((loop+1)%3)) - { - add_norm_id(vertex,vert_count); - /* Test here to see if we added a new vertex, since the - vertex has more than one normal and the 2 normals are greater - than the threshold specified - */ - if (norm_array(vertex,0,norm_difference,nvertices,num_vert)) - { - /* Add a new vertex and change the - id of the vertex that we just read to the id of the new - vertex that we just added - */ - /* Put it in the output file, note the added vertices will - be after the normals and separated from the rest of the - vertices. Will not affect our viewer - */ - fprintf(bands,"v %lf %lf %lf\n", - (vertices + temp[vert_count - 1])->x, - (vertices + temp[vert_count - 1])->y, - (vertices + temp[vert_count - 1])->z); - num_vert++; - temp[vert_count - 1] = num_vert - 1; - if (!(add_vert_id(num_vert - 1,vert_count))) - vert_count--; - } - } - /* the vertex */ - else if ((loop == 0) || (*(ptr2-1) == ' ')) - { - temp[vert_count] = vertex ; - vert_count++; - if (vert_count == 4) - quads = TRUE; - if (!(add_vert_id(vertex,vert_count))) - vert_count--; - add_texture(vertex,TRUE); - norm_array(vertex,1,norm_difference,nvertices,num_vert); - } - else /* The texture */ - add_texture(vertex,FALSE); - } - - else if ( texture ) - { - /* the vertex */ - if (!(loop%2)) - { - temp[vert_count] = vertex ; - vert_count++; - if (vert_count == 4) - quads = TRUE; - add_texture(vertex,TRUE); - if (!(add_vert_id(vertex,vert_count))) - vert_count--; - norm_array(vertex,1,norm_difference,nvertices,num_vert); - } - else /* texture */ - add_texture(vertex,FALSE); - } - - else - { - /*** no nvertices ***/ - temp[vert_count] = vertex ; - vert_count++; - if (vert_count == 4) - quads = TRUE; - if (!(add_vert_id(vertex,vert_count))) - vert_count--; - } - while (*ptr2>='0' && *ptr2<='9') - ptr2++; - } - /* Done with the polygon */ - num_edges += vert_count; - /* add it to face structure */ - if (vert_count >= 3) - AddNewFace(ids,vert_count,face_id,norms); - else - face_id--; - if (vert_count == 4) - quads = TRUE; - } - else if ((g == TRUE) && (face_id > 0) - && ((*ptr == 'g') || (*ptr == 's') || (*ptr == 'm') || (*ptr == 'o'))) - { - /* The user specified that the strips will be contained in each group - from the data file, so we just finished a group and will find the - triangle strips in it. - */ - Start_Edge_Struct(num_vert); - Find_Adjacencies(face_id); - if (quads) - { - Init_Table_SGI(); - Build_SGI_Table(num_vert,face_id); - /* Code for lengths of walks in each direction */ - Save_Walks(face_id,TRUE); - - /* Code for finding the bands */ - Find_Bands(face_id,bands,&swaps,&strips,&cost,&triangles,num_nvert,vert_norms,num_texture,vert_texture); - - /* Remove the faces that we did so that we can - run the strip code on the rest of the faces that are left - */ - if (cost != 0) - { - printf("Total %d triangles with %d cost\n",triangles,cost); - Save_Rest(&face_id); - printf("We saved %d .... now doing the local algorithm\n",face_id); - fprintf(bands,"\n#local\n"); - End_Edge_Struct(num_vert); - Start_Edge_Struct(num_vert); - Find_Adjacencies(face_id); - } - } - - SGI_Strip(num_vert,face_id,bands,t,tr); - - /* Get the total cost */ - Output_TriEx(-1,-2,-3,NULL,-1,-20,cost); - - End_Face_Struct(num_faces); - End_Edge_Struct(num_vert); - cost = 0; - face_id = 0; - quads = FALSE; - Start_Face_Struct(num_faces-face_id); - num_faces = num_faces - face_id; - Free_Strips(); - } -} - - /* Done reading in all the information into data structures */ - num_faces = face_id; - fclose (file); - /*printf(" Done.\n\n");*/ - free(vertices); - free(nvertices); - - /*printf ("Vertices: %d\nNormals: %d\nFaces: %d\n",num_vert,num_nvert,num_faces);*/ - Start_Edge_Struct(num_vert); - Find_Adjacencies(num_faces); - - /* Initialize it */ - Init_Table_SGI(); - /* Build it */ - Build_SGI_Table(num_vert,num_faces); - - InitStripTable(); - - - if (quads) - { - /* Code for lengths of walks in each direction */ - Save_Walks(num_faces,TRUE); - - /* Code for finding the bands */ - Find_Bands(num_faces,bands,&swaps,&strips,&cost,&triangles,num_nvert,vert_norms,num_texture,vert_texture); - /*printf("Total %d triangles with %d cost\n",triangles,cost);*/ - - /* Remove the faces that we did so that we can - run the strip code on the rest of the faces that are left - */ - Save_Rest(&num_faces); - /*printf("We saved %d .... now doing the local algorithm\n",num_faces);*/ - fprintf(bands,"\n#local\n"); - End_Edge_Struct(num_vert); - Start_Edge_Struct(num_vert); - Find_Adjacencies(num_faces); - } - - SGI_Strip(num_vert,num_faces,bands,t,tr); - - /* Get the total cost */ - Output_TriEx(-1,-2,-3,NULL,-1,-20,cost); - - End_Face_Struct(num_faces); - End_Edge_Struct(num_vert); - fclose(bands); - STOP - - get_time(); - -} - diff --git a/Tools/Stripe_u/common.c b/Tools/Stripe_u/common.c deleted file mode 100644 index 6e553f149..000000000 --- a/Tools/Stripe_u/common.c +++ /dev/null @@ -1,811 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: common.c - This file contains common code used in both the local and global algorithm -*/ -/*---------------------------------------------------------------------*/ - - -#include -#include "polverts.h" -#include "extend.h" -#include "output.h" -#include "triangulate.h" -#include "util.h" -#include "add.h" - -int Old_Adj(int face_id) -{ - /* Find the bucket that the face_id is currently in, - because maybe we will be deleting it. - */ - PF_FACES temp = NULL; - ListHead *pListHead; - int size,y; - - pListHead = PolFaces[face_id]; - temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); - if ( temp == NULL ) - { - printf("The face was already deleted, there is an error\n"); - exit(0); - } - - size = temp->nPolSize; - if (Done(face_id,size,&y) == NULL) - { - printf("There is an error in finding the face\n"); - exit(0); - } - return y; -} - -int Number_Adj(int id1, int id2, int curr_id) -{ - /* Given edge whose endpoints are specified by id1 and id2, - determine how many polygons share this edge and return that - number minus one (since we do not want to include the polygon - that the caller has already). - */ - - int size,y,count=0; - PF_EDGES temp = NULL; - PF_FACES temp2 = NULL; - ListHead *pListHead; - BOOL there= FALSE; - - /* Always want smaller id first */ - switch_lower(&id1,&id2); - - pListHead = PolEdges[id1]; - temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count); - if (temp == NULL) - /* new edge that was created might not be here */ - return 0; - while (temp->edge[0] != id2) - { - count++; - temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count); - if (temp == NULL) - /* This edge was not there in the original, which - mean that we created it in the partial triangulation. - So it is adjacent to nothing. - */ - return 0; - } - /* Was not adjacent to anything else except itself */ - if (temp->edge[2] == -1) - return 0; - else - { - /* It was adjacent to another polygon, but maybe we did this - polygon already, and it was done partially so that this edge - could have been done - */ - if (curr_id != temp->edge[1]) - { - /* Did we use this polygon already?and it was deleted - completely from the structure - */ - pListHead = PolFaces[temp->edge[1]]; - temp2 = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); - if (Done(temp->edge[1],temp2->nPolSize,&size) == NULL) - return 0; - } - else - { - pListHead = PolFaces[temp->edge[2]]; - temp2 = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); - if (Done(temp->edge[2],temp2->nPolSize,&size)== NULL) - return 0; - } - - /* Now we have to check whether it was partially done, before - we can say definitely if it is adjacent. - Check each edge of the face and tally the number of adjacent - polygons to this face. - */ - if ( temp2 != NULL ) - { - /* Size of the polygon */ - size = temp2->nPolSize; - for (y = 0; y< size; y++) - { - /* If we are doing partial triangulation, we must check - to see whether the edge is still there in the polygon, - since we might have done a portion of the polygon - and saved the rest for later. - */ - if (y != (size-1)) - { - if( ((id1 == *(temp2->pPolygon+y)) && (id2 ==*(temp2->pPolygon+y+1))) - || ((id2 == *(temp2->pPolygon+y)) && (id1 ==*(temp2->pPolygon+y+1)))) - /* edge is still there we are ok */ - there = TRUE; - } - else - { - if( ((id1 == *(temp2->pPolygon)) && (id2 == *(temp2->pPolygon+size-1))) - || ((id2 == *(temp2->pPolygon)) && (id1 ==*(temp2->pPolygon+size-1)))) - /* edge is still there we are ok */ - there = TRUE; - } - } - } - - if (there ) - return 1; - return 0; - } -} - -int Min_Adj(int id) -{ - /* Used for the lookahead to break ties. It will - return the minimum adjacency found at this face. - */ - int y,numverts,t,x=60; - PF_FACES temp=NULL; - ListHead *pListHead; - - /* If polygon was used then we can't use this face */ - if (Done(id,59,&y) == NULL) - return 60; - - /* It was not used already */ - pListHead = PolFaces[id]; - temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); - if ( temp != NULL ) - { - numverts = temp->nPolSize; - for (y = 0; y< numverts; y++) - { - if (y != (numverts-1)) - t = Number_Adj(*(temp->pPolygon+y),*(temp->pPolygon+y+1),id); - else - t = Number_Adj(*(temp->pPolygon),*(temp->pPolygon+(numverts-1)),id); - if (t < x) - x = t; - } - } - if (x == -1) - { - printf("Error in the look\n"); - exit(0); - } - return x; -} - - - -void Edge_Least(int *index,int *new1,int *new2,int face_id,int size) -{ - /* We had a polygon without an input edge and now we re going to pick one - of the edges with the least number of adjacencies to be the input - edge - */ - register int x,value,smallest=60; - - for (x = 0; xpPolygon+y) == id2) && (*(temp->pPolygon+y+1) != id3)) - || ((*(temp->pPolygon+y) == id3) && (*(temp->pPolygon+y+1) != id2))) - { - saved[x++] = Number_Adj(*(temp->pPolygon+y),*(temp->pPolygon+y+1),face_id); - big_saved[z++] = saved[x-1]; - } - else - big_saved[z++] = Number_Adj(*(temp->pPolygon+y),*(temp->pPolygon+y+1),face_id); - } - else - { - if (((*(temp->pPolygon) == id2) && (*(temp->pPolygon+size-1) != id3)) - || ((*(temp->pPolygon) == id3) && (*(temp->pPolygon+size-1) != id2))) - { - saved[x++] = Number_Adj(*(temp->pPolygon),*(temp->pPolygon+size-1),face_id); - big_saved[z++] = saved[x-1]; - } - else - big_saved[z++] = Number_Adj(*(temp->pPolygon),*(temp->pPolygon+size-1),face_id); - } - } - /* There was an input edge */ - if (x == 2) - { - if (saved[0] < saved[1]) - /* Count the polygon that we will be cutting as another adjacency*/ - *min = saved[0] + 1; - else - *min = saved[1] + 1; - } - /* There was not an input edge */ - else - { - if (z != size) - { - printf("There is an error with the z %d %d\n",size,z); - exit(0); - } - *min = 60; - for (x = 0; x < size; x++) - { - if (*min > big_saved[x]) - *min = big_saved[x]; - } - } -} - - -void New_Face (int face_id, int v1, int v2, int v3) -{ - /* We want to change the face that was face_id, we will - change it to a triangle, since the rest of the polygon - was already outputtted - */ - ListHead *pListHead; - PF_FACES temp = NULL; - - pListHead = PolFaces[face_id]; - temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0); - /* Check each edge of the face and tally the number of adjacent - polygons to this face. - */ - if ( temp != NULL ) - { - /* Size of the polygon */ - if (temp->nPolSize != 4) - { - printf("There is a miscalculation in the partial\n"); - exit (0); - } - temp->nPolSize = 3; - *(temp->pPolygon) = v1; - *(temp->pPolygon+1) = v2; - *(temp->pPolygon+2) = v3; - } -} - -void New_Size_Face (int face_id) -{ - /* We want to change the face that was face_id, we will - change it to a triangle, since the rest of the polygon - was already outputtted - */ - ListHead *pListHead; - PF_FACES temp = NULL; - - pListHead = PolFaces[face_id]; - temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); - /* Check each edge of the face and tally the number of adjacent - polygons to this face. - */ - if ( temp != NULL ) - (temp->nPolSize)--; - else - printf("There is an error in updating the size\n"); -} - - - -void Check_In_Quad(int face_id,int *min) -{ - /* Check to see what the adjacencies are for the polygons that - are inside the quad, ie the 2 triangles that we can form. - */ - ListHead *pListHead; - int y,id1,id2,id3,x=0; - int saved[4]; - PF_FACES temp; - register int size = 4; - - pListHead = PolFaces[face_id]; - temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); - - /* Get the input edge that we came in on */ - Last_Edge(&id1,&id2,&id3,0); - - /* Now find the adjacencies for the inside triangles */ - for (y = 0; y< size; y++) - { - /* Will not do this if the edge is the input edge */ - if (y != (size-1)) - { - if ((((*(temp->pPolygon+y) == id2) && (*(temp->pPolygon+y+1) == id3))) || - (((*(temp->pPolygon+y) == id3) && (*(temp->pPolygon+y+1) == id2)))) - saved[x++] = -1; - else - { - if (x == 4) - { - printf("There is an error in the check in quad \n"); - exit(0); - } - /* Save the number of Adjacent Polygons to this edge */ - saved[x++] = Number_Adj(*(temp->pPolygon+y),*(temp->pPolygon+y+1),face_id); - } - } - else if ((((*(temp->pPolygon) == id2) && (*(temp->pPolygon+size-1) == id3))) || - (((*(temp->pPolygon) == id3) && (*(temp->pPolygon+size-1) == id2))) ) - saved[x++] = -1; - else - { - if (x == 4) - { - printf("There is an error in the check in quad \n"); - exit(0); - } - /* Save the number of Adjacent Polygons to this edge */ - saved[x++] = Number_Adj(*(temp->pPolygon),*(temp->pPolygon+size-1),face_id); - - } - } - if (x != 4) - { - printf("Did not enter all the values %d \n",x); - exit(0); - } - - *min = 10; - for (x=0; x<4; x++) - { - if (x!= 3) - { - if ((saved[x] != -1) && (saved[x+1] != -1) && - ((saved[x] + saved[x+1]) < *min)) - *min = saved[x] + saved[x+1]; - } - else - { - if ((saved[0] != -1) && (saved[x] != -1) && - ((saved[x] + saved[0]) < *min)) - *min = saved[0] + saved[x]; - } - } -} - - - -int Get_Output_Edge(int face_id, int size, int *index,int id2,int id3) -{ - /* Return the vertex adjacent to either input1 or input2 that - is adjacent to the least number of polygons on the edge that - is shared with either input1 or input2. - */ - register int x=0,y; - int saved[2]; - int edges[2][1]; - - for (y = 0; y < size; y++) - { - if (y != (size-1)) - { - if (((*(index+y) == id2) && (*(index+y+1) != id3)) - || ((*(index+y) == id3) && (*(index+y+1) != id2))) - { - saved[x++] = Number_Adj(*(index+y),*(index+y+1),face_id); - edges[x-1][0] = *(index+y+1); - } - else if (y != 0) - { - if (( (*(index+y) == id2) && (*(index+y-1) != id3) ) || - ( (*(index+y) == id3) && (*(index+y-1) != id2)) ) - { - saved[x++] = Number_Adj(*(index+y),*(index+y-1),face_id); - edges[x-1][0] = *(index+y-1); - } - } - else if (y == 0) - { - if (( (*(index) == id2) && (*(index+size-1) != id3) ) || - ( (*(index) == id3) && (*(index+size-1) != id2)) ) - { - saved[x++] = Number_Adj(*(index),*(index+size-1),face_id); - edges[x-1][0] = *(index+size-1); - } - } - - } - else - { - if (((*(index+size-1) == id2) && (*(index) != id3)) - || ((*(index+size-1) == id3) && (*(index) != id2))) - { - saved[x++] = Number_Adj(*(index),*(index+size-1),face_id); - edges[x-1][0] = *(index); - } - - if (( (*(index+size-1) == id2) && (*(index+y-1) != id3) ) || - ( (*(index+size-1) == id3) && (*(index+y-1) != id2)) ) - { - saved[x++] = Number_Adj(*(index+size-1),*(index+y-1),face_id); - edges[x-1][0] = *(index+y-1); - } - } - } - if ((x != 2)) - { - printf("There is an error in getting the input edge %d \n",x); - exit(0); - } - if (saved[0] < saved[1]) - return edges[0][0]; - else - return edges[1][0]; - -} - -void Get_Input_Edge(int *index,int id1,int id2,int id3,int *new1,int *new2,int size, - int face_id) -{ - /* We had a polygon without an input edge and now we are going to pick one - as the input edge. The last triangle was id1,id2,id3, we will try to - get an edge to have something in common with one of those vertices, otherwise - we will pick the edge with the least number of adjacencies. - */ - - register int x; - int saved[3]; - - saved[0] = -1; - saved[1] = -1; - saved[2] = -1; - - /* Go through the edges to see if there is one in common with one - of the vertices of the last triangle that we had, preferably id2 or - id3 since those are the last 2 things in the stack of size 2. - */ - for (x=0; x< size; x++) - { - if (*(index+x) == id1) - { - if (x != (size-1)) - saved[0] = *(index+x+1); - else - saved[0] = *(index); - } - - if (*(index+x) == id2) - { - if (x != (size-1)) - saved[1] = *(index+x+1); - else - saved[1] = *(index); - } - - if (*(index+x) == id3) - { - if (x != (size -1)) - saved[2] = *(index+x+1); - else - saved[2] = *(index); - } - } - /* Now see what we saved */ - if (saved[2] != -1) - { - *new1 = id3; - *new2 = saved[2]; - return; - } - else if (saved[1] != -1) - { - *new1 = id2; - *new2 = saved[1]; - return; - } - else if (saved[0] != -1) - { - *new1 = id1; - *new2 = saved[0]; - return; - } - /* We did not find anything so get the edge with the least number of adjacencies */ - Edge_Least(index,new1,new2,face_id,size); - -} - -int Find_Face(int current_face, int id1, int id2, int *bucket) -{ - /* Find the face that is adjacent to the edge and is not the - current face. - */ - register int size,each_poly=0,y,tally=0,count=0; - PF_EDGES temp = NULL; - PF_FACES temp2 = NULL; - ListHead *pListHead; - int next_face; - BOOL there = FALSE; - - - /* Always want smaller id first */ - switch_lower(&id1,&id2); - - pListHead = PolEdges[id1]; - temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count); - /* The input edge was a new edge */ - if (temp == NULL) - return -1; - - while (temp->edge[0] != id2) - { - count++; - temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count); - /* The input edge was a new edge */ - if (temp == NULL) - return -1; - } - /* Was not adjacent to anything else except itself */ - if (temp->edge[2] == -1) - return -1; - else - { - if (temp->edge[2] == current_face) - next_face = temp->edge[1]; - else - next_face = temp->edge[2]; - } - /* We have the other face adjacent to this edge, it is - next_face. - */ - pListHead = PolFaces[next_face]; - temp2 = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); - - /* See if the face was already deleted, and where - it is if it was not - */ - - if (Done(next_face,59,bucket) == NULL) - return -1; - - /* Make sure the edge is still in this polygon, and that it is not - done - */ - /* Size of the polygon */ - size = temp2->nPolSize; - for (y = 0; y< size; y++) - { - /* Make sure that the edge is still in the - polygon and was not deleted, because if the edge was - deleted, then we used it already. - */ - if (y != (size-1)) - { - if( ((id1 == *(temp2->pPolygon+y)) && (id2 ==*(temp2->pPolygon+y+1))) - || ((id2 == *(temp2->pPolygon+y)) && (id1 ==*(temp2->pPolygon+y+1)))) - /* edge is still there we are ok */ - there = TRUE; - } - else - { - if( ((id1 == *(temp2->pPolygon)) && (id2 ==*(temp2->pPolygon+size-1))) - || ((id2 == *(temp2->pPolygon)) && (id1 ==*(temp2->pPolygon+size-1)))) - /* edge is still there we are ok */ - there = TRUE; - } - } - - if (!there) - /* Edge already used and deleted from the polygon*/ - return -1; - else - return next_face; -} - -BOOL Look_Up(int id1,int id2,int face_id) -{ - /* See if the endpoints of the edge specified by id1 and id2 - are adjacent to the face with face_id - */ - register int count = 0; - PF_EDGES temp = NULL; - ListHead *pListHead; - PF_FACES temp2 = NULL; - - /* Always want smaller id first */ - switch_lower(&id1,&id2); - - pListHead = PolEdges[id1]; - temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count); - if (temp == NULL) - /* Was a new edge that we created */ - return 0; - - while (temp->edge[0] != id2) - { - count++; - temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count); - if (temp == NULL) - /* Was a new edge that we created */ - return 0; - } - /* Was not adjacent to anything else except itself */ - if ((temp->edge[2] == face_id) || (temp->edge[1] == face_id)) - { - /* Edge was adjacent to face, make sure that edge is - still there - */ - if (Exist(face_id,id1,id2)) - return 1; - else - return 0; - } - else - return 0; -} - - -void Add_Id_Strips(int id, int where) -{ - /* Just save the triangle for later */ - P_STRIPS pfNode; - - pfNode = (P_STRIPS) malloc(sizeof(Strips) ); - if ( pfNode ) - { - pfNode->face_id = id; - if (where == 1) - AddTail(strips[0],(PLISTINFO) pfNode); - /* We are backtracking in the strip */ - else - AddHead(strips[0],(PLISTINFO) pfNode); - } - else - { - printf("There is not enough memory to allocate for the strips\n"); - exit(0); - } -} - - -int Num_Adj(int id1, int id2) -{ - /* Given edge whose endpoints are specified by id1 and id2, - determine how many polygons share this edge and return that - number minus one (since we do not want to include the polygon - that the caller has already). - */ - - PF_EDGES temp = NULL; - ListHead *pListHead; - register count=-1; - - /* Always want smaller id first */ - switch_lower(&id1,&id2); - - pListHead = PolEdges[id1]; - temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count); - if (temp == NULL) - { - printf("There is an error in the creation of the table \n"); - exit(0); - } - while (temp->edge[0] != id2) - { - count++; - temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count); - if (temp == NULL) - { - printf("There is an error in the creation of the table\n"); - exit(0); - } - } - /* Was not adjacent to anything else except itself */ - if (temp->edge[2] == -1) - return 0; - return 1; -} - - -void Add_Sgi_Adj(int bucket,int face_id) -{ - /* This routine will add the face to the proper bucket, - depending on how many faces are adjacent to it (what the - value bucket should be). - */ - P_ADJACENCIES pfNode; - - pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) ); - if ( pfNode ) - { - pfNode->face_id = face_id; - AddHead(array[bucket],(PLISTINFO) pfNode); - } - else - { - printf("Out of memory for the SGI adj list!\n"); - exit(0); - } -} - -void Find_Adjacencies(int num_faces) -{ - register int x,y; - register int numverts; - PF_FACES temp=NULL; - ListHead *pListHead; - - /* Fill in the adjacencies data structure for all the faces */ - for (x=0;xnPolSize; - if (numverts != 1) - { - for (y = 0; y< numverts; y++) - { - if (y != (numverts-1)) - Add_AdjEdge(*(temp->pPolygon+y),*(temp->pPolygon+y+1),x,y); - - else - Add_AdjEdge(*(temp->pPolygon),*(temp->pPolygon+(numverts-1)),x,numverts-1); - - } - } - temp = NULL; - } - } -} - - diff --git a/Tools/Stripe_u/common.h b/Tools/Stripe_u/common.h deleted file mode 100644 index a220b3628..000000000 --- a/Tools/Stripe_u/common.h +++ /dev/null @@ -1,41 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: common.h ------------------------------------------------------------------------*/ - -void Add_AdjEdge(); -void Find_Adjacencies(); -void Add_Sgi_Adj(); -int Num_Adj(); -void Add_Id_Strips(); -BOOL Look_Up(); -int Number_Adj(); -int Old_Adj(); -int Min_Adj(); -int Find_Face(); -void Edge_Least(); -void Get_Input_Edge(); -int Get_Output_Edge(); -void Check_In_Polygon(); -void Check_In_Quad(); -void New_Size_Face (); -void New_Face (); - - - - - - - - - - - - diff --git a/Tools/Stripe_u/define.h b/Tools/Stripe_u/define.h deleted file mode 100644 index 931e5713f..000000000 --- a/Tools/Stripe_u/define.h +++ /dev/null @@ -1,13 +0,0 @@ - -#define VRDATA double -#define MAX1 60 - -#define TRUE 1 -#define FALSE 0 - -#define PI 3.1415926573 - -struct vert_struct { - VRDATA x, y, z; /* point coordinates */ -}; - diff --git a/Tools/Stripe_u/extend.h b/Tools/Stripe_u/extend.h deleted file mode 100644 index 78c135e3a..000000000 --- a/Tools/Stripe_u/extend.h +++ /dev/null @@ -1,17 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: extend.h ------------------------------------------------------------------------*/ - -int Bottom_Left(); -int Top_Left(); -void Start_Edge(); - - diff --git a/Tools/Stripe_u/free.c b/Tools/Stripe_u/free.c deleted file mode 100644 index 9494f4fb4..000000000 --- a/Tools/Stripe_u/free.c +++ /dev/null @@ -1,110 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: free.c - This file contains the code used to free the data structures. -*/ -/*---------------------------------------------------------------------*/ - -#include -#include -#include "polverts.h" - -void ParseAndFreeList( ListHead *pListHead ) -{ - PLISTINFO value; - register int c,num; - - /* Freeing a linked list */ - num = NumOnList(pListHead); - for (c = 0; c< num; c++) - value = RemHead(pListHead); -} - -void FreePolygonNode( PF_VERTS pfVerts) -{ - /* Free a vertex node */ - if ( pfVerts->pPolygon ) - free( pfVerts->pPolygon ); - free( pfVerts ); - -} - -void Free_Strips() -{ - P_STRIPS temp = NULL; - - /* Free strips data structure */ - if (strips[0] == NULL) - return; - else - ParseAndFreeList(strips[0]); -} - -void FreeFaceNode( PF_FACES pfFaces) -{ - /* Free face node */ - if ( pfFaces->pPolygon ) - free( pfFaces->pPolygon ); - free( pfFaces ); -} - - -void FreeFaceTable(int nSize) -{ - register int nIndex; - - for ( nIndex=0; nIndex < nSize; nIndex++ ) - { - if ( PolFaces[nIndex] != NULL ) - ParseAndFreeList( PolFaces[nIndex] ); - } - free( PolFaces ); -} - -void FreeEdgeTable(int nSize) -{ - register int nIndex; - - for ( nIndex=0; nIndex < nSize; nIndex++ ) - { - if ( PolEdges[nIndex] != NULL ) - ParseAndFreeList( PolEdges[nIndex] ); - } - free( PolEdges ); -} - - -void Free_All_Strips() -{ - - ListHead *pListHead; - register int y; - - for (y =0; ; y++) - { - pListHead = all_strips[y]; - if (pListHead == NULL) - return; - else - ParseAndFreeList(all_strips[y]); - } -} - -void End_Face_Struct(int numfaces) -{ - FreeFaceTable(numfaces); -} - -void End_Edge_Struct(int numverts) -{ - FreeEdgeTable(numverts); -} - - diff --git a/Tools/Stripe_u/free.h b/Tools/Stripe_u/free.h deleted file mode 100644 index 3303d05e1..000000000 --- a/Tools/Stripe_u/free.h +++ /dev/null @@ -1,22 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: free.h ------------------------------------------------------------------------*/ - -void Free_All_Strips(); -void ParseAndFreeList(); -void FreePolygonNode(); -void Free_Strips(); -void FreeFaceTable(); -void FreeEdgeTable(); -void End_Face_Struct(); -void End_Edge_Struct(); - - diff --git a/Tools/Stripe_u/global.h b/Tools/Stripe_u/global.h deleted file mode 100644 index 3621b25e1..000000000 --- a/Tools/Stripe_u/global.h +++ /dev/null @@ -1,37 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: global.h ------------------------------------------------------------------------*/ - -#define VRDATA double -#define MAX1 60 - -#define TRUE 1 -#define FALSE 0 - -#ifndef PI -# define PI 3.1415926573 -#endif /* PI */ -#define ATOI(C) (C -'0') -#define X 0 -#define Y 1 -#define Z 2 -#define EVEN(x) (((x) & 1) == 0) -#define MAX_BAND 10000 - -struct vert_struct { - VRDATA x, y, z; /* point coordinates */ -}; - -int ids[MAX1]; -int norms[MAX1]; -int *vert_norms; -int *vert_texture; - diff --git a/Tools/Stripe_u/glove.h b/Tools/Stripe_u/glove.h deleted file mode 100644 index 74bcd07da..000000000 --- a/Tools/Stripe_u/glove.h +++ /dev/null @@ -1,151 +0,0 @@ -/* - * dg2lib.h - header file for the DG2 library libdg2.a - * - * copyright 1988-92 VPL Research Inc. - * - */ - - - -/******** error returns from the library */ - -extern int DG2_error; /* for error information */ -extern float DG2_lib_version; /* for the library version */ -extern int DG2_box_version; /* for the firmware version */ -extern int DG2_glove_sensors; /* for the number of sensors in the glove */ - -/* defines for DG2_error values */ - -#define DG2_AOK 0 -#define DG2_SETTINGS_FILE -1 -#define DG2_SERIAL_OPEN -2 -#define DG2_SERIAL_PORT -4 -#define DG2_RESET -6 -#define DG2_PARAMETER -7 -#define DG2_FILE_IO -8 -#define DG2_CALIBRATION_FILE -9 -#define DG2_GESTURE_FILE -10 -#define DG2_CAL_GEST_FILES -11 -/* defines for DG2_response() */ - -#define DATAGLOVE 1 -#define POLHEMUS 2 -#define GESTURE 8 - -#define DG2_60Hz 1 -#define DG2_30Hz 2 -#define DG2_oneShot 3 - -/* defines for DG2_DataGlove_select() */ - -#define THUMB_INNER 0x1 -#define THUMB_OUTER 0x2 -#define INDEX_INNER 0x4 -#define INDEX_OUTER 0x8 -#define MIDDLE_INNER 0x10 -#define MIDDLE_OUTER 0x20 -#define RING_INNER 0x40 -#define RING_OUTER 0x80 -#define LITTLE_INNER 0x100 -#define LITTLE_OUTER 0x200 -#define NORMAL_JOINTS 0x3ff -#define FLEX11 0x400 -#define FLEX12 0x800 -#define FLEX13 0x1000 -#define FLEX14 0x2000 -#define FLEX15 0x4000 -#define FLEX16 0x8000 - - -/* defines for DG2_DataGlove_trans_select() */ - -#define DG2_TRANSLATED 5 -#define DG2_RAW 6 - -/* defines for DG2_Polhemus_units() */ - -#define POL_RAW 0 -#define POL_INCHES 1 -#define POL_CM 2 - -/* defines for DG2_user_IRQ() */ - -#define IRQ_ON 1 -#define IRQ_OFF 2 - - -/* defines for DG2_get_data() */ - -#define DG2_report 1 -#define DG2_userport 2 - - -/* dg2 command codes*/ -#define LEADINGBYTE 0x24 -#define RPT60 0x41 /* repeat 60 */ -#define RPT30 0x42 /* repeat 30 */ -#define ONESHOT 0x43 /* one shot */ -#define SYSID 0x44 /* system ID */ -#define EPTBUF 0x45 /* empty buffer */ -#define USRRD 0x46 /* user read */ -#define USRIRQ 0x47 /* user IRQ */ -#define QBRT 0x48 /* query bright */ -#define CDRST 0x49 /* cold reset */ -#define WMRST 0x4A /* warm reset */ -#define MEMALLO 0x4B /* memory alloc */ -#define DLTSND 0x4C /* delta send */ -#define SETBRT 0x4D /* set bright */ -#define SETDIM 0x4E /* set dim */ -#define FILBUF 0x4F /* fill buffer */ -#define LDTBL 0x50 /* load table */ -#define LDPOL 0x51 /* send up to 63 bytes to Polhemus */ -#define ANGLE 0x52 /* angles */ -#define NSNSR 0x53 /* num sensors */ -#define SETFB 0x54 /* set feedback */ -#define QCUT 0X55 /* query cutoff*/ -#define SETCUT 0X56 /* set cutoff */ -#define FLXVAL 0X57 /* raw flex values */ -#define USRWR 0X58 /* user write */ -#define JNTMAP 0X59 /* joint map */ -#define ERRMESS 0XFF /* error in command input */ -#define TIMOUT 0XFE /* timed out during command */ - -/* response structure */ - -typedef struct DG2_data { - char gesture; - double location[3]; /* X,Y,Z */ - double orientation[3]; /* yaw, pitch, roll */ - short flex[16]; - char gesture_name[20]; - short reserved[16]; - /* user port data: */ - char user_nibble; - char user_analog[3]; -} DG2_data; - - -/**************function prototypes*************/ -/*NOTE: all DG2_ functions return -1 on error*/ - -extern int DG2_open(char *portname, int baud); -extern int DG2_close(int filedes); -extern int DG2_direct(int filedes,char *message,int count); -extern int DG2_response(int filedes,int devices,int rate); -extern int DG2_DataGlove_select(int filedes,int flex_sensors); -extern int DG2_DataGlove_translation(int filedes,int flex_sensors,char table[16][256]); -extern int DG2_DataGlove_trans_select(int filedes,int status); -extern int DG2_DataGlove_LED_set(int filedes,int LED); -extern int DG2_DataGlove_LED_read(int filedes); -extern int DG2_Polhemus_units(int filedes,char type); -extern int DG2_Polhemus_direct(int filedes,char *message,int count); -extern int DG2_user_write(int filedes,int nibble); -extern int DG2_user_IRQ(int filedes,int mode); -extern int DG2_user_read(int filedes,DG2_data *data); -extern int DG2_get_data(int filedes,DG2_data *data); -extern int DG2_gesture_load(int filedes,char *calib,char *gest); - -/*use this with caution since it does not return until it gets a correct - *response from the DG2 -*/ -extern int DG2U_get_reply(int filedes,char *buff,int response,int size); diff --git a/Tools/Stripe_u/init.c b/Tools/Stripe_u/init.c deleted file mode 100644 index b3b218cec..000000000 --- a/Tools/Stripe_u/init.c +++ /dev/null @@ -1,217 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: init.c - This file contains the initialization of data structures. -*/ -/*---------------------------------------------------------------------*/ - -#include -#include -#include "global.h" -#include "polverts.h" - -void init_vert_norms(int num_vert) -{ - /* Initialize vertex/normal array to have all zeros to - start with. - */ - register int x; - - for (x = 0; x < num_vert; x++) - *(vert_norms + x) = 0; -} - -void init_vert_texture(int num_vert) -{ - /* Initialize vertex/normal array to have all zeros to - start with. - */ - register int x; - - for (x = 0; x < num_vert; x++) - *(vert_texture + x) = 0; -} - -BOOL InitVertTable( int nSize ) -{ - register int nIndex; - - /* Initialize the vertex table */ - PolVerts = (ListHead**) malloc(sizeof(ListHead*) * nSize ); - if ( PolVerts ) - { - for ( nIndex=0; nIndex < nSize; nIndex++ ) - { - PolVerts[nIndex] = NULL; - } - return( TRUE ); - } - return( FALSE ); -} - -BOOL InitFaceTable( int nSize ) -{ - register int nIndex; - - /* Initialize the face table */ - PolFaces = (ListHead**) malloc(sizeof(ListHead*) * nSize ); - if ( PolFaces ) - { - for ( nIndex=0; nIndex < nSize; nIndex++ ) - { - PolFaces[nIndex] = NULL; - } - return( TRUE ); - } - return( FALSE ); -} - -BOOL InitEdgeTable( int nSize ) -{ - register int nIndex; - - /* Initialize the edge table */ - PolEdges = (ListHead**) malloc(sizeof(ListHead*) * nSize ); - if ( PolEdges ) - { - for ( nIndex=0; nIndex < nSize; nIndex++ ) - { - PolEdges[nIndex] = NULL; - } - return( TRUE ); - } - return( FALSE ); -} - - -void InitStripTable( ) -{ - - PLISTHEAD pListHead; - - /* Initialize the strip table */ - pListHead = ( PLISTHEAD ) malloc(sizeof(ListHead)); - if ( pListHead ) - { - InitList( pListHead ); - strips[0] = pListHead; - } - else - { - printf("Out of memory !\n"); - exit(0); - } - -} - -void Init_Table_SGI() -{ - PLISTHEAD pListHead; - int max_adj = 60; - register int x; - - /* This routine will initialize the table that will - have the faces sorted by the number of adjacent polygons - to it. - */ - - for (x=0; x< max_adj; x++) - { - /* We are allowing the max number of sides of a polygon - to be max_adj. - */ - pListHead = ( PLISTHEAD ) malloc(sizeof(ListHead)); - if ( pListHead ) - { - InitList( pListHead ); - array[x] = pListHead; - } - else - { - printf("Out of memory !\n"); - exit(0); - } - } -} - -void BuildVertTable( int nSize ) -{ - register int nIndex; - PLISTHEAD pListHead; - - for ( nIndex=0; nIndex < nSize; nIndex++ ) - { - pListHead = ( PLISTHEAD ) malloc(sizeof(ListHead)); - if ( pListHead ) - { - InitList( pListHead ); - PolVerts[nIndex] = pListHead; - } - else - return; - - } -} - - -void BuildFaceTable( int nSize ) -{ - register int nIndex; - PLISTHEAD pListHead; - - for ( nIndex=0; nIndex < nSize; nIndex++ ) - { - pListHead = ( PLISTHEAD ) malloc(sizeof(ListHead)); - if ( pListHead ) - { - InitList( pListHead ); - PolFaces[nIndex] = pListHead; - } - else - return; - - } -} - -void BuildEdgeTable( int nSize ) -{ - register int nIndex; - PLISTHEAD pListHead; - - for ( nIndex=0; nIndex < nSize; nIndex++ ) - { - pListHead = ( PLISTHEAD ) malloc(sizeof(ListHead)); - if ( pListHead ) - { - InitList( pListHead ); - PolEdges[nIndex] = pListHead; - } - else - return; - } -} - -void Start_Face_Struct(int numfaces) -{ - if (InitFaceTable(numfaces)) - { - BuildFaceTable(numfaces); - } -} - -void Start_Edge_Struct(int numverts) -{ - if (InitEdgeTable(numverts)) - { - BuildEdgeTable(numverts); - } -} - - diff --git a/Tools/Stripe_u/init.h b/Tools/Stripe_u/init.h deleted file mode 100644 index 2faf0e838..000000000 --- a/Tools/Stripe_u/init.h +++ /dev/null @@ -1,30 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: init.h ------------------------------------------------------------------------*/ - -void init_vert_norms(); -void init_vert_texture(); -BOOL InitVertTable(); -BOOL InitFaceTable(); -BOOL InitEdgeTable(); -void InitStripTable(); -void Init_Table_SGI(); -void BuildVertTable(); -void BuildFaceTable(); -void BuildEdgeTable(); -void Start_Face_Struct(); -void Start_Edge_Struct(); - - - - - - diff --git a/Tools/Stripe_u/local.c b/Tools/Stripe_u/local.c deleted file mode 100644 index 2db94904e..000000000 --- a/Tools/Stripe_u/local.c +++ /dev/null @@ -1,123 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: local.c - This file contains the code that initializes the data structures for - the local algorithm, and starts the local algorithm going. -*/ -/*---------------------------------------------------------------------*/ - -#include -#include -#include "polverts.h" -#include "local.h" -#include "triangulatex.h" -#include "sturctsex.h" -#include "common.h" -#include "outputex.h" -#include "util.h" -#include "init.h" - -void Find_StripsEx(FILE *output,FILE *strip,int *ties, - int tie, int triangulate, - int swaps,int *next_id) -{ - /* This routine will peel off the strips from the model */ - - ListHead *pListHead; - P_ADJACENCIES temp = NULL; - register int max,bucket=0; - BOOL whole_flag = TRUE; - int dummy = 0; - - /* Set the last known input edge to be null */ - Last_Edge(&dummy,&dummy,&dummy,1); - - /* Search for lowest adjacency polygon and output strips */ - while (whole_flag) - { - bucket = -1; - /* Search for polygons in increasing number of adjacencies */ - while (bucket < 59) - { - bucket++; - pListHead = array[bucket]; - max = NumOnList(pListHead); - if (max > 0) - { - temp = (P_ADJACENCIES) PeekList(pListHead,LISTHEAD,0); - if (temp == NULL) - { - printf("Error in the buckets%d %d %d\n",bucket,max,0); - exit(0); - } - Polygon_OutputEx(temp,temp->face_id,bucket,pListHead, - output,strip,ties,tie,triangulate,swaps,next_id,1); - /* Try to extend backwards, if the starting polygon in the - strip had 2 or more adjacencies to begin with - */ - if (bucket >= 2) - Extend_BackwardsEx(temp->face_id,output,strip,ties,tie,triangulate, - swaps,next_id); - break; - } - } - /* Went through the whole structure, it is empty and we are done. - */ - if ((bucket == 59) && (max == 0)) - whole_flag = FALSE; - - /* We just finished a strip, send dummy data to signal the end - of the strip so that we can output it. - */ - else - { - Output_TriEx(-1,-2,-3,output,-1,-10,1); - Last_Edge(&dummy,&dummy,&dummy,1); - } - } -} - - - -void SGI_Strip(int num_verts,int num_faces,FILE *output, - int ties,int triangulate) - -{ - FILE *strip; - int next_id = -1,t=0; - - strip = fopen("output.d","w"); - /* We are going to output and find triangle strips - according the the method that SGI uses, ie always - choosing as the next triangle in our strip the triangle - that has the least number of adjacencies. We do not have - all triangles and will be triangulating on the fly those - polygons that have more than 3 sides. - */ - - /* Build a table that has all the polygons sorted by the number - of polygons adjacent to it. - */ - /* Initialize it */ - Init_Table_SGI(); - /* Build it */ - Build_SGI_Table(num_verts,num_faces); - - /* We will have a structure to hold all the strips, until - outputted. - */ - InitStripTable(); - /* Now we have the structure built to find the polygons according - to the number of adjacencies. Now use the SGI Method to find - strips according to the adjacencies - */ - Find_StripsEx(output,strip,&t,ties,triangulate,ON,&next_id); - -} diff --git a/Tools/Stripe_u/local.h b/Tools/Stripe_u/local.h deleted file mode 100644 index 34769ebb8..000000000 --- a/Tools/Stripe_u/local.h +++ /dev/null @@ -1,19 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE:local.h ------------------------------------------------------------------------*/ - -void Local_Polygon_Output(); -void Local_Output_Tri(); -int Different(); -void Local_Non_Blind_Triangulate(); -void Local_Blind_Triangulate(); -void Local_Triangulate_Polygon(); -void SGI_Strip(); diff --git a/Tools/Stripe_u/my_global.h b/Tools/Stripe_u/my_global.h deleted file mode 100644 index 629c12074..000000000 --- a/Tools/Stripe_u/my_global.h +++ /dev/null @@ -1,3 +0,0 @@ -int change_in_stripEx = 0; -int change_in_strip = 0; - diff --git a/Tools/Stripe_u/newpolve.c b/Tools/Stripe_u/newpolve.c deleted file mode 100644 index 9adbfd651..000000000 --- a/Tools/Stripe_u/newpolve.c +++ /dev/null @@ -1,1667 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: newpolve.c - This routine contains the bulk of the code that will find the - patches of quads in the data model -*/ -/*---------------------------------------------------------------------*/ - -#include -#include "polverts.h" -#include "extend.h" -#include "output.h" -#include "triangulate.h" -#include "common.h" -#include "util.h" -#include "global.h" -#include "init.h" -#include "add.h" - -ListHead **PolVerts; -ListHead **PolFaces; -ListHead **PolEdges; -int length; -BOOL resetting = FALSE; -int ids[MAX1]; -int added_quad = 0; -BOOL reversed = FALSE; -int patch = 0; -int *vn; -int *vt; - -int Calculate_Walks(int lastvert,int y, PF_FACES temp2) -{ - /* Find the length of the walk */ - - int previous_edge1, previous_edge2; - register int nextvert,numverts,counter,walk=0; - BOOL flag; - F_EDGES *node; - ListHead *pListHead; - static int seen = 0; - - /* Find the edge that we are currently on */ - if (y != 3) - { - previous_edge1 = *(temp2->pPolygon +y); - previous_edge2 = *(temp2->pPolygon + y + 1); - } - else - { - previous_edge1 = *(temp2->pPolygon +y); - previous_edge2 = *(temp2->pPolygon); - } - - temp2->seen = seen; - counter = y; - - /*Find the adjacent face to this edge */ - node = *(temp2->VertandId+y); - if (node->edge[2] != lastvert) - nextvert = node->edge[2]; - else - nextvert = node->edge[1]; - - /* Keep walking in this direction until we cannot do so */ - while ((nextvert != lastvert) && (nextvert != -1)) - { - walk++; - pListHead = PolFaces[nextvert]; - temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0); - numverts = temp2->nPolSize; - if ((numverts != 4) || (temp2->seen == seen)) - { - walk--; - nextvert = -1; - } - else - { - temp2->seen = seen; - /* Find edge that is not adjacent to the previous one */ - counter = 0; - flag = TRUE; - while ((counter < 3) && (flag)) - { - if ( ((*(temp2->pPolygon+counter) == previous_edge1) || - (*(temp2->pPolygon+counter+1) == previous_edge2)) || - ((*(temp2->pPolygon+counter) == previous_edge2) || - (*(temp2->pPolygon+counter+1) == previous_edge1)) ) - counter++; - else - flag = FALSE; - } - /* Get the IDs of the next edge */ - if (counter < 3) - { - previous_edge1 = *(temp2->pPolygon + counter); - previous_edge2 = *(temp2->pPolygon + counter + 1); - } - else - { - previous_edge1 = *(temp2->pPolygon + counter); - previous_edge2 = *(temp2->pPolygon); - } - - node = *(temp2->VertandId + counter); - if (node->edge[1] == nextvert) - nextvert = node->edge[2]; - else - nextvert = node->edge[1]; - } - } - seen++; - return walk; -} - - -BOOL Check_Right(int last_seen,PF_FACES temp2,int y,int face_id) -{ - /* Check when we last saw the face to the right of the current - one. We want to have seen it just before we started this strip - */ - - F_EDGES *node; - ListHead *pListHead; - register int nextvert,oldy; - PF_FACES t; - - oldy = y; - if (y != 3) - y = y+1; - else - y = 0; - node = *(temp2->VertandId + y); - if (face_id == node->edge[1]) - nextvert = node->edge[2]; - else - nextvert = node->edge[1]; - - if (nextvert == -1) - return FALSE; - - pListHead = PolFaces[nextvert]; - t = (PF_FACES) PeekList(pListHead,LISTHEAD,0); - if (t->seen != (last_seen - 1)) - { - /* maybe because of the numbering, we are not - on the right orientation, so we have to check the - opposite one to be sure - */ - if (oldy != 0) - y = oldy-1; - else - y = 3; - node = *(temp2->VertandId + y); - if (face_id == node->edge[1]) - nextvert = node->edge[2]; - else - nextvert = node->edge[1]; - if (nextvert == -1) - return FALSE; - pListHead = PolFaces[nextvert]; - t = (PF_FACES) PeekList(pListHead,LISTHEAD,0); - if (t->seen != (last_seen - 1)) - return FALSE; - } - return TRUE; -} - - -int Update_and_Test(PF_FACES temp2,int y,BOOL first,int distance,int lastvert, int val) -{ - - static int last_seen = 17; - int previous_edge1, previous_edge2; - register int original_distance,nextvert,numverts,counter; - BOOL flag; - F_EDGES *node; - ListHead *pListHead; - - original_distance = distance; - /* Find the edge that we are currently on */ - if (y != 3) - { - previous_edge1 = *(temp2->pPolygon +y); - previous_edge2 = *(temp2->pPolygon + y + 1); - } - else - { - previous_edge1 = *(temp2->pPolygon +y); - previous_edge2 = *(temp2->pPolygon); - } - - temp2->seen = val; - temp2->seen2 = val; - - node = *(temp2->VertandId+y); - if (lastvert != node->edge[2]) - nextvert = node->edge[2]; - else - nextvert = node->edge[1]; - - /* Keep walking in this direction until we cannot do so or - we go to distance */ - while ((distance > 0) && (nextvert != lastvert) && (nextvert != -1)) - { - distance--; - - pListHead = PolFaces[nextvert]; - temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0); - temp2->seen = val; - - if (temp2->seen2 == val) - { - last_seen++; - return (original_distance - distance); - } - - temp2->seen2 = val; - - numverts = temp2->nPolSize; - - if (numverts != 4) - nextvert = -1; - - else if ((!first) && (!(Check_Right(last_seen,temp2,y,nextvert)))) - { - last_seen++; - return (original_distance - distance); - } - else - { - /* Find edge that is not adjacent to the previous one */ - counter = 0; - flag = TRUE; - while ((counter < 3) && (flag)) - { - if ( ((*(temp2->pPolygon+counter) == previous_edge1) || - (*(temp2->pPolygon+counter+1) == previous_edge2)) || - ((*(temp2->pPolygon+counter) == previous_edge2) || - (*(temp2->pPolygon+counter+1) == previous_edge1)) ) - counter++; - else - flag = FALSE; - } - /* Get the IDs of the next edge */ - if (counter < 3) - { - previous_edge1 = *(temp2->pPolygon + counter); - previous_edge2 = *(temp2->pPolygon + counter + 1); - } - else - { - previous_edge1 = *(temp2->pPolygon + counter); - previous_edge2 = *(temp2->pPolygon); - } - if ( ((*(temp2->walked+counter) == -1) && - (*(temp2->walked+counter+2) == -1))) - { - printf("There is an error in the walks!\n"); - printf("1Code %d %d \n",*(temp2->walked+counter),*(temp2->walked+counter+2)); - exit(0); - } - else - { - if ((*(temp2->walked+counter) == -1) && - (*(temp2->walked+counter-2) == -1)) - { - printf("There is an error in the walks!\n"); - printf("2Code %d %d \n",*(temp2->walked+counter),*(temp2->walked+counter-2)); - exit(0); - } - } - node = *(temp2->VertandId + counter); - y = counter; - if (node->edge[1] == nextvert) - nextvert = node->edge[2]; - else - nextvert = node->edge[1]; - } - } - - last_seen++; - - if (distance != 0) - { - if (((nextvert == -1) || (nextvert == lastvert)) && (distance != 1)) - return (original_distance - distance); - } - return original_distance; -} - - -int Test_Adj(PF_FACES temp2,int x,int north,int distance,int lastvert, int value) -{ - /* if first time, then just update the last seen field */ - if (x==1) - return(Update_and_Test(temp2,north,TRUE,distance,lastvert,value)); - /* else we have to check if we are adjacent to the last strip */ - else - return(Update_and_Test(temp2,north,FALSE,distance,lastvert,value)); -} - -void Get_Band_Walk(PF_FACES temp2,int face_id,int *dir1,int *dir2, - int orientation,int cutoff_length) -{ - int previous_edge1, previous_edge2; - F_EDGES *node; - ListHead *pListHead; - register int walk = 0, nextvert,numverts,counter; - BOOL flag; - - /* Get the largest band that will include this face, starting - from orientation. Save the values of the largest band - (either north and south together, or east and west together) - in the direction variables. - */ - /* Find the edge that we are currently on */ - if (orientation != 3) - { - previous_edge1 = *(temp2->pPolygon + orientation); - previous_edge2 = *(temp2->pPolygon + orientation + 1); - } - else - { - previous_edge1 = *(temp2->pPolygon + orientation ); - previous_edge2 = *(temp2->pPolygon); - } - - if (orientation == 0) - { - if (*dir1 > *(temp2->walked + 1)) - *dir1 = *(temp2->walked + 1); - if (*dir2 > *(temp2->walked + 3)) - *dir2 = *(temp2->walked + 3); - } - else if (orientation == 3) - { - if (*dir1 > *(temp2->walked + orientation - 3)) - *dir1 = *(temp2->walked + orientation - 3) ; - if (*dir2 > *(temp2->walked + orientation -1 )) - *dir2 = *(temp2->walked + orientation - 1); - } - else - { - if (*dir1 > *(temp2->walked + orientation - 1)) - *dir1 = *(temp2->walked + orientation -1) ; - if (*dir2 > *(temp2->walked+ orientation + 1)) - *dir2 = *(temp2->walked + orientation + 1); - } - - /* if we know already that we can't extend the - band from this face, we do not need to do the walk - */ - if ((*dir1 != 0) && (*dir2 != 0)) - { - /* Find the adjacent face to this edge */ - node = *(temp2->VertandId+orientation); - if (face_id == node->edge[1]) - nextvert = node->edge[2]; - else - nextvert = node->edge[1]; - } - else - nextvert = -1; /* leave w/o walking */ - - /* Keep walking in this direction until we cannot do so */ - while ((nextvert != face_id) && (nextvert != -1)) - { - walk++; - pListHead = PolFaces[nextvert]; - temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0); - numverts = temp2->nPolSize; - if ((numverts != 4) || (walk > cutoff_length)) - nextvert = -1; - else - { - /* Find edge that is not adjacent to the previous one */ - counter = 0; - flag = TRUE; - while ((counter < 3) && (flag)) - { - if ( ((*(temp2->pPolygon+counter) == previous_edge1) || - (*(temp2->pPolygon+counter+1) == previous_edge2)) || - ((*(temp2->pPolygon+counter) == previous_edge2) || - (*(temp2->pPolygon+counter+1) == previous_edge1)) ) - counter++; - else - flag = FALSE; - } - /* Get the IDs of the next edge */ - if (counter < 3) - { - previous_edge1 = *(temp2->pPolygon + counter); - previous_edge2 = *(temp2->pPolygon + counter + 1); - } - else - { - previous_edge1 = *(temp2->pPolygon + counter); - previous_edge2 = *(temp2->pPolygon); - } - - /* find out how far we can extend in the 2 directions - along this new face in the walk - */ - if (counter == 0) - { - if (*dir1 > *(temp2->walked + 1)) - *dir1 = *(temp2->walked + 1); - if (*dir2 > *(temp2->walked + 3)) - *dir2 = *(temp2->walked + 3); - } - else if (counter == 3) - { - if (*dir1 > *(temp2->walked + counter - 3)) - *dir1 = *(temp2->walked + counter - 3) ; - if (*dir2 > *(temp2->walked + counter -1 )) - *dir2 = *(temp2->walked + counter -1); - } - else - { - if (*dir1 > *(temp2->walked + counter - 1)) - *dir1 = *(temp2->walked + counter -1) ; - if (*dir2 > *(temp2->walked + counter + 1)) - *dir2 = *(temp2->walked + counter + 1); - } - - /* if we know already that we can't extend the - band from this face, we do not need to do the walk - */ - if ((*dir1 == 0) || (*dir2 == 0)) - nextvert = -1; - if (nextvert != -1) - { - node = *(temp2->VertandId + counter); - if (node->edge[1] == nextvert) - nextvert = node->edge[2]; - else - nextvert = node->edge[1]; - } - - } - } -} - - - - -int Find_Max(PF_FACES temp2,int lastvert,int north,int left, - int *lastminup,int *lastminleft) -{ - int temp,walk,counter,minup,x,band_value; - int previous_edge1, previous_edge2; - F_EDGES *node; - ListHead *pListHead; - BOOL flag; - static int last_seen = 0; - register int t,smallest_so_far,nextvert,max=-1; - - t= lastvert; - *lastminup = MAX_BAND; - *lastminleft = 1; - - if (left == 3) - { - previous_edge1 = *(temp2->pPolygon + left); - previous_edge2 = *(temp2->pPolygon); - } - - else - { - previous_edge1 = *(temp2->pPolygon + left + 1); - previous_edge2 = *(temp2->pPolygon + left); - } - - temp2->seen = last_seen; - walk = *(temp2->walked + left); - - for (x=1;x<=(walk+1); x++) - { - /* test to see if we have a true band - that is, are they adjacent to each other - */ - - minup = *(temp2->walked + north) + 1; - - /* if we are at the very first face, then we do not - have to check the adjacent faces going up - and our north distance is the distance of this face's - north direction. - */ - if (x == 1) - { - *lastminup = minup; - minup = Test_Adj(temp2,x,north,*lastminup,lastvert,last_seen); - *lastminup = minup; - smallest_so_far = minup; - } - - - /* find the largest band that we can have */ - if (minup < (*lastminup)) - { - /* see if we really can go up all the way - temp should by less than our equal to minup - if it is less, then one of the faces was not - adjacent to those next to it and the band height - will be smaller - */ - temp = Test_Adj(temp2,x,north,minup,lastvert,last_seen); - if (temp > minup) - { - printf("There is an error in the test adj\n"); - exit(0); - } - minup = temp; - band_value = x * minup; - if (minup < smallest_so_far) - { - if (band_value > max) - { - smallest_so_far = minup; - *lastminup = minup; - *lastminleft = x; - max = band_value; - } - else - smallest_so_far = minup; - } - else - { - band_value = x * smallest_so_far; - if (band_value > max) - { - *lastminup = smallest_so_far; - *lastminleft = x; - max = band_value; - } - } - } - else - { - if (x != 1) - { - temp = Test_Adj(temp2,x,north,smallest_so_far,lastvert,last_seen); - if (temp > smallest_so_far) - { - printf("There is an error in the test adj\n"); - exit(0); - } - smallest_so_far = temp; - } - band_value = x * smallest_so_far; - if (band_value > max) - { - *lastminup = smallest_so_far; - *lastminleft = x; - max = band_value; - } - } - if ( x != (walk + 1)) - { - node = *(temp2->VertandId+left); - if (lastvert == node->edge[1]) - nextvert = node->edge[2]; - else - nextvert = node->edge[1]; - - lastvert = nextvert; - - if (nextvert == -1) - return max; - - pListHead = PolFaces[nextvert]; - temp2 = (PF_FACES) PeekList(pListHead, LISTHEAD, 0); - - /* if we have visited this face before, then there is an error */ - if (((*(temp2->walked) == -1) && (*(temp2->walked+1) == -1) && - (*(temp2->walked+2) == -1) && (*(temp2->walked+3) == -1)) - || (temp2->nPolSize !=4) || (temp2->seen == last_seen)) - { - - if (lastvert == node->edge[1]) - nextvert = node->edge[2]; - else - nextvert = node->edge[1]; - if (nextvert == -1) - return max; - lastvert = nextvert; - /* Last attempt to get the face ... */ - pListHead = PolFaces[nextvert]; - temp2 = (PF_FACES) PeekList(pListHead, LISTHEAD, 0); - if (((*(temp2->walked) == -1) && (*(temp2->walked+1) == -1) && - (*(temp2->walked+2) == -1) && (*(temp2->walked+3) == -1)) - || (temp2->nPolSize !=4) || (temp2->seen == last_seen)) - return max; /* The polygon was not saved with the edge, not - enough room. We will get the walk when we come - to that polygon later. - */ - } - else - { - counter = 0; - flag = TRUE; - temp2->seen = last_seen; - - while ((counter < 3) && (flag)) - { - - if ( ((*(temp2->pPolygon+counter) == previous_edge1) || - (*(temp2->pPolygon+counter+1) == previous_edge2)) || - ((*(temp2->pPolygon+counter) == previous_edge2) || - (*(temp2->pPolygon+counter+1) == previous_edge1)) ) - counter++; - else - flag = FALSE; - } - } - - /* Get the IDs of the next edge */ - left = counter; - north = left+1; - if (left ==3) - north = 0; - if (counter < 3) - { - previous_edge1 = *(temp2->pPolygon + counter + 1); - previous_edge2 = *(temp2->pPolygon + counter); - } - else - { - previous_edge1 = *(temp2->pPolygon + counter); - previous_edge2 = *(temp2->pPolygon); - } - - } - -} -last_seen++; -return max; -} - -void Mark_Face(PF_FACES temp2, int color1, int color2, - int color3, FILE *output_file, BOOL end, int *edge1, int *edge2, - int *face_id, int norms, int texture) -{ - static int last_quad[4]; - register int x,y,z=0; - int saved[2]; - static int output1, output2,last_id; - BOOL cptexture; - - /* Are we done with the patch? If so return the last edge that - we will come out on, and that will be the edge that we will - start to extend upon. - */ - - cptexture = texture; - if (end) - { - *edge1 = output1; - *edge2 = output2; - *face_id = last_id; - return; - } - - last_id = *face_id; - *(temp2->walked) = -1; - *(temp2->walked+1) = -1; - *(temp2->walked+2) = -1; - *(temp2->walked+3) = -1; - added_quad++; - temp2->nPolSize = 1; - - if (patch == 0) - { - /* At the first quad in the strip -- save it */ - last_quad[0] = *(temp2->pPolygon); - last_quad[1] = *(temp2->pPolygon+1); - last_quad[2] = *(temp2->pPolygon+2); - last_quad[3] = *(temp2->pPolygon+3); - patch++; - } - else - { - /* Now we have a triangle to output, find the edge in common */ - for (x=0; x < 4 ;x++) - { - for (y=0; y< 4; y++) - { - if (last_quad[x] == *(temp2->pPolygon+y)) - { - saved[z++] = last_quad[x]; - if (z > 2) - { - /* This means that there was a non convex or - an overlapping polygon - */ - z--; - break; - } - } - } - } - - if (z != 2) - { - printf("Z is not 2 %d \n",patch); - printf("4 %d %d %d %d %d %d %d\n",*(temp2->pPolygon), - *(temp2->pPolygon+1),*(temp2->pPolygon+2),*(temp2->pPolygon+3), - color1,color2,color3); - printf("%d %d %d %d\n",last_quad[0],last_quad[1],last_quad[2],last_quad[3]); - exit(1); - } - - if (patch == 1) - { - /* First one to output, there was no output edge */ - patch++; - x = Adjacent(saved[0],saved[1],last_quad,4); - y = Adjacent(saved[1],saved[0],last_quad,4); - - /* Data might be mixed and we do not have textures for some of the vertices */ - if ((texture) && ( ((vt[x]) == 0) || ((vt[y])==0) || ((vt[saved[1]])==0))) - cptexture = FALSE; - - if ((!norms) && (!cptexture)) - { - fprintf(output_file,"\nt %d %d %d ",x+1,y+1,saved[1]+1); - fprintf(output_file,"%d ",saved[0]+1); - } - else if ((norms) && (!cptexture)) - { - fprintf(output_file,"\nt %d//%d %d//%d %d//%d ",x+1,vn[x] +1, - y+1,vn[y] +1, - saved[1]+1,vn[saved[1]]+1); - fprintf(output_file,"%d//%d ",saved[0]+1,vn[saved[0]]+1); - } - else if ((cptexture) && (!norms)) - { - fprintf(output_file,"\nt %d/%d %d/%d %d/%d ",x+1,vt[x] +1, - y+1,vt[y] +1, - saved[1]+1,vt[saved[1]]+1); - fprintf(output_file,"%d//%d ",saved[0]+1,vt[saved[0]]+1); - } - else - { - fprintf(output_file,"\nt %d/%d/%d %d/%d/%d %d/%d/%d ",x+1,vt[x]+1,vn[x] +1, - y+1,vt[y]+1,vn[y] +1, - saved[1]+1,vt[saved[1]]+1,vn[saved[1]]+1); - fprintf(output_file,"%d/%d/%d ",saved[0]+1,vt[saved[0]]+1,vn[saved[0]]+1); - } - - x = Adjacent(saved[0],saved[1],temp2->pPolygon,4); - y = Adjacent(saved[1],saved[0],temp2->pPolygon,4); - - /* Data might be mixed and we do not have textures for some of the vertices */ - if ((texture) && ( (vt[x] == 0) || (vt[y]==0))) - { - if (cptexture) - fprintf(output_file,"\nq "); - cptexture = FALSE; - } - if ((!norms) && (!cptexture)) - { - fprintf(output_file,"%d ",x+1); - fprintf(output_file,"%d ",y+1); - } - else if ((norms) && (!cptexture)) - { - fprintf(output_file,"%d//%d ",x+1,vn[x]+1); - fprintf(output_file,"%d//%d ",y+1,vn[y]+1); - } - else if ((cptexture) && (!norms)) - { - fprintf(output_file,"%d/%d ",x+1,vt[x]+1); - fprintf(output_file,"%d/%d ",y+1,vt[y]+1); - } - else - { - fprintf(output_file,"%d/%d/%d ",x+1,vt[x]+1,vn[x]+1); - fprintf(output_file,"%d/%d/%d ",y+1,vt[y]+1,vn[y]+1); - } - - output1 = x; - output2 = y; - } - - else - { - x = Adjacent(output2,output1,temp2->pPolygon,4); - y = Adjacent(output1,output2,temp2->pPolygon,4); - /* Data might be mixed and we do not have textures for some of the vertices */ - if ((texture) && ( ((vt[x]) == 0) || ((vt[y])==0) )) - texture = FALSE; - - if ((!norms) && (!texture)) - { - fprintf(output_file,"\nq %d ",x+1); - fprintf(output_file,"%d ",y+1); - } - else if ((norms) && (!texture)) - { - fprintf(output_file,"\nq %d//%d ",x+1,vn[x]+1); - fprintf(output_file,"%d//%d ",y+1,vn[y]+1); - } - else if ((texture) && (!norms)) - { - fprintf(output_file,"\nq %d/%d ",x+1,vt[x]+1); - fprintf(output_file,"%d/%d ",y+1,vt[y]+1); - } - else - { - fprintf(output_file,"\nq %d/%d/%d ",x+1,vt[x]+1,vn[x]+1); - fprintf(output_file,"%d/%d/%d ",y+1,vt[y]+1,vn[y]+1); - } - - output1 = x; - output2 = y; - } - - last_quad[0] = *(temp2->pPolygon); - last_quad[1] = *(temp2->pPolygon+1); - last_quad[2] = *(temp2->pPolygon+2); - last_quad[3] = *(temp2->pPolygon+3); - } -} - -void Fast_Reset(int x) -{ - register int y,numverts; - register int front_walk, back_walk; - ListHead *pListHead; - PF_FACES temp = NULL; - - pListHead = PolFaces[x]; - temp = (PF_FACES) PeekList(pListHead,LISTHEAD,0); - numverts = temp->nPolSize; - - front_walk = 0; - back_walk = 0; - resetting = TRUE; - - /* we are doing this only for quads */ - if (numverts == 4) - { - /* for each face not seen yet, do North and South together - and East and West together - */ - for (y=0;y<2;y++) - { - /* Check if the opposite sides were seen already */ - /* Find walk for the first edge */ - front_walk = Calculate_Walks(x,y,temp); - /* Find walk in the opposite direction */ - back_walk = Calculate_Walks(x,y+2,temp); - /* Now put into the data structure the numbers that - we have found - */ - Assign_Walk(x,temp,front_walk,y,back_walk); - Assign_Walk(x,temp,back_walk,y+2,front_walk); - } - } - resetting = FALSE; -} - - -void Reset_Max(PF_FACES temp2,int face_id,int north,int last_north, int orientation, - int last_left,FILE *output_file,int color1,int color2,int color3, - BOOL start) -{ - register int walk = 0,count = 0; - int previous_edge1,previous_edge2; - int static last_seen = 1000; - F_EDGES *node; - ListHead *pListHead; - int f,t,nextvert,counter; - BOOL flag; - - - /* Reset walks on faces, since we just found a patch */ - if (orientation !=3) - { - previous_edge1 = *(temp2->pPolygon + orientation+1); - previous_edge2 = *(temp2->pPolygon + orientation ); - } - else - { - previous_edge1 = *(temp2->pPolygon + orientation ); - previous_edge2 = *(temp2->pPolygon); - } - - /* only if we are going left, otherwise there will be -1 there */ - /*Find the adjacent face to this edge */ - - for (t = 0; t <=3 ; t++) - { - node = *(temp2->VertandId+t); - - if (face_id == node->edge[1]) - f = node->edge[2]; - else - f = node->edge[1]; - - if (f != -1) - Fast_Reset(f); - } - - node = *(temp2->VertandId+orientation); - if (face_id == node->edge[1]) - nextvert = node->edge[2]; - else - nextvert = node->edge[1]; - - while ((last_left--) > 1) - { - - if (start) - Reset_Max(temp2,face_id,orientation,last_left,north,last_north,output_file,color1,color2,color3,FALSE); - - face_id = nextvert; - pListHead = PolFaces[nextvert]; - temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0); - if ((temp2->nPolSize != 4) && (temp2->nPolSize != 1)) - { - /* There is more than 2 polygons on the edge, and we could have - gotten the wrong one - */ - if (nextvert != node->edge[1]) - nextvert = node->edge[1]; - else - nextvert = node->edge[2]; - pListHead = PolFaces[nextvert]; - temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0); - node = *(temp2->VertandId+orientation); - } - - - if (!start) - { - for (t = 0; t <=3 ; t++) - { - node = *(temp2->VertandId+t); - - if (face_id == node->edge[1]) - f = node->edge[2]; - else - f = node->edge[1]; - - if (f != -1) - Fast_Reset(f); - } - } - - - counter = 0; - flag = TRUE; - while ((counter < 3) && (flag)) - { - if ( ((*(temp2->pPolygon+counter) == previous_edge1) || - (*(temp2->pPolygon+counter+1) == previous_edge2)) || - ((*(temp2->pPolygon+counter) == previous_edge2) || - (*(temp2->pPolygon+counter+1) == previous_edge1)) ) - counter++; - else - flag = FALSE; - } - - /* Get the IDs of the next edge */ - if (counter < 3) - { - previous_edge1 = *(temp2->pPolygon + counter+1); - previous_edge2 = *(temp2->pPolygon + counter); - } - else - { - previous_edge1 = *(temp2->pPolygon + counter); - previous_edge2 = *(temp2->pPolygon); - } - orientation = counter; - - node = *(temp2->VertandId + counter); - if (node->edge[1] == nextvert) - nextvert = node->edge[2]; - else - nextvert = node->edge[1]; - - if (!reversed) - { - if (counter != 3) - north = counter +1; - else - north = 0; - } - else - { - if (counter != 0) - north = counter -1; - else - north = 3; - - } - } -if (start) - Reset_Max(temp2,face_id,orientation,last_left,north,last_north,output_file,color1,color2,color3,FALSE); -else if (nextvert != -1) - Fast_Reset(nextvert); - -} - - -int Peel_Max(PF_FACES temp2,int face_id,int north,int last_north, int orientation, - int last_left,FILE *output_file,int color1,int color2,int color3, - BOOL start, int *swaps_added, int norms, int texture) -{ - int end1,end2,last_id,s=0,walk = 0,count = 0; - int previous_edge1,previous_edge2; - int static last_seen = 1000; - F_EDGES *node; - ListHead *pListHead; - int nextvert,numverts,counter,dummy,tris=0; - BOOL flag; - - /* Peel the patch from the model. - We will try and extend off the end of each strip in the patch. We will return the - number of triangles completed by this extension only, and the number of swaps - in the extension only. - */ - patch = 0; - - if (orientation !=3) - { - previous_edge1 = *(temp2->pPolygon + orientation+1); - previous_edge2 = *(temp2->pPolygon + orientation ); - } - else - { - previous_edge1 = *(temp2->pPolygon + orientation ); - previous_edge2 = *(temp2->pPolygon); - } - - - walk = *(temp2->walked + orientation); - - /* only if we are going left, otherwise there will be -1 there */ - if ((start) && ((walk+1) < last_left)) - { - printf("There is an error in the left %d %d\n",walk,last_left); - exit(0); - } - - /* Find the adjacent face to this edge */ - node = *(temp2->VertandId+orientation); - if (face_id == node->edge[1]) - nextvert = node->edge[2]; - else - nextvert = node->edge[1]; - temp2->seen = last_seen; - - - while ((last_left--) > 1) - { - if (start) - tris += Peel_Max(temp2,face_id,orientation,last_left,north,last_north,output_file, - color1,color2,color3,FALSE,swaps_added,norms,texture); - else - Mark_Face(temp2,color1,color2,color3,output_file,FALSE,&dummy,&dummy,&face_id,norms,texture); - - - pListHead = PolFaces[nextvert]; - temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0); - numverts = temp2->nPolSize; - - if ((numverts != 4) || (temp2->seen == last_seen) - || (nextvert == -1)) - { - - /* There is more than 2 polygons on the edge, and we could have - gotten the wrong one - */ - if (nextvert != node->edge[1]) - nextvert = node->edge[1]; - else - nextvert = node->edge[2]; - pListHead = PolFaces[nextvert]; - temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0); - numverts = temp2->nPolSize; - if ((numverts != 4) || (temp2->seen == last_seen) ) - { - printf("Peel 2 %d\n",numverts); - exit(1); - } - } - - face_id = nextvert; - temp2->seen = last_seen; - - counter = 0; - flag = TRUE; - while ((counter < 3) && (flag)) - { - if ( ((*(temp2->pPolygon+counter) == previous_edge1) || - (*(temp2->pPolygon+counter+1) == previous_edge2)) || - ((*(temp2->pPolygon+counter) == previous_edge2) || - (*(temp2->pPolygon+counter+1) == previous_edge1)) ) - counter++; - else - flag = FALSE; - } - /* Get the IDs of the next edge */ - if (counter < 3) - { - previous_edge1 = *(temp2->pPolygon + counter+1); - previous_edge2 = *(temp2->pPolygon + counter); - } - else - { - previous_edge1 = *(temp2->pPolygon + counter); - previous_edge2 = *(temp2->pPolygon); - } - orientation = counter; - - node = *(temp2->VertandId + counter); - if (node->edge[1] == nextvert) - nextvert = node->edge[2]; - else - nextvert = node->edge[1]; - - if (!reversed) - { - if (counter != 3) - north = counter +1; - else - north = 0; - } - else - { - if (counter != 0) - north = counter -1; - else - north = 3; - } -} - -if (start) - tris += Peel_Max(temp2,face_id,orientation,last_left,north,last_north,output_file, - color1,color2,color3,FALSE,swaps_added,norms,texture); -else - Mark_Face(temp2,color1,color2,color3,output_file,FALSE,&dummy,&dummy,&face_id,norms,texture);/* do the last face */ - -last_seen++; - -/* Get the edge that we came out on the last strip of the patch */ -Mark_Face(NULL,0,0,0,output_file,TRUE,&end1,&end2,&last_id,norms,texture); -tris += Extend_Face(last_id,end1,end2,&s,output_file,color1,color2,color3,vn,norms,vt,texture); -*swaps_added = *swaps_added + s; -return tris; -} - - - -void Find_Bands(int numfaces, FILE *output_file, int *swaps, int *bands, - int *cost, int *tri, int norms, int *vert_norms, int texture, int *vert_texture) -{ - - register int x,y,max1,max2,numverts,face_id,flag,maximum = 25; - ListHead *pListHead; - PF_FACES temp = NULL; - int color1 = 0, color2 = 100, color3 = 255; - int color = 0,larger,smaller; - int north_length1,last_north,left_length1,last_left,north_length2,left_length2; - int total_tri = 0, total_swaps = 0,last_id; - int end1, end2,s=0; - register int cutoff = 20; - - /* Code that will find the patches. "Cutoff" will be - the cutoff of the area of the patches that we will be allowing. After - we reach this cutoff length, then we will run the local algorithm on the - remaining faces. - */ - - /* For each faces that is left find the largest possible band that we can - have with the remaining faces. Note that we will only be finding patches - consisting of quads. - */ - -vn = vert_norms; -vt = vert_texture; -y=1; -*bands = 0; - -while ((maximum >= cutoff)) -{ - y++; - maximum = -1; - for (x=0; xnPolSize; - - /* we are doing this only for quads */ - if (numverts == 4) - { - /* We want a face that is has not been used yet, - since we know that that face must be part of - a band. Then we will find the largest band that - the face may be contained in - */ - - /* Doing the north and the left */ - if ((*(temp->walked) != -1) && (*(temp->walked+3) != -1)) - max1 = Find_Max(temp,x,0,3,&north_length1,&left_length1); - if ((*(temp->walked+1) != -1) && (*(temp->walked+2) != -1)) - max2 = Find_Max(temp,x,2,1,&north_length2,&left_length2); - if ((max1 != (north_length1 * left_length1)) || - (max2 != (north_length2 * left_length2))) - { - printf("Max1 %d, %d %d Max2 %d, %d %d\n",max1,north_length1,left_length1,max2,north_length2,left_length2); - exit(0); - } - - - if ((max1 > max2) && (max1 > maximum)) - { - maximum = max1; - face_id = x; - flag = 1; - last_north = north_length1; - last_left = left_length1; - /* so we know we saved max1 */ - } - else if ((max2 > maximum) ) - { - maximum = max2; - face_id = x; - flag = 2; - last_north = north_length2; - last_left = left_length2; - /* so we know we saved max2 */ - } - } - } - if ((maximum < cutoff) && (*bands == 0)) - return; - pListHead = PolFaces[face_id]; - temp = (PF_FACES) PeekList(pListHead,LISTHEAD,0); - /* There are no patches that we found in this pass */ - if (maximum == -1) - break; - /*printf("The maximum is face %d area %d: lengths %d %d\n",face_id,maximum,last_north,last_left);*/ - - if (last_north > last_left) - { - larger = last_north; - smaller = last_left; - } - else - { - larger = last_left; - smaller = last_north; - } - - length = larger; - -if (flag == 1) -{ - if (last_north > last_left) /* go north sequentially */ - { - total_tri += Peel_Max(temp,face_id,0,last_north,3,last_left,output_file,color1,color2,color3,TRUE,&s,norms,texture); - Reset_Max(temp,face_id,0,last_north,3,last_left,output_file,color1,color2,color3,TRUE); - total_swaps += s; - } - else - { - reversed = TRUE; - total_tri += Peel_Max(temp,face_id,3,last_left,0,last_north,output_file,color1,color2,color3,TRUE,&s,norms,texture); - Reset_Max(temp,face_id,3,last_left,0,last_north,output_file,color1,color2,color3,TRUE); - reversed = FALSE; - total_swaps += s; - } - - - /* Get the edge that we came out on the last strip of the patch */ - Mark_Face(NULL,0,0,0,NULL,TRUE,&end1,&end2,&last_id,norms,texture); - total_tri += Extend_Face(last_id,end1,end2,&s,output_file,color1,color2,color3,vn,norms,vt,texture); - total_swaps += s; - -} -else -{ - if (last_north > last_left) - { - total_tri += Peel_Max(temp,face_id,2,last_north,1,last_left,output_file,color1,color2,color3,TRUE,&s,norms,texture); - Reset_Max(temp,face_id,2,last_north,1,last_left,output_file,color1,color2,color3,TRUE); - total_swaps += s; - } - else - { - reversed = TRUE; - total_tri += Peel_Max(temp,face_id,1,last_left,2,last_north,output_file,color1,color2,color3,TRUE,&s,norms,texture); - Reset_Max(temp,face_id,1,last_left,2,last_north,output_file,color1,color2,color3,TRUE); - reversed = FALSE; - total_swaps += s; - } - - /* Get the edge that we came out on on the patch */ - Mark_Face(NULL,0,0,0,NULL,TRUE,&end1,&end2,&last_id,norms,texture); - total_tri += Extend_Face(last_id,end1,end2,&s,output_file,color1,color2,color3,vn,norms,vt,texture); - total_swaps += s; -} - - /* Now compute the cost of transmitting this band, is equal to - going across the larger portion sequentially, - and swapping 3 times per other dimension - */ - -total_tri += (maximum * 2); -*bands = *bands + smaller; - -} - -/*printf("We transmitted %d triangles,using %d swaps and %d strips\n",total_tri, - total_swaps, *bands); -printf("COST %d\n",total_tri + total_swaps + *bands + *bands);*/ -*cost = total_tri + total_swaps + *bands + *bands; -*tri = total_tri; -added_quad = added_quad * 4; -*swaps = total_swaps; -} - - -void Save_Rest(int *numfaces) -{ - /* Put the polygons that are left into a data structure so that we can run the - stripping code on it. - */ - register int x,y=0,numverts; - ListHead *pListHead; - PF_FACES temp=NULL; - - for (x=0; x<*numfaces; x++) - { - /* for each face, get the face */ - pListHead = PolFaces[x]; - temp = (PF_FACES) PeekList(pListHead,LISTHEAD,0); - numverts = temp->nPolSize; - /* If we did not do the face before add it to data structure with new - face id number - */ - if (numverts != 1) - { - CopyFace(temp->pPolygon,numverts,y+1,temp->pNorms); - y++; - } - /* Used it, so remove it */ - else - RemoveList(pListHead,(PLISTINFO) temp); - - } - *numfaces = y; -} - -void Assign_Walk(int lastvert,PF_FACES temp2, int front_walk,int y, - int back_walk) -{ -/* Go back and do the walk again, but this time save the lengths inside - the data structure. - y was the starting edge number for the front_walk length - back_walk is the length of the walk along the opposite edge - */ - int previous_edge1, previous_edge2; - register int walk = 0,nextvert,numverts,counter; - BOOL flag; - F_EDGES *node; - ListHead *pListHead; - register int total_walk, start_back_walk; - static int seen = 0; - static BOOL first = TRUE; - int test; - BOOL f = TRUE, wrap = FALSE, set = FALSE; - test = lastvert; - - /* In the "Fast_Reset" resetting will be true */ - if ((resetting) && (first)) - { - seen = 0; - first = FALSE; - } - - seen++; - total_walk = front_walk + back_walk; - start_back_walk = back_walk; - /* Had a band who could be a cycle */ - if (front_walk == back_walk) - wrap = TRUE; - - /* Find the edge that we are currently on */ - if (y != 3) - { - previous_edge1 = *(temp2->pPolygon +y); - previous_edge2 = *(temp2->pPolygon + y + 1); - } - else - { - previous_edge1 = *(temp2->pPolygon +y); - previous_edge2 = *(temp2->pPolygon); - } - - /* Assign the lengths */ - if (y < 2) - { - *(temp2->walked+y) = front_walk--; - *(temp2->walked+y+2) = back_walk++; - } - else - { - *(temp2->walked+y) = front_walk--; - *(temp2->walked+y-2) = back_walk++; - } - - /*Find the adjacent face to this edge */ - node = *(temp2->VertandId+y); - - if (node->edge[2] != lastvert) - nextvert = node->edge[2]; - else - nextvert = node->edge[1]; - - temp2->seen3 = seen; - - /* Keep walking in this direction until we cannot do so */ - while ((nextvert != lastvert) && (nextvert != -1) && (front_walk >= 0)) - { - walk++; - pListHead = PolFaces[nextvert]; - - temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0); - numverts = temp2->nPolSize; - if ((numverts != 4)) - { - nextvert = -1; - /* Don't include this face in the walk */ - walk--; - } - else - { - /* Find edge that is not adjacent to the previous one */ - counter = 0; - flag = TRUE; - while ((counter < 3) && (flag)) - { - if ( ((*(temp2->pPolygon+counter) == previous_edge1) || - (*(temp2->pPolygon+counter+1) == previous_edge2)) || - ((*(temp2->pPolygon+counter) == previous_edge2) || - (*(temp2->pPolygon+counter+1) == previous_edge1)) ) - counter++; - else - flag = FALSE; - } - /* Get the IDs of the next edge */ - if (counter < 3) - { - previous_edge1 = *(temp2->pPolygon + counter); - previous_edge2 = *(temp2->pPolygon + counter + 1); - } - else - { - previous_edge1 = *(temp2->pPolygon + counter); - previous_edge2 = *(temp2->pPolygon); - } - - - /* Put in the walk lengths */ - if (counter < 2) - { - if (((*(temp2->walked + counter) >= 0) - || (*(temp2->walked +counter + 2) >= 0))) - { - if ((resetting == FALSE) && ((temp2->seen3) != (seen-1))) - { - /* If there are more than 2 polygons adjacent - to an edge then we can be trying to assign more than - once. We will save the smaller one - */ - temp2->seen3 = seen; - if ( (*(temp2->walked+counter) <= front_walk) && - (*(temp2->walked+counter+2) <= back_walk) ) - return; - if (*(temp2->walked+counter) > front_walk) - *(temp2->walked+counter) = front_walk--; - else - front_walk--; - if (*(temp2->walked+counter+2) > back_walk) - *(temp2->walked+counter+2) = back_walk++; - else - back_walk++; - } - else if (resetting == FALSE) - { - /* if there was a cycle then all lengths are the same */ - walk--; - back_walk--; - front_walk++; - temp2->seen3 = seen; - *(temp2->walked+counter) = front_walk--; - *(temp2->walked+counter+2) = back_walk++; - } - else if (((temp2->seen3 == (seen-1)) - && (wrap) && (walk == 1)) || (set)) - { - /* if there was a cycle then all lengths are the same */ - set = TRUE; - walk--; - back_walk--; - front_walk++; - temp2->seen3 = seen; - *(temp2->walked+counter) = front_walk--; - *(temp2->walked+counter+2) = back_walk++; - } - else - { - temp2->seen3 = seen; - *(temp2->walked+counter) = front_walk--; - *(temp2->walked+counter+2) = back_walk++; - } - } /* if was > 0 */ - else - { - temp2->seen3 = seen; - *(temp2->walked+counter) = front_walk--; - *(temp2->walked+counter+2) = back_walk++; - } - } - - else - { - if (((*(temp2->walked + counter) >= 0 ) - || (*(temp2->walked +counter - 2) >= 0)) ) - { - if ((temp2->seen3 != (seen-1)) && (resetting == FALSE)) - { - /* If there are more than 2 polygons adjacent - to an edge then we can be trying to assign more than - once. We will save the smaller one - */ - temp2->seen3 = seen; - if ( (*(temp2->walked+counter) <= front_walk) && - (*(temp2->walked+counter-2) <= back_walk) ) - return; - if (*(temp2->walked+counter) > front_walk) - *(temp2->walked+counter) = front_walk--; - else - front_walk--; - if (*(temp2->walked+counter-2) > back_walk) - *(temp2->walked+counter-2) = back_walk++; - else - back_walk++; - } - else if (resetting == FALSE) - { - walk--; - back_walk--; - front_walk++; - temp2->seen3 = seen; - *(temp2->walked+counter) = front_walk--; - *(temp2->walked+counter-2) = back_walk++; - } - else if (((temp2->seen3 == (seen-1)) && (walk == 1) && (wrap)) - || (set)) - { - /* if there was a cycle then all lengths are the same */ - set = TRUE; - walk--; - back_walk--; - front_walk++; - temp2->seen3 = seen; - *(temp2->walked+counter) = front_walk--; - *(temp2->walked+counter-2) = back_walk++; - } - else - { - temp2->seen3 = seen; - *(temp2->walked+counter) = front_walk--; - *(temp2->walked+counter-2) = back_walk++; - } - } - else - { - temp2->seen3 = seen; - *(temp2->walked+counter) = front_walk--; - *(temp2->walked+counter-2) = back_walk++; - } - - } - if (nextvert != -1) - { - node = *(temp2->VertandId + counter); - if (node->edge[1] == nextvert) - nextvert = node->edge[2]; - else - nextvert = node->edge[1]; - } - - } -} -if ((EVEN(seen)) ) - seen+=2; -} - -void Save_Walks(int numfaces) -{ - int x,y,numverts; - int front_walk, back_walk; - ListHead *pListHead; - PF_FACES temp = NULL; - - for (x=0; xnPolSize; - front_walk = 0; - back_walk = 0; - - /* we are finding patches only for quads */ - if (numverts == 4) - { - /* for each face not seen yet, do North and South together - and East and West together - */ - for (y=0;y<2;y++) - { - /* Check if the opposite sides were seen already from another - starting face, if they were then there is no need to do the walk again - */ - - if ( ((*(temp->walked+y) == -1) && - (*(temp->walked+y+2) == -1) )) - { - /* Find walk for the first edge */ - front_walk = Calculate_Walks(x,y,temp); - /* Find walk in the opposite direction */ - back_walk = Calculate_Walks(x,y+2,temp); - /* Now put into the data structure the numbers that - we have found - */ - Assign_Walk(x,temp,front_walk,y,back_walk); - Assign_Walk(x,temp,back_walk,y+2,front_walk); - } - } - } - } -} - - diff --git a/Tools/Stripe_u/options.c b/Tools/Stripe_u/options.c deleted file mode 100644 index 7322d937c..000000000 --- a/Tools/Stripe_u/options.c +++ /dev/null @@ -1,181 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: options.c - This file contains routines that are used to determine the options - that were specified by the user -*/ -/*---------------------------------------------------------------------*/ - -#include -#include -#include "options.h" -#include "global.h" - -int power_10(int power) -{ - /* Raise 10 to the power */ - register int i,p; - - p = 1; - for (i = 1; i <= power; ++i) - p = p * 10; - return p; -} - -float power_negative(int power) -{ - /* Raise 10 to the negative power */ - - register int i; - float p; - - p = (float)1; - for (i = 1; i<=power; i++) - p = p * (float).1; - return p; -} - -float convert_array(int num[],int stack_size) -{ - /* Convert an array of characters to an integer */ - - register int counter,c; - float temp =(float)0.0; - - for (c=(stack_size-1), counter = 0; c>=0; c--, counter++) - { - if (num[c] == -1) - /* We are at the decimal point, convert to decimal - less than 1 - */ - { - counter = -1; - temp = power_negative(stack_size - c - 1) * temp; - } - else - temp += power_10(counter) * num[c]; - } - - return(temp); -} - -float get_options(int argc, char **argv, int *f, int *t, int *tr, int *group) -{ - char c; - int count = 0; - int buffer[MAX1]; - int next = 0; - /* tie variable */ - enum tie_options tie = FIRST; - /* triangulation variable */ - enum triangulation_options triangulate = WHOLE; - /* normal difference variable (in degrees) */ - float norm_difference = (float)360.0; - /* file-type variable */ - enum file_options file_type = ASCII; - - /* User has the wrong number of options */ - if ((argc > 5) || (argc < 2)) - { - printf("Usage: bands -[file_option][ties_option][triangulation_option][normal_difference] file_name\n"); - exit(0); - } - - /* Interpret the options specified */ - while (--argc > 0 && (*++argv)[0] == '-') - { - /* At the next option that was specified */ - next = 1; - while (c = *++argv[0]) - switch (c) - { - case 'f': - /* Use the first polygon we see. */ - tie = FIRST; - break; - - case 'r': - /* Randomly choose the next polygon */ - tie = RANDOM; - break; - - case 'a': - /* Alternate direction in choosing the next polygon */ - tie = ALTERNATE; - break; - - case 'l': - /* Use lookahead to choose the next polygon */ - tie = LOOK; - break; - - case 'q': - /* Try to reduce swaps */ - tie = SEQUENTIAL; - break; - - case 'p': - /* Use partial triangulation of polygons */ - triangulate = PARTIAL; - break; - - case 'w': - /* Use whole triangulation of polygons */ - triangulate = WHOLE; - break; - - case 'b': - /* Input file is in binary */ - file_type = BINARY; - break; - - case 'g': - /* Strips will be grouped according to the groups in - the data file. We will have to restrict strips to be - in the grouping of the data file. - */ - *group = 1; - - /* Get each the value of the integer */ - /* We have an integer */ - default: - if ((c >= '0') && (c <= '9')) - { - /* More than one normal difference specified, use the last one */ - if (next == 1) - { - count = 0; - next = 0; - } - buffer[count++] = ATOI(c); - } - /* At the decimal point */ - else if (c == '.') - { - /* More than one normal difference specified, use the last one */ - if (next == 1) - { - count = 0; - next = 0; - } - buffer[count++] = -1; - } - else - break; - } - } - /* Convert the buffer of characters to a floating pt integer */ - if (count != 0) - norm_difference = convert_array(buffer,count); - *f = file_type; - *t = tie; - *tr = triangulate; - return norm_difference; -} diff --git a/Tools/Stripe_u/options.h b/Tools/Stripe_u/options.h deleted file mode 100644 index 055d33ea7..000000000 --- a/Tools/Stripe_u/options.h +++ /dev/null @@ -1,17 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: options.h ------------------------------------------------------------------------*/ - -float get_options(); -enum file_options {ASCII,BINARY}; -enum tie_options {FIRST, RANDOM, ALTERNATE, LOOK, SEQUENTIAL}; -enum triangulation_options {PARTIAL,WHOLE}; - diff --git a/Tools/Stripe_u/output.c b/Tools/Stripe_u/output.c deleted file mode 100644 index d6c30f613..000000000 --- a/Tools/Stripe_u/output.c +++ /dev/null @@ -1,582 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: output.c - This file contains routines that are finding and outputting the - strips from the local algorithm -*/ -/*---------------------------------------------------------------------*/ - -#include -#include -#include "global.h" -#include "polverts.h" -#include "triangulate.h" -#include "partial.h" -#include "sturcts.h" -#include "ties.h" -#include "options.h" -#include "common.h" -#include "util.h" -#include "free.h" - -int *vn; -int *vt; -int norm; -int text; - -int Finished(int *swap, FILE *output, BOOL global) -{ - /* We have finished all the triangles, now is time to output to - the data file. In the strips data structure, every three ids - is a triangle. Now we see whether we can swap, or make a new strip - or continue the strip, and output the data accordingly to the - data file. - */ - register int start_swap = 0; - int num,x,vertex1,vertex2; - ListHead *pListHead; - int id[2],other1,other2,index = 0,a,b,c; - P_STRIPS temp1,temp2,temp3,temp4,temp5,temp6; - BOOL cptexture; - *swap =0; - - cptexture = text; - pListHead = strips[0]; - if (pListHead == NULL) - return 0; - - num = NumOnList(pListHead); - /*printf ("There are %d triangles in the extend\n",num/3);*/ - - /* Go through the list triangle by triangle */ - temp1 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 0); - temp2 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 1); - temp3 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 2); - - /* Next triangle for lookahead */ - temp4 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 3); - - - /* There is only one polygon in the strip */ - if (temp4 == NULL) - { - /* Data might be mixed and we do not have textures for some of the vertices */ - if ((text) && (vt[temp3->face_id] == 0)) - cptexture = FALSE; - if ((norm) && (!cptexture)) - fprintf(output,"%d//%d %d//%d %d//%d",temp3->face_id+1,vn[temp3->face_id]+1, - temp2->face_id+1,vn[temp2->face_id]+1, - temp1->face_id+1,vn[temp1->face_id]+1); - else if ((cptexture) && (!norm)) - fprintf(output,"%d/%d %d/%d %d/%d",temp3->face_id+1,vt[temp3->face_id]+1, - temp2->face_id+1,vt[temp2->face_id]+1, - temp1->face_id+1,vt[temp1->face_id]+1); - else if ((cptexture)&& (norm)) - fprintf(output,"%d/%d/%d %d/%d/%d %d/%d/%d",temp3->face_id+1,vt[temp3->face_id]+1,vn[temp3->face_id]+1, - temp2->face_id+1,vt[temp2->face_id]+1,vn[temp2->face_id]+1, - temp1->face_id+1,vt[temp1->face_id]+1,vn[temp1->face_id]+1); - else - fprintf(output,"%d %d %d",temp3->face_id+1,temp2->face_id+1,temp1->face_id+1); - Free_Strips(); - return 1; - } - - /* We have a real strip */ - temp5 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 4); - temp6 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 5); - - if ((temp1 == NULL) || (temp2 == NULL) || (temp3 == NULL) || (temp5 == NULL) || (temp6 == NULL)) - { - printf("There is an error in the output of the triangles\n"); - exit(0); - } - - /* Find the vertex in the first triangle that is not in the second */ - vertex1 = Different(temp1->face_id,temp2->face_id,temp3->face_id,temp4->face_id,temp5->face_id,temp6->face_id,&other1,&other2); - /* Find the vertex in the second triangle that is not in the first */ - vertex2 = Different(temp4->face_id,temp5->face_id,temp6->face_id,temp1->face_id,temp2->face_id,temp3->face_id,&other1,&other2); - - /* Lookahead for the correct order of the 2nd and 3rd vertex of the first triangle */ - temp1 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 6); - temp2 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 7); - temp3 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 8); - - if (temp1 != NULL) - other1 = Different(temp3->face_id,temp4->face_id,temp5->face_id,temp1->face_id,temp2->face_id,temp3->face_id,&other1,&a); - - id[index] = vertex1; index = !index; - id[index] = other1; index = !index; - id[index] = other2; index = !index; - - a = temp4->face_id; - b = temp5->face_id; - c = temp6->face_id; - - /* If we need to rearrange the first sequence because otherwise - there would have been a swap. - */ - - if ((temp3 != NULL) && (text) && ( vt[temp3->face_id]==0)) - cptexture = FALSE; - if ((norm) && (!cptexture)) - fprintf(output,"%d//%d %d//%d %d//%d ",vertex1+1,vn[vertex1]+1,other1+1,vn[other1]+1, - other2+1,vn[other2]+1); - else if ((cptexture) && (!norm)) - fprintf(output,"%d/%d %d/%d %d/%d ",vertex1+1,vt[vertex1]+1,other1+1,vt[other1]+1, - other2+1,vt[other2]+1); - else if ((cptexture) && (norm)) - fprintf(output,"%d/%d/%d %d/%d/%d %d/%d/%d ",vertex1+1,vt[vertex1]+1,vn[vertex1]+1, - other1+1,vt[other1]+1,vn[other1]+1, - other2+1,vt[other2]+1,vn[other2]+1); - else - fprintf(output,"%d %d %d ",vertex1+1,other1+1,other2+1); - - - for (x = 6; x < num ; x = x+3) - { - - /* Get the next triangle */ - temp1 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, x); - temp2 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, x+1); - temp3 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, x+2); - - /* Error checking */ - if (!(member(id[0],a,b,c)) || !(member(id[1],a,b,c)) || !(member(vertex2,a,b,c))) - { - /* If we used partial we might have a break in the middle of a strip */ - fprintf(output,"\nt "); - /* Find the vertex in the first triangle that is not in the second */ - vertex1 = Different(a,b,c,temp1->face_id,temp2->face_id,temp3->face_id,&other1,&other2); - /* Find the vertex in the second triangle that is not in the first */ - vertex2 = Different(temp1->face_id,temp2->face_id,temp3->face_id,a,b,c,&other1,&other2); - - id[index] = vertex1; index = !index; - id[index] = other1; index = !index; - id[index] = other2; index = !index; - } - - if ((temp1 == NULL ) || (temp2 == NULL) || (temp3 == NULL)) - { - printf("There is an error in the triangle list \n"); - exit(0); - } - - if ((id[0] == id[1]) || (id[0] == vertex2)) - continue; - - if ((member(id[index],temp1->face_id,temp2->face_id,temp3->face_id))) - { - if ((text) && ( vt[id[index]]==0)) - cptexture = FALSE; - if ((!norm) && (!cptexture)) - fprintf(output,"%d ",id[index]+1); - else if ((norm) && (!cptexture)) - fprintf(output,"%d//%d ",id[index]+1,vn[id[index]]+1); - else if ((!norm) && (cptexture)) - fprintf(output,"%d/%d ",id[index]+1,vt[id[index]]+1); - else - fprintf(output,"%d/%d/%d ",id[index]+1,vt[id[index]]+1,vn[id[index]]+1); - index = !index; - *swap = *swap + 1; - } - - if ((text) && ( vt[vertex2]==0)) - cptexture = FALSE; - if ((!norm) && (!cptexture)) - fprintf(output,"\nq %d ",vertex2+1); - else if ((norm) && (!cptexture)) - fprintf(output,"\nq %d//%d ",vertex2+1,vn[vertex2]+1); - else if ((!norm) && (cptexture)) - fprintf(output,"\nq %d/%d ",vertex2+1,vt[vertex2]+1); - else - fprintf(output,"\nq %d/%d/%d ",vertex2+1,vt[vertex2]+1,vn[vertex2]+1); - - id[index] = vertex2; index = !index; - - /* Get the next vertex not in common */ - vertex2 = Different(temp1->face_id,temp2->face_id,temp3->face_id,a,b,c,&other1,&other2); - a = temp1->face_id; - b = temp2->face_id; - c = temp3->face_id; - } - /* Do the last vertex */ - if ((text) && (vt[vertex2]==0)) - { - if (cptexture) - fprintf(output,"\nq "); - cptexture = FALSE; - } - if ((!norm) && (!cptexture)) - fprintf(output,"%d ",vertex2+1); - else if ((norm) && (!cptexture)) - fprintf(output,"%d//%d ",vertex2+1,vn[vertex2]+1); - else if ((!norm) && (cptexture)) - fprintf(output,"%d/%d ",vertex2+1,vt[vertex2]+1); - else - fprintf(output,"%d/%d/%d ",vertex2+1,vt[vertex2]+1,vn[vertex2]+1); - - - Free_Strips(); - return (num/3); -} - -void Output_Tri(int id1, int id2, int id3,FILE *bands, int color1, int color2, int color3,BOOL end) -{ - /* We will save everything into a list, rather than output at once, - as was done in the old routine. This way for future modifications - we can change the strips later on if we want to. - */ - - int temp1,temp2,temp3; - - /* Make sure we do not have an error */ - /* There are degeneracies in some of the files */ - if ( (id1 == id2) || (id1 == id3) || (id2 == id3)) - { - printf("Degenerate triangle %d %d %d\n",id1,id2,id3); - exit(0); - } - else - { - Last_Edge(&temp1,&temp2,&temp3,0); - Add_Id_Strips(id1,end); - Add_Id_Strips(id2,end); - Add_Id_Strips(id3,end); - Last_Edge(&id1,&id2,&id3,1); - } -} - - -int Polygon_Output(P_ADJACENCIES temp,int face_id,int bucket, - ListHead *pListHead, BOOL first, int *swaps, - FILE *bands,int color1,int color2,int color3,BOOL global, BOOL end) -{ - ListHead *pListFace; - PF_FACES face; - P_ADJACENCIES pfNode; - static BOOL begin = TRUE; - int old_face,next_face_id,next_bucket,e1,e2,e3,other1,other2,other3; - P_ADJACENCIES lpListInfo; - int ties=0; - int tie = SEQUENTIAL; - - /* We have a polygon to output, the id is face id, and the number - of adjacent polygons to it is bucket. This routine extends the patches from - either end to make longer triangle strips. - */ - - - /* Now get the edge */ - Last_Edge(&e1,&e2,&e3,0); - - /* Get the polygon with id face_id */ - pListFace = PolFaces[face_id]; - face = (PF_FACES) PeekList(pListFace,LISTHEAD,0); - - /* We can't go any more */ - if ((face->nPolSize == 1) || ((face->nPolSize == 4) && (global))) /* if global, then we are still doing patches */ - { - /* Remove it from the list so we do not have to waste - time visiting it in the future, or winding up in an infinite loop - if it is the first on that we are looking at for a possible strip - */ - if (face->nPolSize == 1) - RemoveList(pListHead,(PLISTINFO) temp); - if (first) - return 0; - else - return (Finished(swaps,bands,global)); - } - - if (face->nPolSize == 3) - { - /* It is already a triangle */ - if (bucket == 0) - { - /* It is not adjacent to anything so we do not have to - worry about the order of the sides or updating adjacencies - */ - - next_face_id = Different(*(face->pPolygon),*(face->pPolygon+1),*(face->pPolygon+2), - e1,e2,e3,&other1,&other2); - face->nPolSize = 1; - - /* If this is the first triangle in the strip */ - if ((e2 == 0) && (e3 ==0)) - { - e2 = other1; - e3 = other2; - } - - Output_Tri(e2,e3,next_face_id,bands,color1,color2,color3,end); - RemoveList(pListHead,(PLISTINFO) temp); - return (Finished(swaps,bands,global)); - } - - - /* It is a triangle with adjacencies. This means that we - have to: - 1. Update the adjacencies in the list, because we are - using this polygon and it will be deleted. - 2. Get the next polygon. - */ - else - { - /* Return the face_id of the next polygon we will be using, - while updating the adjacency list by decrementing the - adjacencies of everything adjacent to the current triangle. - */ - - next_face_id = Update_Adjacencies(face_id, &next_bucket, &e1,&e2,&ties); - /* Maybe we deleted something in a patch and could not find an adj polygon */ - if (next_face_id == -1) - { - Output_Tri(*(face->pPolygon),*(face->pPolygon+1),*(face->pPolygon+2),bands,color1, - color2,color3,end); - face->nPolSize = 1; - RemoveList(pListHead,(PLISTINFO) temp); - return (Finished(swaps,bands,global)); - } - - old_face = next_face_id; - /* Find the other vertex to transmit in the triangle */ - e3 = Return_Other(face->pPolygon,e1,e2); - Last_Edge(&other1,&other2,&other3,0); - - if ((other2 != 0) && (other3 != 0)) - { - /* See which vertex in the output edge is not in the input edge */ - if ((e1 != other2) && (e1 != other3)) - e3 = e1; - else if ((e2 != other2) && (e2 != other3)) - e3 = e2; - else - { - printf("There is an error in the tri with adj\n"); - exit(0); - } - - /* See which vertex of the input edge is not in the output edge */ - if ((other2 != e1) && (other2 != e2)) - { - other1 = other2; - other2 = other3; - } - else if ((other3 != e1) && (other3 != e2)) - other1 = other3; - else - { - printf("There is an error in getting the tri with adj\n"); - exit(0); - } - - } - else - { - /* We are the first triangle in the strip and the starting edge - has not been set yet - */ - /* Maybe we deleted something in a patch and could not find an adj polygon */ - if (next_face_id == -1) - { - Output_Tri(*(face->pPolygon),*(face->pPolygon+1),*(face->pPolygon+2),bands,color1, - color2,color3,end); - face->nPolSize = 1; - RemoveList(pListHead,(PLISTINFO) temp); - return (Finished(swaps,bands,global)); - } - - other1 = e3; - e3 = e2; - other2 = e1; - } - - /* At this point the adjacencies have been updated and we - have the next polygon id - */ - - Output_Tri(other1,other2,e3,bands,color1,color2,color3,end); - face->nPolSize = 1; - RemoveList(pListHead,(PLISTINFO) temp); - begin = FALSE; - - /* Maybe we deleted something in a patch and could not find an adj polygon */ - if (next_face_id == -1) - return (Finished(swaps,bands,global)); - - if (Done(next_face_id,59,&next_bucket) == NULL) - { - printf("We deleted the next face 4%d\n",next_face_id); - exit(0); - } - - pListHead = array[next_bucket]; - pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) ); - if ( pfNode ) - pfNode->face_id = next_face_id; - lpListInfo = (P_ADJACENCIES) (SearchList(array[next_bucket], pfNode, - (int (*)(void *,void *)) (Compare))); - if (lpListInfo == NULL) - { - printf("There is an error finding the next polygon3 %d\n",next_face_id); - exit(0); - } - return (Polygon_Output(lpListInfo,next_face_id,next_bucket, - pListHead, FALSE, swaps,bands,color1,color2,color3,global,end)); - - } - } - - else - { - /* It is not a triangle, we have to triangulate it . - Since it is not adjacent to anything we can triangulate it - blindly - */ - if (bucket == 0) - { - /* It is the first polygon in the strip, therefore there is no - input edge to start with. - */ - if ((e2 == 0) && (e3 ==0)) - Blind_Triangulate(face->nPolSize,face->pPolygon,bands, - TRUE,1,color1,color2,color3); - - else - Blind_Triangulate(face->nPolSize,face->pPolygon,bands, - FALSE,1,color1,color2,color3); - - RemoveList(pListHead,(PLISTINFO) temp); - - /* We will be at the beginning of the next strip. */ - face->nPolSize = 1; - return (Finished(swaps,bands,global)); - } - - - else - { - - - /* WHOLE triangulation */ - /* It is not a triangle and has adjacencies. - This means that we have to: - 1. Triangulate this polygon, not blindly because - we have an edge that we want to come out on, that - is the edge that is adjacent to a polygon with the - least number of adjacencies. Also we must come in - on the last seen edge. - 2. Update the adjacencies in the list, because we are - using this polygon . - 3. Get the next polygon. - */ - /* Return the face_id of the next polygon we will be using, - while updating the adjacency list by decrementing the - adjacencies of everything adjacent to the current polygon. - */ - - next_face_id = Update_Adjacencies(face_id, &next_bucket, &e1,&e2,&ties); - - /* Maybe we deleted something in a patch and could not find an adj polygon */ - if (next_face_id == -1) - { - - /* If we are at the first polygon in the strip and there is no input - edge, then begin is TRUE - */ - if ((e2 == 0) && (e3 == 0)) - Blind_Triangulate(face->nPolSize,face->pPolygon, - bands,TRUE,1,color1,color2,color3); - - else - Blind_Triangulate(face->nPolSize,face->pPolygon, - bands,FALSE,1,color1,color2,color3); - - RemoveList(pListHead,(PLISTINFO) temp); - - /* We will be at the beginning of the next strip. */ - face->nPolSize = 1; - return (Finished(swaps,bands,global)); - } - - if (Done(next_face_id,59,&next_bucket) == NULL) - { - printf("We deleted the next face 6 %d %d\n",next_face_id,face_id); - exit(0); - } - - Non_Blind_Triangulate(face->nPolSize,face->pPolygon, - bands,next_face_id,face_id,1,color1,color2,color3); - - RemoveList(pListHead,(PLISTINFO) temp); - begin = FALSE; - face->nPolSize = 1; - pListHead = array[next_bucket]; - pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) ); - if ( pfNode ) - pfNode->face_id = next_face_id; - lpListInfo = (P_ADJACENCIES) (SearchList(array[next_bucket], pfNode, - (int (*)(void *,void *)) (Compare))); - if (lpListInfo == NULL) - { - printf("There is an error finding the next polygon2 %d %d\n",next_face_id,next_bucket); - exit(0); - } - return (Polygon_Output(lpListInfo,next_face_id,next_bucket, - pListHead, FALSE, swaps,bands,color1,color2,color3,global,end)); - } - - } - Last_Edge(&e1,&e2,&e3,0); - -} - - -int Extend_Face(int face_id,int e1,int e2,int *swaps,FILE *bands, - int color1,int color2,int color3,int *vert_norm, int normals, - int *vert_texture, int texture) -{ - int dummy=0,next_bucket; - P_ADJACENCIES pfNode,lpListInfo; - ListHead *pListHead; - - /* Try to extend backwards off of the local strip that we just found */ - - vn = vert_norm; - vt = vert_texture; - norm = normals; - text = texture; - - *swaps = 0; - /* Find the face that is adjacent to the edge and is not the - current face. - */ - face_id = Find_Face(face_id, e1, e2,&next_bucket); - if (face_id == -1) - return 0; - - pListHead = array[next_bucket]; - pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) ); - if ( pfNode ) - pfNode->face_id = face_id; - lpListInfo = (P_ADJACENCIES) (SearchList(array[next_bucket], pfNode, - (int (*)(void *,void *)) (Compare))); - if (lpListInfo == NULL) - { - printf("There is an error finding the next polygon3 %d\n",face_id); - exit(0); - } - Last_Edge(&dummy,&e1,&e2,1); - - /* Find a strip extending from the patch and return the cost */ - return (Polygon_Output(lpListInfo,face_id,next_bucket,pListHead,TRUE,swaps,bands,color1,color2,color3,TRUE,TRUE)); -} - - diff --git a/Tools/Stripe_u/output.h b/Tools/Stripe_u/output.h deleted file mode 100644 index d9aed50a9..000000000 --- a/Tools/Stripe_u/output.h +++ /dev/null @@ -1,26 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: output.h ------------------------------------------------------------------------*/ - - -#define TRIANGLE 3 -#define MAGNITUDE 1000000 - -void Output_Tri(); -void Sgi_Test(); -int Polygon_Output(); -void Last_Edge(); -void Extend_Backwards(); -int Finished(); -int Extend_Face(); -void Fast_Reset(); - - diff --git a/Tools/Stripe_u/outputex.c b/Tools/Stripe_u/outputex.c deleted file mode 100644 index 48d4da147..000000000 --- a/Tools/Stripe_u/outputex.c +++ /dev/null @@ -1,518 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: outputex.c - This file contains routines that are used for various functions in - the local algorithm. -*/ -/*---------------------------------------------------------------------*/ - - -#include -#include -#include "global.h" -#include "outputex.h" -#include "triangulatex.h" -#include "polverts.h" -#include "ties.h" -#include "partial.h" -#include "sturctsex.h" -#include "options.h" -#include "output.h" -#include "common.h" -#include "util.h" - - -void Output_TriEx(int id1, int id2, int id3, FILE *output, int next_face, int flag, - int where) -{ - /* We will save everything into a list, rather than output at once, - as was done in the old routine. This way for future modifications - we can change the strips later on if we want to. - */ - - int swap,temp1,temp2,temp3; - static int total=0; - static int tri=0; - static int strips = 0; - static int cost = 0; - - if (flag == -20) - { - cost = cost + where+total+tri+strips+strips; - printf("We will need to send %d vertices to the renderer\n",cost); - total = 0; - tri = 0; - strips = 0; - return ; - } - - - if (flag == -10) - /* We are finished, now is time to output the triangle list - */ - { - fprintf(output,"\nt "); - tri = tri + Finished(&swap,output,FALSE); - total = total + swap; - strips++; - /*printf("There are %d swaps %d tri %d strips\n",total,tri,strips);*/ - } - - else - { - Last_Edge(&temp1,&temp2,&temp3,0); - Add_Id_Strips(id1,where); - Add_Id_Strips(id2,where); - Add_Id_Strips(id3,where); - Last_Edge(&id1,&id2,&id3,1); - } -} - - - - -void Extend_BackwardsEx(int face_id, FILE *output, FILE *strip, int *ties, - int tie, int triangulate, - int swaps,int *next_id) -{ - /* We just made a strip, now we are going to see if we can extend - backwards from the starting face, which had 2 or more adjacencies - to start with. - */ - int bucket,next_face,num,x,y,z,c,d=1,max,f; - ListHead *pListFace; - PF_FACES face; - P_ADJACENCIES temp; - - /* Get the first triangle that we have saved the the strip data - structure, so we can see if there are any polygons adjacent - to this edge or a neighboring one - */ - First_Edge(&x,&y,&z); - - pListFace = PolFaces[face_id]; - face = (PF_FACES) PeekList(pListFace,LISTHEAD,0); - - num = face->nPolSize; - - /* Go through the edges to see if there is an adjacency - with a vertex in common to the first triangle that was - outputted in the strip. (maybe edge was deleted....) - */ - for (c=0; cpPolygon+c) == x) && (*(face->pPolygon+c+1) == y)) || - (*(face->pPolygon+c) == y) && (*(face->pPolygon+c+1) == x))) - { - /* Input edge is still there see if there is an adjacency */ - next_face = Find_Face(face_id, x, y, &bucket); - if (next_face == -1) - /* Could not find a face adjacent to the edge */ - break; - pListFace = array[bucket]; - max = NumOnList(pListFace); - for (f=0;;f++) - { - temp = (P_ADJACENCIES) PeekList(pListFace,LISTHEAD,f); - if (temp->face_id == next_face) - { - Last_Edge(&z,&y,&x,1); - Polygon_OutputEx(temp,temp->face_id,bucket,pListFace, - output,strip,ties,tie,triangulate,swaps,next_id,0); - return; - } - - if (temp == NULL) - { - printf("Error in the new buckets%d %d %d\n",bucket,max,0); - exit(0); - } - } - - } - else if ( (c == (num -1)) && - ( ((*(face->pPolygon) == x) && (*(face->pPolygon+num-1) == y)) || - (*(face->pPolygon) == y) && (*(face->pPolygon+num-1) == x))) - { - next_face = Find_Face(face_id,x,y,&bucket); - if (next_face == -1) - /* Could not find a face adjacent to the edge */ - break; - pListFace = array[bucket]; - max = NumOnList(pListFace); - for (f=0;;f++) - { - temp = (P_ADJACENCIES) PeekList(pListFace,LISTHEAD,f); - if (temp->face_id == next_face) - { - Last_Edge(&z,&y,&x,1); - Polygon_OutputEx(temp,temp->face_id,bucket,pListFace, - output,strip,ties,tie,triangulate,swaps,next_id,0); - return; - } - - if (temp == NULL) - { - printf("Error in the new buckets%d %d %d\n",bucket,max,0); - exit(0); - } - } - } - - } - -} - -void Polygon_OutputEx(P_ADJACENCIES temp,int face_id,int bucket, - ListHead *pListHead, FILE *output, FILE *strips, - int *ties, int tie, - int triangulate, int swaps, - int *next_id, int where) -{ - ListHead *pListFace; - PF_FACES face; - P_ADJACENCIES pfNode; - static BOOL begin = TRUE; - int old_face,next_face_id,next_bucket,e1,e2,e3,other1,other2,other3; - P_ADJACENCIES lpListInfo; - - /* We have a polygon to output, the id is face id, and the number - of adjacent polygons to it is bucket. - */ - - Last_Edge(&e1,&e2,&e3,0); - - /* Get the polygon with id face_id */ - pListFace = PolFaces[face_id]; - face = (PF_FACES) PeekList(pListFace,LISTHEAD,0); - - if (face->nPolSize == 3) - { - /* It is already a triangle */ - if (bucket == 0) - { - /* It is not adjacent to anything so we do not have to - worry about the order of the sides or updating adjacencies - */ - - Last_Edge(&e1,&e2,&e3,0); - next_face_id = Different(*(face->pPolygon),*(face->pPolygon+1),*(face->pPolygon+2), - e1,e2,e3,&other1,&other2); - /* No input edge, at the start */ - if ((e2 ==0) && (e3 == 0)) - { - e2 = other1; - e3 = other2; - } - - Output_TriEx(e2,e3,next_face_id,strips,-1,begin,where); - RemoveList(pListHead,(PLISTINFO) temp); - /* We will be at the beginning of the next strip. */ - begin = TRUE; - } - /* It is a triangle with adjacencies. This means that we - have to: - 1. Update the adjacencies in the list, because we are - using this polygon and it will be deleted. - 2. Get the next polygon. - */ - else - { - /* Return the face_id of the next polygon we will be using, - while updating the adjacency list by decrementing the - adjacencies of everything adjacent to the current triangle. - */ - - next_face_id = Update_AdjacenciesEx(face_id, &next_bucket, &e1,&e2,ties); - old_face = next_face_id; - - /* Break the tie, if there was one */ - if (tie != FIRST) - old_face = Get_Next_Face(tie,face_id,triangulate); - - if (next_face_id == -1) - { - Polygon_OutputEx(temp,face_id,0,pListHead,output,strips,ties,tie, - triangulate,swaps,next_id,where); - return; - } - - - /* We are using a different face */ - if ((tie != FIRST) && (old_face != next_face_id) && (swaps == ON)) - { - next_face_id = old_face; - /* Get the new output edge, since e1 and e2 are for the - original next face that we got. - */ - e3 = Get_EdgeEx(&e1,&e2,face->pPolygon,next_face_id,face->nPolSize,0,0); - } - - /* Find the other vertex to transmit in the triangle */ - e3 = Return_Other(face->pPolygon,e1,e2); - Last_Edge(&other1,&other2,&other3,0); - - if ((other1 != 0) && (other2 != 0)) - { - /* See which vertex in the output edge is not in the input edge */ - if ((e1 != other2) && (e1 != other3)) - e3 = e1; - else if ((e2 != other2) && (e2 != other3)) - e3 = e2; - /* can happen with > 2 polys on an edge but won't form a good strip so stop - the strip here - */ - else - { - Polygon_OutputEx(temp,face_id,0,pListHead,output,strips,ties,tie, - triangulate,swaps,next_id,where); - return; - } - - /* See which vertex of the input edge is not in the output edge */ - if ((other2 != e1) && (other2 != e2)) - { - other1 = other2; - other2 = other3; - } - else if ((other3 != e1) && (other3 != e2)) - other1 = other3; - else - { - /* Degenerate triangle just return*/ - Output_TriEx(other1,other2,e3,strips,next_face_id,begin,where); - RemoveList(pListHead,(PLISTINFO) temp); - begin = FALSE; - return; - } - - } - - /* There was not an input edge, we are the first triangle in a strip */ - else - { - /* Find the correct order to transmit the triangle, what is - the output edge that we want ? - */ - other1 = e3; - e3 = e2; - other2 = e1; - } - - /* At this point the adjacencies have been updated and we - have the next polygon id - */ - Output_TriEx(other1,other2,e3,strips,next_face_id,begin,where); - RemoveList(pListHead,(PLISTINFO) temp); - begin = FALSE; - - if (Done(next_face_id,59,&next_bucket) == NULL) - return; - - pListHead = array[next_bucket]; - pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) ); - if ( pfNode ) - pfNode->face_id = next_face_id; - lpListInfo = (P_ADJACENCIES) (SearchList(array[next_bucket], pfNode, - (int (*)(void *,void *)) (Compare))); - if (lpListInfo == NULL) - { - printf("There is an error finding the next polygon3 %d\n",next_face_id); - exit(0); - } - Polygon_OutputEx(lpListInfo,next_face_id,next_bucket, - pListHead, output, strips,ties,tie,triangulate,swaps,next_id,where); - - } -} - - else - { - /* It is not a triangle, we have to triangulate it . - Since it is not adjacent to anything we can triangulate it - blindly - */ - if (bucket == 0) - { - /* Check to see if there is not an input edge */ - Last_Edge(&other1,&other2,&other3,0); - if ((other1 == 0) && (other2 ==0)) - Blind_TriangulateEx(face->nPolSize,face->pPolygon, strips, - output,TRUE,where); - else - Blind_TriangulateEx(face->nPolSize,face->pPolygon,strips, - output,FALSE,where); - - RemoveList(pListHead,(PLISTINFO) temp); - /* We will be at the beginning of the next strip. */ - begin = TRUE; - } - - /* If we have specified PARTIAL triangulation then - we will go to special routines that will break the - polygon and update the data structure. Else everything - below will simply triangulate the whole polygon - */ - else if (triangulate == PARTIAL) - { - - /* Return the face_id of the next polygon we will be using, - */ - next_face_id = Min_Face_AdjEx(face_id,&next_bucket,ties); - - - /* Don't do it partially, because we can go inside and get - less adjacencies, for a quad we can do the whole thing. - */ - if ((face_id == next_face_id) && (face->nPolSize == 4) && (swaps == ON)) - { - next_face_id = Update_AdjacenciesEx(face_id, &next_bucket, &e1,&e2,ties); - if (next_face_id == -1) - { - /* There is no sequential face to go to, end the strip */ - Polygon_OutputEx(temp,face_id,0,pListHead,output,strips,ties,tie, - triangulate,swaps,next_id,where); - return; - } - - /* Break the tie, if there was one */ - if (tie != FIRST) - next_face_id = Get_Next_Face(tie,face_id,triangulate); - Non_Blind_TriangulateEx(face->nPolSize,face->pPolygon, strips, - output,next_face_id,face_id,where); - RemoveList(pListHead,(PLISTINFO) temp); - } - - /* Was not a quad but we still do not want to do it partially for - now, since we want to only do one triangle at a time - */ - else if ((face_id == next_face_id) && (swaps == ON)) - Inside_Polygon(face->nPolSize,face->pPolygon,strips,output, - next_face_id,face_id,next_id,pListHead,temp,where); - - else - { - if ((tie != FIRST) && (swaps == ON)) - next_face_id = Get_Next_Face(tie,face_id,triangulate); - Partial_Triangulate(face->nPolSize,face->pPolygon,strips, - output,next_face_id,face_id,next_id,pListHead,temp,where); - /* Check the next bucket again ,maybe it changed - We calculated one less, but that might not be the case - */ - } - - if (Done(next_face_id,59,&next_bucket) == NULL) - { - /* Check to see if there is not an input edge */ - Last_Edge(&other1,&other2,&other3,0); - if ((other1 == 0) && (other2 ==0)) - Blind_TriangulateEx(face->nPolSize,face->pPolygon, strips, - output,TRUE,where); - else - Blind_TriangulateEx(face->nPolSize,face->pPolygon,strips, - output,FALSE,where); - - if (Done(face_id,59,&bucket) != NULL) - { - pListHead = array[bucket]; - pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) ); - if ( pfNode ) - pfNode->face_id = face_id; - lpListInfo = (P_ADJACENCIES) (SearchList(array[bucket], pfNode, - (int (*)(void *,void *)) (Compare))); - RemoveList(pListHead,(PLISTINFO)lpListInfo); - } - begin = TRUE; - return; - } - - begin = FALSE; - pListHead = array[next_bucket]; - pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) ); - if ( pfNode ) - pfNode->face_id = next_face_id; - lpListInfo = (P_ADJACENCIES) (SearchList(array[next_bucket], pfNode, - (int (*)(void *,void *)) (Compare))); - if (lpListInfo == NULL) - { - printf("There is an error finding the next polygon1 %d %d\n",next_face_id,next_bucket); - exit(0); - } - Polygon_OutputEx(lpListInfo,next_face_id,next_bucket, - pListHead, output, strips,ties,tie,triangulate,swaps,next_id,where); - } - - - else - { - /* WHOLE triangulation */ - /* It is not a triangle and has adjacencies. - This means that we have to: - 1. TriangulateEx this polygon, not blindly because - we have an edge that we want to come out on, that - is the edge that is adjacent to a polygon with the - least number of adjacencies. Also we must come in - on the last seen edge. - 2. Update the adjacencies in the list, because we are - using this polygon . - 3. Get the next polygon. - */ - /* Return the face_id of the next polygon we will be using, - while updating the adjacency list by decrementing the - adjacencies of everything adjacent to the current polygon. - */ - - next_face_id = Update_AdjacenciesEx(face_id, &next_bucket, &e1,&e2,ties); - - if (Done(next_face_id,59,&next_bucket) == NULL) - { - Polygon_OutputEx(temp,face_id,0,pListHead,output,strips,ties,tie, - triangulate,swaps,next_id,where); - /* Because maybe there was more than 2 polygons on the edge */ - return; - } - - /* Break the tie, if there was one */ - else if (tie != FIRST) - next_face_id = Get_Next_Face(tie,face_id,triangulate); - - Non_Blind_TriangulateEx(face->nPolSize,face->pPolygon, strips, - output,next_face_id,face_id,where); - RemoveList(pListHead,(PLISTINFO) temp); - begin = FALSE; - pListHead = array[next_bucket]; - pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) ); - if ( pfNode ) - pfNode->face_id = next_face_id; - lpListInfo = (P_ADJACENCIES) (SearchList(array[next_bucket], pfNode, - (int (*)(void *,void *)) (Compare))); - if (lpListInfo == NULL) - { - printf("There is an error finding the next polygon2 %d %d\n",next_face_id,next_bucket); - exit(0); - } - Polygon_OutputEx(lpListInfo,next_face_id,next_bucket, - pListHead, output, strips,ties,tie,triangulate,swaps,next_id,where); - } - - } - Last_Edge(&e1,&e2,&e3,0); - -} - - - - - - - - diff --git a/Tools/Stripe_u/outputex.h b/Tools/Stripe_u/outputex.h deleted file mode 100644 index 68cff0ca2..000000000 --- a/Tools/Stripe_u/outputex.h +++ /dev/null @@ -1,23 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: outputex.h ------------------------------------------------------------------------*/ - - -#define TRIANGLE 3 -#define MAGNITUDE 1000000 - -void Output_TriEx(); -void Sgi_Test(); -void Polygon_OutputEx(); -void Extend_BackwardsEx(); -void FinishedEx(); - - diff --git a/Tools/Stripe_u/partial.c b/Tools/Stripe_u/partial.c deleted file mode 100644 index 9afb03c19..000000000 --- a/Tools/Stripe_u/partial.c +++ /dev/null @@ -1,665 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: partial.c - This file contains routines that are used partial triangulation of polygons -*/ -/*---------------------------------------------------------------------*/ - -#include -#include -#include -#include "global.h" -#include "outputex.h" -#include "polvertsex.h" -#include "triangulatex.h" -#include "sturctsex.h" -#include "polverts.h" -#include "common.h" -#include "util.h" - -void P_Triangulate_Quad(int out_edge1,int out_edge2,int in_edge1, - int in_edge2,int size,int *index, - FILE *output,FILE *fp,int reversed,int face_id, - int *next_id,ListHead *pListHead, - P_ADJACENCIES temp, - int where) -{ - int vertex4,vertex5,dummy=60; - - /* This routine will nonblindly triangulate a quad, meaning - that there is a definite input and a definite output - edge that we must adhere to. Reversed will tell the orientation - of the input edge. (Reversed is -1 is we do not have an input - edge, in other words we are at the beginning of a strip.) - Out_edge* is the output edge, and in_edge* is the input edge. - Index are the edges of the polygon - and size is the size of the polygon. Begin is whether we are - at the start of a new strip. - Note that we will not necessarily triangulate the whole quad; - maybe we will do half and leave the other half (a triangle) - for later. - */ - - - /* If we do not have an input edge, then we can make our input - edge whatever we like, therefore it will be easier to come - out on the output edge. In this case the whole quad is done. - */ - if (reversed == -1) - { - vertex4 = AdjacentEx(out_edge1,out_edge2,index,size); - vertex5 = Get_Other_Vertex(vertex4,out_edge1,out_edge2,index); - Output_TriEx(vertex5,vertex4,out_edge1,output,-1,-1,where); - Output_TriEx(vertex4,out_edge1,out_edge2,output,-1,-1,where); - dummy = Update_AdjacenciesEx(face_id, &dummy, &dummy,&dummy,&dummy); - RemoveList(pListHead,(PLISTINFO) temp); - return; - } - - /* These are the 5 cases that we can have for the output edge */ - - /* Are they consecutive so that we form a triangle to - peel off, but cannot use the whole quad? - */ - - if (in_edge2 == out_edge1) - { - /* Output the triangle that comes out the correct - edge. Save the other half for later. - */ - vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge2,index); - Output_TriEx(in_edge1,in_edge2,out_edge2,output,-1,-1,where); - /* Now we have a triangle used, and a triangle that is - left for later. - */ - - /* Now delete the adjacencies by one for all the faces - that are adjacent to the triangle that we just outputted. - */ - Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy, - face_id,&dummy,&dummy,&dummy); - Delete_AdjEx(out_edge2,in_edge2,&dummy,&dummy, - face_id,&dummy,&dummy,&dummy); - /* Put the new face in the proper bucket of adjacencies - There are 2 edges that need to be checked for the triangle - that was just outputted. For the output edge we definitely - will be decreasing the adjacency, but we must check for the - input edge. - */ - - dummy = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp,FALSE); - dummy = Change_FaceEx(face_id,in_edge2,out_edge2,pListHead,temp,TRUE); - - /* Update the face data structure, by deleting the old - face and putting in the triangle as the new face - */ - New_Face(face_id,in_edge1,out_edge2,vertex4); - return; - } - else if (in_edge1 == out_edge1) - { - /* We want to output the first triangle (whose output - edge is not the one that we want. - We have to find the vertex that we need, which is - the other vertex which we do not have. - */ - vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge2,index); - Output_TriEx(in_edge2,in_edge1,out_edge2,output,-1,-1,where); - /* Now we have a triangle used, and a triangle that is - left for later. - */ - - /* Now delete the adjacencies by one for all the faces - that are adjacent to the triangle that we just outputted. - */ - Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id, - &dummy,&dummy,&dummy); - Delete_AdjEx(out_edge2,out_edge1,&dummy,&dummy, - face_id,&dummy,&dummy,&dummy); - - /* Put the new face in the proper bucket of adjacencies */ - dummy = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp,FALSE); - dummy = Change_FaceEx(face_id,in_edge1,out_edge2,pListHead,temp,TRUE); - - /* Update the face data structure, by deleting the old - face and putting in the triangle as the new face - */ - New_Face(face_id,in_edge2,out_edge2,vertex4); - return; - } - - /* Consecutive cases again, but with the output edge reversed */ - else if (in_edge1 == out_edge2) - { - vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge1,index); - Output_TriEx(in_edge2,in_edge1,out_edge1,output,-1,-1,where); - /* Now we have a triangle used, and a triangle that is - left for later. - */ - - /* Now delete the adjacencies by one for all the faces - that are adjacent to the triangle that we just outputted. - */ - Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id, - &dummy,&dummy,&dummy); - Delete_AdjEx(out_edge2,out_edge1,&dummy,&dummy, - face_id,&dummy,&dummy,&dummy); - - /* Put the new face in the proper bucket of adjacencies */ - dummy = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp,FALSE); - dummy = Change_FaceEx(face_id,out_edge1,out_edge2,pListHead,temp,TRUE); - - /* Update the face data structure, by deleting the old - face and putting in the triangle as the new face - */ - New_Face(face_id,in_edge2,out_edge1,vertex4); - return; - } - else if (in_edge2 == out_edge2) - { - vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge1,index); - Output_TriEx(in_edge1,in_edge2,out_edge1,output,-1,-1,where); - /* Now we have a triangle used, and a triangle that is - left for later. - */ - /* Now delete the adjacencies by one for all the faces - that are adjacent to the triangle that we just outputted. - */ - Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id, - &dummy,&dummy,&dummy); - Delete_AdjEx(out_edge2,out_edge1,&dummy,&dummy, - face_id,&dummy,&dummy,&dummy); - - /* Put the new face in the proper bucket of adjacencies */ - dummy = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp,FALSE); - dummy = Change_FaceEx(face_id,out_edge1,out_edge2,pListHead,temp,TRUE); - - /* Update the face data structure, by deleting the old - face and putting in the triangle as the new face - */ - New_Face(face_id,in_edge1,out_edge1,vertex4); - return; - } - - /* The final case is where we want to come out the opposite - edge. - */ - else - { - if( ((!reversed) && (out_edge1 == (AdjacentEx(in_edge1,in_edge2,index,size)))) || - ((reversed) && (out_edge2 == (AdjacentEx(in_edge2,in_edge1,index,size))))) - { - /* We need to know the orientation of the input - edge, so we know which way to put the diagonal. - And also the output edge, so that we triangulate - correctly. Does not need partial. - */ - Output_TriEx(in_edge1,in_edge2,out_edge2,output,-1,-1,where); - Output_TriEx(in_edge2,out_edge2,out_edge1,output,-1,-1,where); - dummy = Update_AdjacenciesEx(face_id, &dummy, &dummy,&dummy,&dummy); - RemoveList(pListHead,(PLISTINFO) temp); - } - else - { - /* Input and output orientation was reversed, so diagonal will - be reversed from above. - */ - Output_TriEx(in_edge1,in_edge2,out_edge1,output,-1,-1,where); - Output_TriEx(in_edge2,out_edge1,out_edge2,output,-1,-1,where); - dummy = Update_AdjacenciesEx(face_id, &dummy, &dummy,&dummy,&dummy); - RemoveList(pListHead,(PLISTINFO) temp); - } - return; - } -} - -void P_Triangulate_Polygon(int out_edge1,int out_edge2,int in_edge1, - int in_edge2,int size, - int *index,FILE *output,FILE *fp, - int reversed,int face_id,int *next_id, - ListHead *pListHead, P_ADJACENCIES temp2, - int where) -{ - /* We have a polygon greater than 4 sides, which we wish - to partially triangulate - */ - int next_bucket,vertex4,dummy = 60; - int *temp; - P_ADJACENCIES pfNode; - - - /* Since we are calling this recursively, we have to check whether - we are down to the case of the quad. - */ - if (size == 4) - { - P_Triangulate_Quad(out_edge1,out_edge2,in_edge1,in_edge2,size, - index,output,fp,reversed,face_id,next_id, - pListHead,temp2,where); - return; - } - - /* We do not have a specified input edge, and therefore we - can make it anything we like, as long as we still come out - the output edge that we want. - */ - if (reversed == -1) - { - /* Get the vertex for the last triangle, which is - the one coming out the output edge, before we do - any deletions to the list. We will be doing this - bottom up. - */ - vertex4 = AdjacentEx(out_edge1,out_edge2,index,size); - temp = (int *) malloc(sizeof(int) * size); - memcpy(temp,index,sizeof(int)*size); - Delete_From_ListEx(out_edge2,index,size); - /* We do not have to partially triangulate, since - we will do the whole thing, so use the whole routine - */ - Triangulate_PolygonEx(vertex4,out_edge1,in_edge2, - vertex4,size-1,index,output,fp,reversed,face_id, - next_id,pListHead,temp2,where); - memcpy(index,temp,sizeof(int)*size); - /* Lastly do the triangle that comes out the output - edge. - */ - Output_TriEx(vertex4,out_edge1,out_edge2,output,-1,-1,where); - /* We were able to do the whole polygon, now we - can delete the whole thing from our data structure. - */ - dummy = Update_AdjacenciesEx(face_id, &dummy, &dummy,&dummy,&dummy); - RemoveList(pListHead,(PLISTINFO) temp2); - return; - } - - /* These are the 5 cases that we can have for the output edge */ - - /* Are they consecutive so that we form a triangle to - peel off that comes out the correct output edge, - but we cannot use the whole polygon? - */ - if (in_edge2 == out_edge1) - { - Output_TriEx(in_edge1,out_edge1,out_edge2,output,-1,-1,where); - - /* Now delete the adjacencies by one for all the faces - that are adjacent to the triangle that we just outputted. - */ - Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id, - &dummy,&dummy,&dummy); - Delete_AdjEx(out_edge2,out_edge1,&dummy,&dummy, - face_id,&dummy,&dummy,&dummy); - - /* Put the new face in the proper bucket of adjacencies */ - next_bucket = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE); - next_bucket = Change_FaceEx(face_id,out_edge1,out_edge2,pListHead,temp2,TRUE); - - /* Create a new edgelist without the triangle that - was just outputted. - */ - Delete_From_ListEx(in_edge2,index,size); - /* Update the face data structure, by deleting the old - face and putting in the polygon minus the triangle - as the new face, here we will be decrementing the size - by one. - */ - New_Size_Face(face_id); - return; - } - - /* Next case is where it is again consecutive, but the triangle - formed by the consecutive edges do not come out of the - correct output edge. (the input edge will be reversed in - the next triangle) - */ - else if (in_edge1 == out_edge1) - { - /* Get vertex adjacent to in_edge2, but is not in_edge1 */ - Output_TriEx(in_edge2,in_edge1,out_edge2,output,-1,-1,where); - - /* Now delete the adjacencies by one for all the faces - that are adjacent to the triangle that we just outputted. - */ - Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id, - &dummy,&dummy,&dummy); - Delete_AdjEx(out_edge2,out_edge1,&dummy,&dummy, - face_id,&dummy,&dummy,&dummy); - - /* Put the new face in the proper bucket of adjacencies */ - next_bucket = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE); - next_bucket = Change_FaceEx(face_id,out_edge1,out_edge2,pListHead,temp2,TRUE); - - /* Create a new edgelist without the triangle that - was just outputted. - */ - Delete_From_ListEx(in_edge1,index,size); - /* Update the face data structure, by deleting the old - face and putting in the polygon minus the triangle - as the new face, here we will be decrementing the size - by one. - */ - New_Size_Face(face_id); - return; - } - - /* Consecutive cases again, but with the output edge reversed */ - else if (in_edge1 == out_edge2) - { - Output_TriEx(in_edge2,in_edge1,out_edge1,output,-1,-1,where); - - /* Now delete the adjacencies by one for all the faces - that are adjacent to the triangle that we just outputted. - */ - Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id, - &dummy,&dummy,&dummy); - Delete_AdjEx(out_edge1,out_edge2,&dummy,&dummy, - face_id,&dummy,&dummy,&dummy); - - /* Put the new face in the proper bucket of adjacencies */ - next_bucket = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE); - next_bucket = Change_FaceEx(face_id,out_edge1,out_edge2,pListHead,temp2,TRUE); - - /* Create a new edgelist without the triangle that - was just outputted. - */ - Delete_From_ListEx(in_edge1,index,size); - /* Update the face data structure, by deleting the old - face and putting in the polygon minus the triangle - as the new face, here we will be decrementing the size - by one. - */ - New_Size_Face(face_id); - return; - } - else if (in_edge2 == out_edge2) - { - Output_TriEx(in_edge1,in_edge2,out_edge1,output,-1,-1,where); - - /* Now delete the adjacencies by one for all the faces - that are adjacent to the triangle that we just outputted. - */ - Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id, - &dummy,&dummy,&dummy); - Delete_AdjEx(out_edge2,out_edge1,&dummy,&dummy, - face_id,&dummy,&dummy,&dummy); - - /* Put the new face in the proper bucket of adjacencies */ - next_bucket = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE); - next_bucket = Change_FaceEx(face_id,out_edge1,out_edge2,pListHead,temp2,TRUE); - - /* Create a new edgelist without the triangle that - was just outputted. - */ - Delete_From_ListEx(in_edge2,index,size); - /* Update the face data structure, by deleting the old - face and putting in the polygon minus the triangle - as the new face, here we will be decrementing the size - by one. - */ - New_Size_Face(face_id); - return; - } - - /* Else the edge is not consecutive, and it is sufficiently - far away, for us not to make a conclusion at this time. - So we can take off a triangle and recursively call this - function. - */ - else - { - if (!reversed) - { - vertex4 = AdjacentEx(in_edge2,in_edge1,index,size); - Output_TriEx(in_edge1,in_edge2,vertex4,output,-1,-1,where); - - /* Now delete the adjacencies by one for all the faces - that are adjacent to the triangle that we just outputted. - */ - Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id, - &dummy,&dummy,&dummy); - Delete_AdjEx(in_edge1,vertex4,&dummy,&dummy, - face_id,&dummy,&dummy,&dummy); - - /* Put the new face in the proper bucket of adjacencies */ - next_bucket = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE); - next_bucket = Change_FaceEx(face_id,in_edge1,vertex4,pListHead,temp2,FALSE); - - /* Create a new edgelist without the triangle that - was just outputted. - */ - Delete_From_ListEx(in_edge1,index,size); - /* Update the face data structure, by deleting the old - face and putting in the polygon minus the triangle - as the new face, here we will be decrementing the size - by one. - */ - New_Size_Face(face_id); - - /* Save the info for the new bucket, we will need it on - the next pass for the variables, pListHead and temp - */ - pListHead = array[next_bucket]; - pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) ); - if ( pfNode ) - pfNode->face_id = face_id; - temp2 = (P_ADJACENCIES) (SearchList(array[next_bucket], pfNode, - (int (*)(void *,void *)) (Compare))); - if (temp2 == NULL) - { - printf("There is an error finding the next polygon10\n",next_bucket,face_id); - exit(0); - } - - P_Triangulate_Polygon(out_edge1,out_edge2,in_edge2, - vertex4,size-1,index,output,fp,!reversed, - face_id,next_id,pListHead,temp2,where); - } - else - { - vertex4 = AdjacentEx(in_edge1,in_edge2,index,size); - Output_TriEx(in_edge2,in_edge1,vertex4,output,-1,-1,where); - - /* Now delete the adjacencies by one for all the faces - that are adjacent to the triangle that we just outputted. - */ - Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id, - &dummy,&dummy,&dummy); - Delete_AdjEx(in_edge2,vertex4,&dummy,&dummy, - face_id,&dummy,&dummy,&dummy); - - /* Put the new face in the proper bucket of adjacencies */ - next_bucket = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE); - next_bucket = Change_FaceEx(face_id,in_edge2,vertex4,pListHead,temp2,FALSE); - - /* Create a new edgelist without the triangle that - was just outputted. - */ - Delete_From_ListEx(in_edge2,index,size); - - /* Update the face data structure, by deleting the old - face and putting in the polygon minus the triangle - as the new face, here we will be decrementing the size - by one. - */ - New_Size_Face(face_id); - - /* Save the info for the new bucket, we will need it on - the next pass for the variables, pListHead and temp - */ - pListHead = array[next_bucket]; - pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) ); - if ( pfNode ) - pfNode->face_id = face_id; - temp2 = (P_ADJACENCIES) (SearchList(array[next_bucket], pfNode, - (int (*)(void *,void *)) (Compare))); - if (temp2 == NULL) - { - printf("There is an error finding the next polygon11 %d %d\n",face_id,next_bucket); - exit(0); - } - - P_Triangulate_Polygon(out_edge1,out_edge2,vertex4, - in_edge1,size-1,index,output,fp,!reversed, - face_id,next_id,pListHead,temp2,where); - } - return; - } -} - -void P_Triangulate(int out_edge1,int out_edge2,int in_edge1, - int in_edge2,int size,int *index, - FILE *fp,FILE *output,int reversed,int face_id, - int *next_id,ListHead *pListHead, - P_ADJACENCIES temp,int where) -{ - - if (size == 4) - P_Triangulate_Quad(out_edge1,out_edge2,in_edge1,in_edge2,size, - index,fp,output,reversed,face_id,next_id,pListHead, temp,where); - else - P_Triangulate_Polygon(out_edge1,out_edge2,in_edge1,in_edge2,size, - index,fp,output,reversed,face_id,next_id,pListHead,temp,where); -} - - void Partial_Triangulate(int size,int *index, FILE *fp, - FILE *output,int next_face_id,int face_id, - int *next_id,ListHead *pListHead, - P_ADJACENCIES temp, int where) -{ - int id1,id2,id3; - int nedge1,nedge2; - int reversed; - - /* We have a polygon that has to be triangulated and we cannot - do it blindly, ie we will try to come out on the edge that - has the least number of adjacencies, But also we do not - want to triangulate the whole polygon now, so that means - we will output the least number of triangles that we can - and then update the data structures, with the polygon - that is left after we are done. - */ - Last_Edge(&id1,&id2,&id3,0); - - /* Find the edge that is adjacent to the new face , - also return whether the orientation is reversed in the - face of the input edge, which is id2 and id3. - */ - reversed = Get_EdgeEx(&nedge1,&nedge2,index,next_face_id,size,id2,id3); - - /* Input edge and output edge can be the same if there are more than - one polygon on an edge - */ - if ( ((nedge1 == id2) && (nedge2 == id3)) || - ((nedge1 == id3) && (nedge2 == id2)) ) - /* Set output edge arbitrarily but when come out of here the - next face will be on the old output edge (identical one) - */ - nedge2 = Return_Other(index,id2,id3); - - /* Do the triangulation */ - P_Triangulate(nedge1,nedge2,id2,id3,size,index,fp,output,reversed, - face_id,next_id,pListHead,temp,where); -} - - void Input_Edge(int face_id, int *index, int size, int in_edge1, int in_edge2, - FILE *fp, FILE *output,ListHead *pListHead, P_ADJACENCIES temp2, - int where) - { - /* The polygon had an input edge, specified by input1 and input2 */ - - int output1,next_bucket; - int vertex4, vertex5,dummy=60; - - output1 = Get_Output_Edge(face_id,size,index,in_edge1,in_edge2); - vertex5 = AdjacentEx(in_edge2,in_edge1,index,size); - vertex4 = AdjacentEx(in_edge1,in_edge2,index,size); - - if (vertex4 == output1) - { - Output_TriEx(in_edge2,in_edge1,output1,output,-1,-1,where); - /* Now delete the adjacencies by one for all the faces - that are adjacent to the triangle that we just outputted. - */ - Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id, - &dummy,&dummy,&dummy); - Delete_AdjEx(in_edge2,output1,&dummy,&dummy, - face_id,&dummy,&dummy,&dummy); - /* Put the new face in the proper bucket of adjacencies */ - next_bucket = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE); - next_bucket = Change_FaceEx(face_id,in_edge2,output1,pListHead,temp2,FALSE); - - /* Create a new edgelist without the triangle that - was just outputted. - */ - Delete_From_ListEx(in_edge2,index,size); - - } - else if (vertex5 == output1) - { - Output_TriEx(in_edge1,in_edge2,vertex5,output,-1,-1,where); - /* Now delete the adjacencies by one for all the faces - that are adjacent to the triangle that we just outputted. - */ - Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id, - &dummy,&dummy,&dummy); - Delete_AdjEx(in_edge1,vertex5,&dummy,&dummy, - face_id,&dummy,&dummy,&dummy); - /* Put the new face in the proper bucket of adjacencies */ - next_bucket = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE); - next_bucket = Change_FaceEx(face_id,in_edge1,vertex5,pListHead,temp2,FALSE); - - /* Create a new edgelist without the triangle that - was just outputted. - */ - Delete_From_ListEx(in_edge1,index,size); - } - - /* Update the face data structure, by deleting the old - face and putting in the polygon minus the triangle - as the new face, here we will be decrementing the size - by one. - */ - New_Size_Face(face_id); - return; - } - - void Inside_Polygon(int size,int *index,FILE *fp,FILE *output, - int next_face_id,int face_id,int *next_id, - ListHead *pListHead,P_ADJACENCIES temp, int where) - { - /* We know that we have a polygon that is greater than 4 sides, and - that it is better for us to go inside the polygon for the next - one, since inside will have less adjacencies than going outside. - So, we are not doing partial for a part of the polygon. - */ - int id1,id2,id3; - int new1,new2; - - Last_Edge(&id1,&id2,&id3,0); - - /* See if the input edge existed in the polygon, that will help us */ - if (Exist(face_id,id2,id3)) - Input_Edge(face_id,index,size,id2,id3,output,fp,pListHead,temp,where); - else - { - /* Make one of the input edges - We will choose it by trying to get an edge that has something - in common with the last triangle, or by getting the edge that - is adjacent to the least number of thigs, with preference given - to the first option - */ - - Get_Input_Edge(index,id1,id2,id3,&new1,&new2,size,face_id); - Input_Edge(face_id,index,size,new1,new2,output,fp,pListHead,temp,where); - } - } - - diff --git a/Tools/Stripe_u/partial.h b/Tools/Stripe_u/partial.h deleted file mode 100644 index c9a9439c8..000000000 --- a/Tools/Stripe_u/partial.h +++ /dev/null @@ -1,15 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: partial.h ------------------------------------------------------------------------*/ - -void Partial_Triangulate(); -void Inside_Polygon(); - diff --git a/Tools/Stripe_u/polverts.h b/Tools/Stripe_u/polverts.h deleted file mode 100644 index 79ece86db..000000000 --- a/Tools/Stripe_u/polverts.h +++ /dev/null @@ -1,87 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: polverts.h ------------------------------------------------------------------------*/ - -#include "queue.h" -#include - - -/* external functions */ -void Find_Adjacencies(); -void Test_Adj_Struct(); -void Test_SGI_Struct(); -void Write_Edges(); -void Build_SGI_Table(); -void Save_Walks(); -void Find_Bands(); -void Save_Rest(); -void Assign_Walk(); -void Save_Walks(); - -typedef struct adjacencies -{ - Node ListNode; - int face_id; -} ADJACENCIES,*P_ADJACENCIES; - -typedef struct FVerts -{ - Node ListNode; - int *pPolygon; - int nPolSize; - int nId; -} F_VERTS, *PF_VERTS; - -/*Every time we need to use this, cast it ( ListInfo*)*/ - -typedef struct FEdges -{ - Node ListNode; - int edge[3]; -}F_EDGES,*PF_EDGES; - -typedef struct FFaces -{ - Node ListNode; - int *pPolygon; - int *pNorms; - int seen; - int seen2; - int seen3; - int nPolSize; - F_EDGES **VertandId; - int *marked; - int *walked; -} F_FACES,*PF_FACES; - - -typedef struct Strips -{ - Node ListNode; - int face_id; -} Strips,*P_STRIPS; - - - struct vert_added - { - int num; - int *normal; - }; - - -/* Globals */ -ListHead **PolVerts; -ListHead **PolFaces; -ListHead **PolEdges; -ListHead *array[60]; -int id_array[60]; -ListHead *strips[1]; -ListHead *all_strips[100000]; /* Assume max 100000 strips */ diff --git a/Tools/Stripe_u/polvertsex.h b/Tools/Stripe_u/polvertsex.h deleted file mode 100644 index 8e05a7dd3..000000000 --- a/Tools/Stripe_u/polvertsex.h +++ /dev/null @@ -1,34 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: polvertsex.h ------------------------------------------------------------------------*/ - -#include "queue.h" -#include - - -/* external functions */ -void Start_Vert_Struct(); -void Start_Face_StructEx(); -void Start_Edge_StructEx(); -void AddNewNode(); -void AddNewFaceEx(); -void Find_AdjacenciesEx(); -void Test_Adj_Struct(); -void Test_SGI_Struct(); -void Write_Edges(); -void End_Verts_Struct(); -void End_Face_StructEx(); -void End_Edge_StructEx(); -void Build_SGI_TableEx(); -void Add_AdjEdgeEx(); - - - diff --git a/Tools/Stripe_u/queue.c b/Tools/Stripe_u/queue.c deleted file mode 100644 index 29d5e9de0..000000000 --- a/Tools/Stripe_u/queue.c +++ /dev/null @@ -1,226 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: queue.c - This file contains the routines used in the data structures lists, which - are queues. -*/ -/*---------------------------------------------------------------------*/ - - #include "queue.h" - - - -/*---------------------------------------------------------------------------- - * InitList: - */ -BOOL InitList (PLISTHEAD LHead) - -{ - if (LHead == NULL) return(FALSE); - - LHead->LHeaders[LISTHEAD] = LHead->LHeaders[LISTTAIL] = NULL; - LHead->NumList = 0; - return(TRUE); -} - -/*---------------------------------------------------------------------------- - * AddHead: - */ -BOOL AddHead(PLISTHEAD LHead, PLISTINFO LInfo) -{ - if (LHead == NULL || LInfo == NULL) - return(FALSE); - if (EMPTYLIST(LHead)) - LHead->LHeaders[LISTTAIL] = LInfo; - else LHead->LHeaders[LISTHEAD]->ListNode.Previous = (void *) LInfo; - - LInfo->ListNode.Next = (void *) LHead->LHeaders[LISTHEAD]; - LHead->LHeaders[LISTHEAD] = LInfo; - LInfo->ListNode.Previous = NULL; - LHead->NumList++; - return(TRUE); -} - -/*---------------------------------------------------------------------------- - * AddTail - */ -BOOL AddTail(PLISTHEAD LHead, PLISTINFO LInfo) -{ - if (LHead == NULL || LInfo == NULL) - return(FALSE); - if (EMPTYLIST(LHead)) - LHead->LHeaders[LISTHEAD] = LInfo; - else LHead->LHeaders[LISTTAIL]->ListNode.Next = (void *) LInfo; - - LInfo->ListNode.Previous = (void *) LHead->LHeaders[LISTTAIL]; - LHead->LHeaders[LISTTAIL] = LInfo; - LInfo->ListNode.Next = NULL; - LHead->NumList++; - return(TRUE); -} - - -BOOL InsertNode( PLISTHEAD LHead, int nPos, PLISTINFO LInfo ) -{ -PLISTINFO LAddNode; - - if ( LHead == NULL || LInfo == NULL || nPos > NumOnList( LHead ) ) - return( FALSE ); - - if ( nPos == 0 ) - AddHead( LHead, LInfo ); - else if ( nPos == NumOnList( LHead ) ) - AddTail( LHead, LInfo ); - else - { - if ( (LAddNode = PeekList( LHead, LISTHEAD, nPos - 1 )) == NULL ) - return( FALSE ); - - ((PLISTINFO)LAddNode->ListNode.Next)->ListNode.Previous = LInfo; - LInfo->ListNode.Next = LAddNode->ListNode.Next; - LInfo->ListNode.Previous = LAddNode; - LAddNode->ListNode.Next = LInfo; - - LHead->NumList++; - } - - return( TRUE ); -} - - - - -/*---------------------------------------------------------------------------- - * RemHead: - */ -PLISTINFO RemHead(PLISTHEAD LHead) -{ - PLISTINFO t, t1; - - if ( LHead == NULL || EMPTYLIST(LHead) ) - return(NULL); - - t = LHead->LHeaders[LISTHEAD]; - LHead->LHeaders[LISTHEAD] = (PLISTINFO) t->ListNode.Next; - - if (LHead->LHeaders[LISTHEAD] != NULL) - { - t1 = (PLISTINFO) t->ListNode.Next; - t1->ListNode.Previous = NULL; - } - else - LHead->LHeaders[LISTTAIL] = NULL; - - LHead->NumList--; - - return(t); -} - -/*---------------------------------------------------------------------------- - * RemTail: - */ -PLISTINFO RemTail(PLISTHEAD LHead) -{ - PLISTINFO t, t1; - - if ( LHead == NULL || EMPTYLIST(LHead) ) - return(NULL); - - t = LHead->LHeaders[LISTTAIL]; - LHead->LHeaders[LISTTAIL] = (PLISTINFO) t->ListNode.Previous; - if (LHead->LHeaders[LISTTAIL] != NULL) - { - t1 = (PLISTINFO) t->ListNode.Previous; - t1->ListNode.Next = NULL; - } - else - LHead->LHeaders[LISTHEAD] = NULL; - - LHead->NumList--; - return(t); -} - -/*---------------------------------------------------------------------------- - * PeekList: - */ -PLISTINFO PeekList(PLISTHEAD LHead, int wch, int index ) -{ - PLISTINFO t; - - if (LHead == NULL) - return(NULL); - if ( (t = LHead->LHeaders[wch]) == NULL ) - return(NULL); - - for (; t != NULL && index > 0; index-- ) - t = (wch == LISTHEAD) ? (PLISTINFO) t->ListNode.Next : - (PLISTINFO) t->ListNode.Previous; - return(t); -} - - -/*---------------------------------------------------------------------------- - * RemoveList: - */ -PLISTINFO RemoveList( PLISTHEAD LHead, PLISTINFO LInfo ) -{ - PLISTINFO t, t1; - - t = LInfo; - if (LHead == NULL) - return(NULL); - if (LHead->LHeaders[LISTHEAD] == t) - t = (PLISTINFO) RemHead(LHead); - else if (LHead->LHeaders[LISTTAIL] == t) - t = (PLISTINFO) RemTail(LHead); - else - { - t1 = (PLISTINFO) t->ListNode.Previous; - t1->ListNode.Next = t->ListNode.Next; - t1 = (PLISTINFO) t->ListNode.Next; - t1->ListNode.Previous = t->ListNode.Previous; - LHead->NumList--; - } - - return(t); -} - -/*---------------------------------------------------------------------------- - * SearchList: - * Try to find a specific node in the queue whose key matches with - * searching key. Return the pointer to that node if found, return NULL - * otherwise - * - * Input: - * lpHashTbl => a far pointer to the hash table - * lpKey => a far poniter to searching key - * CompareCallBack => comparision function - * - * Output: a far pointer to the node to be found - * - */ -PLISTINFO SearchList( - PLISTHEAD lpListHead, - PVOID lpSKey, - int (* CompareCallBack) ( PVOID, PVOID ) ) -{ -PLISTINFO lpListInfo; - - lpListInfo = PeekList( lpListHead, LISTHEAD, 0); - while ( lpListInfo != NULL ) - { - if ( CompareCallBack( lpListInfo, lpSKey ) ) - break; - lpListInfo = GetNextNode( lpListInfo ); - } - - return( lpListInfo ); -} - diff --git a/Tools/Stripe_u/queue.h b/Tools/Stripe_u/queue.h deleted file mode 100644 index 0bf926e0f..000000000 --- a/Tools/Stripe_u/queue.h +++ /dev/null @@ -1,283 +0,0 @@ - -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE:queue.h ------------------------------------------------------------------------*/ - -#ifndef QUEUE_INCLUDED -#define QUEUE_INCLUDED - -/* %%s Node */ -/***************************************************************** - This structure is used to store the List linkage information of a -ListInfo structure. It contains all the necessary information for the -List functions to function properly. This structure must be the first -one defined in any block of memory to be linked with the List functions. -for an example of the used of The Node structure look in the files -ipd2dms.c and ipd2man.h -******************************************************************/ -#include -#define FALSE 0 -#define TRUE 1 -typedef struct -{ - void *Next; - void *Previous; -} - Node, * PNODE; - -/***************************************************************** - Next : is a pointer to the next structure in this List. - Previous : is a pointer to the previous structure in this List. - priority : this is the priority of this structure in the List. The - highest priority is 0. This field is only used by the - functions EnQue and DeQue. -******************************************************************/ -/* %%e */ - - -/* %%s ListInfo */ - -/***************************************************************** - This is the general means of linking application defined information into -Lists and queues. All structures must begin with the Node Structure. All -other data in the structure is user definable. -******************************************************************/ - -typedef struct List -{ - Node ListNode; /* link to the next Listinfo Structure */ - /* user definable data */ -} ListInfo, *PLISTINFO; - -/***************************************************************** - ListNode : this is the required node structure for the List - mainpulation functions. This must be the first - element of a user definable structure. - - In order for an application to use the List routines, it must define -a structure with all the needed information. The first element in the -user definable structure must be a Node structure. The Node structure -contains all the necessary information for the List routines to do their -magic. For an example of a user defined List structure see the file -ipd2i.h. The User definable structure can be passed to any List function -that excepts a pointer to a ListInfo structure. - -example: - -typedef mstruct -{ - Node ListNode; - int a,b,c,d,e,f,g; -} - mystruct; - - the user definable portion of the above structure is represented by -the integers a,b,c,d,e,f,g. When passing this structure to a List -function a cast of (ListInfo *) must be made to satisify the "C" complier. -******************************************************************/ -/* %%e */ - - -/* %%s ListHead */ -/***************************************************************** - ListHead is used as a header to a List. LHeaders[0] points to the -head of the List. LHeaders[1] points the tail of the list. When -accessing these variables use the defines LISTHEAD, LISTTAIL. -******************************************************************/ - -typedef struct LHead -{ - PLISTINFO LHeaders[2]; - int NumList; -} -ListHead, *PLISTHEAD; - -/***************************************************************** - LHeaders : this is an array of two pointers to ListInfo structures. - This information is used to point to the head and tail of - a list. - NumList : this integer hold the number of structures linked into this - list. - -ListHead #define: - - LISTHEAD : when Peeking down a list this specifies you should - start at the Head of the list and search downward. - - LISTTAIL : when Peeking down a list this specifies you should - start at the tail of the list and search foward. - ******************************************************************/ - -#define LISTHEAD 0 - -#define LISTTAIL 1 -/* %%e */ - -typedef int BOOL; -typedef void * PVOID; - -#define PEEKFROMHEAD( lh, ind ) ( PeekList( (lh), LISTHEAD, (ind) ) ) -#define PEEKFROMTAIL( lh, ind ) ( PeekList( (lh), LISTTAIL, (ind) ) ) -#define EMPTYLIST( lh ) ( ( (lh)->LHeaders[LISTHEAD] == NULL ) ) - -/* General utility routines */ -/* %%s QueRoutines */ -BOOL InitList ( PLISTHEAD ); - -/***************************************************************** - InitList : Initialize a new list structure for use with the List - routines - - INPUTS : LHead : a pointer to a ListHead structure. - OUTPUT : a boolean value TRUE if no errors occured FALSE - otherwise -******************************************************************/ - - -PLISTINFO PeekList ( PLISTHEAD, int, int ); - -/***************************************************************** - PeekList : This funciton peeks down a list for the N'th element - from the HEAD or TAIL of the list - - INPUTS : LHead : a pointer to a List head structure. - from : can either search from the HEAD or TAIL - of the list - where : how many nodes from the begining should the - List routines look. - OUTPUT : a pointer to a ListInfo structure identified by - from/where or NULL if an error occurred. -******************************************************************/ - - -PLISTINFO RemoveList( PLISTHEAD LHead, PLISTINFO LInfo ); - - -/***************************************************************** - RemoveList: Remove a ListInfo structure from a List. - - INPUTS : LHead : a pointer to a ListHead structure. - LInfo : a pointer to the ListInfo structure to remove - from the list. - OUTPUT : a pointer to the ListInfo structure that was removed or - NULL if an error occurred. -******************************************************************/ - -BOOL InsertNode( PLISTHEAD LHead, int nPos, PLISTINFO LInfo ); - -/***************************************************************** - InsertNode: add a node to a list after a given node - - INPUTS : LHead : a pointer to a ListHead structure. - nPos : the position to insert the node into - LInfo : a pointer to the new node to add to the list. - OUTPUT: a boolean value TRUE if all goes well false otherwise -*****************************************************************/ - -BOOL AddHead ( PLISTHEAD, PLISTINFO ); - -/***************************************************************** - AddHead : add a ListInfo structure to the HEAD of a list. - - INPUTS : LHead : a pointer to a ListHead structure of the list - to add to. - LInfo : a pointer to the ListInfo structure to add to - the list. - OUTPUT : A boolean value TRUE if no errors occurred FALSE - otherwise. -******************************************************************/ - - -BOOL AddTail ( PLISTHEAD, PLISTINFO ); - -/***************************************************************** - AddTail : Add a ListInfo structure to the TAIL of a list. - - INPUTS : LHead : a pointer to a ListHead structure of the List - to add to. - LInfo : a pointer to the ListInfo structure to add to - the List. - OUTPUT : a boolean value TRUE if no errors occurred FALSE - otherwise. -******************************************************************/ - - -PLISTINFO RemTail ( PLISTHEAD ); - -/***************************************************************** - RemTail : Remove a ListInfo structure from the TAIL of a List. - - INPUTS : LHead : a pointer to a ListHead structure of the List - to remove from. - OUTPUT : a pointer to the ListInfo structure that was removed - or NULL if an error occurred. -******************************************************************/ - - -PLISTINFO RemHead ( PLISTHEAD ); - -/***************************************************************** - RemHead : Remove a ListInfo structure from the Head of a List. - - INPUTS : LHead : a pointer to a ListHead structure of the List - to remove from. - OUTPUT : a pointer to the ListInfo structure that was removed or - NULL if an error occurred. -******************************************************************/ - -PLISTINFO SearchList( - PLISTHEAD lpListHead, - PVOID lpSKey, - int ( * CompareCallBack) ( PVOID, PVOID ) ); - -/***************************************************************** - SearchList: - Try to find a specific node in the queue whose key matches with - searching key. Return the pointer to that node if found, return NULL - otherwise - - Input: - lpHashTbl => a far pointer to the hash table - lpKey => a far poniter to searching key - CompareCallBack => comparision function - - Output: a far pointer to the node to be found - - ******************************************************************/ - -#define NumOnList(lh) ( ((lh)->NumList) ) - -/***************************************************************** - NumOnList: Returns the number of Nodes linked to a ListHead - structure. This number is maintained by the List - routines. -******************************************************************/ - -#define GetNextNode(pli) ( ((pli)->ListNode.Next) ) - -/******************************************************** - GetNextNode: This macro returns the Next Structure in this list. - This macro will return NULL if no more structures are - in the List. -*********************************************************/ - -#define GetPrevNode(pli) ( ((pli)->ListNode.Previous) ) - -/******************************************************** - GetPrevNode: This macro returns the Previous Structure in this list. - This macro will reutrn NULL if no more structures are - in the List. -********************************************************/ -/* %%e */ - -#endif - - diff --git a/Tools/Stripe_u/sgi_triang.c b/Tools/Stripe_u/sgi_triang.c deleted file mode 100644 index 40dff70f6..000000000 --- a/Tools/Stripe_u/sgi_triang.c +++ /dev/null @@ -1,631 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: sgi_triang.c - File contains the routines that do the whole triangulation - of polygons. -*/ -/*---------------------------------------------------------------------*/ - -#include -#include -#include -#include "global.h" -#include "output.h" -#include "polverts.h" -#include "sturcts.h" -#include "common.h" -#include "util.h" -#include "init.h" - -int Adjacent(int id2,int id1, int *list, int size) -{ - /* Return the vertex that is adjacent to id1, - but is not id2, in the list of integers. - */ - - register int x=0; - - while (x < size) - { - if (*(list+x) == id1) - { - if ((x != (size -1)) && (x != 0)) - { - if ( *(list+x+1) != id2) - return *(list+x+1); - else - return *(list+x-1); - } - else if (x == (size -1)) - { - if (*(list) != id2) - return *(list); - else - return *(list+x-1); - } - else - { - if (*(list+size-1) != id2) - return *(list+size-1); - else - return *(list+x+1); - } - } - x++; - } - /* if there are degeneracies */ - return id1; -} - - -void Rearrange_Index(int *index, int size) -{ - /* If we are in the middle of a strip we must find the - edge to start on, which is the last edge that we had - transmitted. - */ - int x,f,y,e1,e2,e3; - register int increment = 1; - int *temp; - - /* Find where the input edge is in the input list */ - Last_Edge(&e1,&e2,&e3,0); - for (y = 0; y < size; y++) - { - if (*(index+y) == e2) - { - if ((y != (size - 1)) && (*(index+y+1) == e3)) - break; - else if ((y == (size - 1)) && (*(index) == e3)) - break; - else if ((y != 0) && (*(index+y-1) == e3)) - { - increment = -1; - break; - } - else if ((y==0) && (*(index+size-1) == e3)) - { - increment = -1; - break; - } - } - if (*(index+y) == e3) - { - if ((y != (size - 1)) && (*(index+y+1) == e2)) - break; - else if ((y == (size - 1)) && (*(index) == e2)) - break; - else if ((y != 0) && (*(index+y-1) == e2)) - { - increment = -1; - break; - } - else if ((y==0) && (*(index+size-1) == e2)) - { - increment = -1; - break; - } - } - /* Edge is not here, we are at the beginning */ - if ((y == (size-1)) && (increment != -1)) - return; - } - - /* Now put the list into a new list, starting with the - input edge. Increment tells us whether we have to go - forward or backward. - */ - /* Was in good position already */ - if ((y == 0) && (increment == 1)) - return; - - temp = (int *) malloc(sizeof(int) * size); - memcpy(temp,index,sizeof(int)*size); - - if (increment == 1) - { - x=0; - for (f = y ; f< size; f++) - { - *(index+x) = *(temp+f); - x++; - } - /* Finish the rest of the list */ - for(f = 0; f < y ; f++) - { - *(index+x) = *(temp+f); - x++; - } - } - else - { - x=0; - for (f = y ; f >= 0; f--) - { - *(index+x) = *(temp+f); - x++; - } - /* Finish the rest of the list */ - for(f = (size - 1); f > y ; f--) - { - *(index+x) = *(temp+f); - x++; - } - } -} - -void Delete_From_List(int id,int *list, int *size) -{ - /* Delete the occurence of id in the list. - (list has size size) - */ - - int *temp; - register int x,y=0; - - temp = (int *) malloc(sizeof(int) * (*size)); - for (x=0; x<(*size); x++) - { - if (*(list+x) != id) - { - *(temp+y) = *(list+x); - y++; - } - } - *(temp+y) = -1; - *size = *size - (*size - y - 1); - memcpy(list,temp,sizeof(int)*(*size)); -} - - -void Build_SGI_Table(int num_verts,int num_faces) -{ - /* Build a table that has the polygons sorted by the - number of adjacent polygons. - */ - int x,y,size,tally=0; - ListHead *pListHead; - PF_FACES temp = NULL; - - /* For each face....*/ - for (x=0;x < num_faces;x++) - { - pListHead = PolFaces[x]; - temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); - /* Check each edge of the face and tally the number of adjacent - polygons to this face. - */ - if ( temp != NULL ) - { - /* Size of the polygon */ - size = temp->nPolSize; - if (size != 1) - { - for (y = 0; y< size; y++) - { - if (y != (size-1)) - tally += Num_Adj(*(temp->pPolygon+y),*(temp->pPolygon+y+1)); - else - tally += Num_Adj(*(temp->pPolygon),*(temp->pPolygon+(size-1))); - } - - /* Tally is the number of polygons that is adjacent to - the current polygon. - */ - /* Now put the face in the proper bucket depending on tally. */ - Add_Sgi_Adj(tally,x); - temp = NULL; - tally=0; - } - } - } -} - - -void Triangulate_Quad(int out_edge1,int out_edge2,int in_edge1, - int in_edge2,int size,int *index, - FILE *output,int reversed,int face_id, - int where,int color1,int color2,int color3) -{ - int vertex4,vertex5; - - /* This routine will nonblindly triangulate a quad, meaning - that there is a definite input and a definite output - edge that we must adhere to. Reversed will tell the orientation - of the input edge. (Reversed is -1 is we do not have an input - edge, in other words we are at the beginning of a strip.) - Out_edge* is the output edge, and in_edge* is the input edge. - Index are the edges of the polygon - and size is the size of the polygon. Begin is whether we are - at the start of a new strip. - */ - - /* If we do not have an input edge, then we can make our input - edge whatever we like, therefore it will be easier to come - out on the output edge. - */ - if (reversed == -1) - { - vertex4 = Adjacent(out_edge1,out_edge2,index,size); - vertex5 = Get_Other_Vertex(vertex4,out_edge1,out_edge2,index); - Output_Tri(vertex5,vertex4,out_edge1,output,color1,color2,color3,where); - Output_Tri(vertex4,out_edge1,out_edge2,output,color1,color2,color3,where); - return; - } - - /* These are the 5 cases that we can have for the output edge */ - - /* Are they consecutive so that we form a triangle to - peel off, but cannot use the whole quad? - */ - - if (in_edge2 == out_edge1) - { - /* Output the triangle that comes out the correct - edge last. First output the triangle that comes out - the wrong edge. - */ - vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge2,index); - Output_Tri(in_edge1,in_edge2,vertex4,output,color1,color2,color3,where); - Output_Tri(vertex4,in_edge2,out_edge2,output,color1,color2,color3,where); - return; - } - /* The next case is where it is impossible to come out the - edge that we want. So we will have to start a new strip to - come out on that edge. We will output the one triangle - that we can, and then start the new strip with the triangle - that comes out on the edge that we want to come out on. - */ - else if (in_edge1 == out_edge1) - { - /* We want to output the first triangle (whose output - edge is not the one that we want. - We have to find the vertex that we need, which is - the other vertex which we do not have. - */ - vertex4 = Get_Other_Vertex(in_edge2,in_edge1,out_edge2,index); - Output_Tri(in_edge2,in_edge1,vertex4,output,color1,color2,color3,where); - Output_Tri(vertex4,in_edge1,out_edge2,output,color1,color2,color3,where); - return; - } - - /* Consecutive cases again, but with the output edge reversed */ - else if (in_edge1 == out_edge2) - { - vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge1,index); - Output_Tri(in_edge2,in_edge1,vertex4,output,color1,color2,color3,where); - Output_Tri(vertex4,in_edge1,out_edge1,output,color1,color2,color3,where); - return; - } - else if (in_edge2 == out_edge2) - { - vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge1,index); - Output_Tri(in_edge1,in_edge2,vertex4,output,color1,color2,color3,where); - Output_Tri(vertex4,in_edge2,out_edge1,output,color1,color2,color3,where); - return; - } - - /* The final case is where we want to come out the opposite - edge. - */ - else - { - if( ((!reversed) && (out_edge1 == (Adjacent(in_edge1,in_edge2,index,size)))) || - ((reversed) && (out_edge2 == (Adjacent(in_edge2,in_edge1,index,size))))) - { - /* We need to know the orientation of the input - edge, so we know which way to put the diagonal. - And also the output edge, so that we triangulate - correctly. - */ - Output_Tri(in_edge1,in_edge2,out_edge2,output,color1,color2,color3,where); - Output_Tri(in_edge2,out_edge2,out_edge1,output,color1,color2,color3,where); - } - else - { - /* Input and output orientation was reversed, so diagonal will - be reversed from above. - */ - Output_Tri(in_edge1,in_edge2,out_edge1,output,color1,color2,color3,where); - Output_Tri(in_edge2,out_edge1,out_edge2,output,color1,color2,color3,where); - } - return; - } -} - -void Triangulate_Polygon(int out_edge1,int out_edge2,int in_edge1, - int in_edge2,int size,int *index, - FILE *output,int reversed,int face_id, - int where,int color1,int color2,int color3) -{ - /* We have a polygon that we need to nonblindly triangulate. - We will recursively try to triangulate it, until we are left - with a polygon of size 4, which can use the quad routine - from above. We will be taking off a triangle at a time - and outputting it. We will have 3 cases similar to the - cases for the quad above. The inputs to this routine - are the same as for the quad routine. - */ - - int vertex4; - int *temp; - - - /* Since we are calling this recursively, we have to check whether - we are down to the case of the quad. - */ - - if (size == 4) - { - Triangulate_Quad(out_edge1,out_edge2,in_edge1,in_edge2,size, - index,output,reversed,face_id,where,color1,color2,color3); - return; - } - - - - /* We do not have a specified input edge, and therefore we - can make it anything we like, as long as we still come out - the output edge that we want. - */ - if (reversed == -1) - { - /* Get the vertex for the last triangle, which is - the one coming out the output edge, before we do - any deletions to the list. We will be doing this - bottom up. - */ - vertex4 = Adjacent(out_edge1,out_edge2,index,size); - temp = (int *) malloc(sizeof(int) * size); - memcpy(temp,index,sizeof(int)*size); - Delete_From_List(out_edge2,index,&size); - Triangulate_Polygon(out_edge1,vertex4,in_edge2, - vertex4,size-1,index,output,reversed,face_id,where,color1,color2,color3); - memcpy(index,temp,sizeof(int)*size); - /* Lastly do the triangle that comes out the output - edge. - */ - Output_Tri(vertex4,out_edge1,out_edge2,output,color1,color2,color3,where,where); - return; - } - - /* These are the 5 cases that we can have for the output edge */ - - /* Are they consecutive so that we form a triangle to - peel off that comes out the correct output edge, - but we cannot use the whole polygon? - */ - if (in_edge2 == out_edge1) - { - /* Output the triangle that comes out the correct - edge last. First recursively do the rest of the - polygon. - */ - /* Do the rest of the polygon without the triangle. - We will be doing a fan triangulation. - */ - /* Get the vertex adjacent to in_edge1, but is not - in_edge2. - */ - vertex4 = Adjacent(in_edge2,in_edge1,index,size); - Output_Tri(in_edge1,in_edge2,vertex4,output,color1,color2,color3,where); - /* Create a new edgelist without the triangle that - was just outputted. - */ - temp = (int *) malloc(sizeof(int) * size); - memcpy(temp,index,sizeof(int)*size); - Delete_From_List(in_edge1,index,&size); - Triangulate_Polygon(out_edge1,out_edge2,in_edge2, - vertex4,size-1,index,output,!reversed,face_id,where,color1,color2,color3); - memcpy(index,temp,sizeof(int)*size); - return; - } - - /* Next case is where it is again consecutive, but the triangle - formed by the consecutive edges do not come out of the - correct output edge. For this case, we can not do much to - keep it sequential. Try and do the fan. - */ - else if (in_edge1 == out_edge1) - { - /* Get vertex adjacent to in_edge2, but is not in_edge1 */ - vertex4 = Adjacent(in_edge1,in_edge2,index,size); - Output_Tri(in_edge1,in_edge2,vertex4,output,color1,color2,color3,where,where); - /* Since that triangle goes out of the polygon (the - output edge of it), we can make our new input edge - anything we like, so we will try to make it good for - the strip. (This will be like starting a new strip, - all so that we can go out the correct output edge.) - */ - temp = (int *) malloc(sizeof(int) * size); - memcpy(temp,index,sizeof(int)*size); - Delete_From_List(in_edge2,index,&size); - Triangulate_Polygon(out_edge1,out_edge2,in_edge1, - vertex4,size-1,index,output,reversed,face_id,where,color1,color2,color3); - memcpy(index,temp,sizeof(int)*size); - return; - } - /* Consecutive cases again, but with the output edge reversed */ - else if (in_edge1 == out_edge2) - { - /* Get vertex adjacent to in_edge2, but is not in_edge1 */ - vertex4 = Adjacent(in_edge1,in_edge2,index,size); - Output_Tri(in_edge2,in_edge1,vertex4,output,color1,color2,color3,where,where); - temp = (int *) malloc(sizeof(int) * size); - memcpy(temp,index,sizeof(int)*size); - Delete_From_List(in_edge2,index,&size); - Triangulate_Polygon(out_edge1,out_edge2,in_edge1, - vertex4,size-1,index,output,reversed,face_id,where,color1,color2,color3); - memcpy(index,temp,sizeof(int)*size); - return; - } - else if (in_edge2 == out_edge2) - { - /* Get vertex adjacent to in_edge2, but is not in_edge1 */ - vertex4 = Adjacent(in_edge2,in_edge1,index,size); - Output_Tri(in_edge1,in_edge2,vertex4,output,color1,color2,color3,where,where); - temp = (int *) malloc(sizeof(int) * size); - memcpy(temp,index,sizeof(int)*size); - Delete_From_List(in_edge1,index,&size); - Triangulate_Polygon(out_edge1,out_edge2,vertex4, - in_edge2,size-1,index,output,reversed,face_id,where,color1,color2,color3); - memcpy(index,temp,sizeof(int)*size); - return; - } - - /* Else the edge is not consecutive, and it is sufficiently - far away, for us not to make a conclusion at this time. - So we can take off a triangle and recursively call this - function. - */ - else - { - vertex4 = Adjacent(in_edge2,in_edge1,index,size); - Output_Tri(in_edge1,in_edge2,vertex4,output,color1,color2,color3,where,where); - temp = (int *) malloc(sizeof(int) * size); - memcpy(temp,index,sizeof(int)*size); - Delete_From_List(in_edge1,index,&size); - Triangulate_Polygon(out_edge1,out_edge2,in_edge2, - vertex4,size-1,index,output,!reversed,face_id,where,color1,color2,color3); - memcpy(index,temp,sizeof(int)*size); - return; - } -} - -void Triangulate(int out_edge1,int out_edge2,int in_edge1, - int in_edge2,int size,int *index, - FILE *output,int reversed,int face_id, int where, - int color1, int color2,int color3) -{ - /* We have the info we need to triangulate a polygon */ - - if (size == 4) - Triangulate_Quad(out_edge1,out_edge2,in_edge1,in_edge2,size, - index,output,reversed,face_id,where,color1,color2,color3); - else - Triangulate_Polygon(out_edge1,out_edge2,in_edge1,in_edge2,size, - index,output,reversed,face_id,where,color1,color2,color3); -} - -void Non_Blind_Triangulate(int size,int *index, - FILE *output,int next_face_id,int face_id,int where, - int color1,int color2,int color3) -{ - int id1,id2,id3; - int nedge1,nedge2; - int reversed; - /* We have a polygon that has to be triangulated and we cannot - do it blindly, ie we will try to come out on the edge that - has the least number of adjacencies - */ - - Last_Edge(&id1,&id2,&id3,0); - /* Find the edge that is adjacent to the new face , - also return whether the orientation is reversed in the - face of the input edge, which is id2 and id3. - */ - if (next_face_id == -1) - { - printf("The face is -1 and the size is %d\n",size); - exit(0); - } - - reversed = Get_Edge(&nedge1,&nedge2,index,next_face_id,size,id2,id3); - /* Do the triangulation */ - - /* If reversed is -1, the input edge is not in the polygon, therefore we can have the - input edge to be anything we like, since we are at the beginning - of a strip - */ - Triangulate(nedge1,nedge2,id2,id3,size,index,output,reversed, - face_id, where,color1,color2,color3); -} - - - -void Blind_Triangulate(int size, int *index, FILE *output, - BOOL begin, int where ,int color1,int color2, - int color3) -{ - /* save sides in temp array, we need it so we know - about swaps. - */ - int mode, decreasing,increasing,e1,e2,e3; - int x = 0; - BOOL flag = FALSE; - - /* Rearrange the index list so that the input edge is first - */ - if (!begin) - Rearrange_Index(index,size); - - /* We are given a polygon of more than 3 sides - and want to triangulate it. We will output the - triangles to the output file. - */ - - /* Find where the input edge is in the input list */ - Last_Edge(&e1,&e2,&e3,0); - if (( (!begin) && (*(index) == e2) ) || (begin)) - { - Output_Tri(*(index+0),*(index+1),*(index+size-1),output,color1,color2,color3,where,where); - /* If we have a quad, (chances are yes), then we know that - we can just add one diagonal and be done. (divide the - quad into 2 triangles. - */ - if (size == 4) - { - Output_Tri(*(index+1),*(index+size-1),*(index+2),output,color1,color2,color3,where,where); - return; - } - increasing = 1; - mode = 1; - - } - else if (!begin) - { - Output_Tri(*(index+1),*(index+0),*(index+size-1),output,color1,color2,color3,where,where); - if (size == 4) - { - Output_Tri(*(index+0),*(index+size-1),*(index+2),output,color1,color2,color3,where,where); - return; - } - Output_Tri(*(index+0),*(index+size-1),*(index+2),output,color1,color2,color3,where,where); - increasing = 2; - mode = 0; - } - if (size != 4) - { - /* We do not have a quad, we have something bigger. */ - decreasing = size - 1; - do - { - /* Will be alternating diagonals, so we will be increasing - and decreasing around the polygon. - */ - if (mode) - { - Output_Tri(*(index+increasing),*(index+decreasing),*(index+increasing+1),output,color1,color2,color3,where,where); - increasing++; - } - else - { - Output_Tri(*(index+decreasing),*(index+increasing),*(index+decreasing-1),output,color1,color2,color3,where,where); - decreasing--; - } - mode = !mode; - } while ((decreasing - increasing) >= 2); - - } -} - - - - diff --git a/Tools/Stripe_u/sgi_triangex.c b/Tools/Stripe_u/sgi_triangex.c deleted file mode 100644 index afa2fd7db..000000000 --- a/Tools/Stripe_u/sgi_triangex.c +++ /dev/null @@ -1,584 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: sgi_triangex.c - This file contains routines that are used for various functions in - the local algorithm. -*/ -/*---------------------------------------------------------------------*/ - -#include -#include -#include -#include "global.h" -#include "outputex.h" -#include "polverts.h" -#include "sturctsex.h" -#include "common.h" -#include "util.h" - - -int AdjacentEx(int id2,int id1, int *list, int size) -{ - /* Return the vertex that is adjacent to id1, - but is not id2, in the list of integers. - */ - - register int x=0; - - while (x < size) - { - if (*(list+x) == id1) - { - if ((x != (size -1)) && (x != 0)) - { - if ( *(list+x+1) != id2) - return *(list+x+1); - else - return *(list+x-1); - } - else if (x == (size -1)) - { - if (*(list) != id2) - return *(list); - else - return *(list+x-1); - } - else - { - if (*(list+size-1) != id2) - return *(list+size-1); - else - return *(list+x+1); - } - } - x++; - } - printf("Error in the list\n"); - exit(0); -} - - -void Delete_From_ListEx(int id,int *list, int size) -{ - /* Delete the occurence of id in the list. - (list has size size) - */ - - int *temp; - register int x,y=0; - - temp = (int *) malloc(sizeof(int) * size); - for (x=0; x= 0; f--) - { - *(index+x) = *(temp+f); - x++; - } - /* Finish the rest of the list */ - for(f = (size - 1); f > y ; f--) - { - *(index+x) = *(temp+f); - x++; - } - } -} - -void Blind_TriangulateEx(int size, int *index, FILE *fp, - FILE *output, BOOL begin, int where ) -{ - /* save sides in temp array, we need it so we know - about swaps. - */ - int mode, decreasing,increasing,e1,e2,e3; - int x = 0; - BOOL flag = FALSE; - - /* Rearrange the index list so that the input edge is first - */ - if (!begin) - Rearrange_IndexEx(index,size); - - /* We are given a polygon of more than 3 sides - and want to triangulate it. We will output the - triangles to the output file. - */ - - /* Find where the input edge is in the input list */ - Last_Edge(&e1,&e2,&e3,0); - if (( (!begin) && (*(index) == e2) ) || (begin)) - { - Output_TriEx(*(index+0),*(index+1),*(index+size-1),fp,-1,-1,where); - /* If we have a quad, (chances are yes), then we know that - we can just add one diagonal and be done. (divide the - quad into 2 triangles. - */ - if (size == 4) - { - Output_TriEx(*(index+1),*(index+size-1),*(index+2),fp,-1,-1,where); - return; - } - increasing = 1; - mode = 1; - - } - else if (!begin) - { - Output_TriEx(*(index+1),*(index+0),*(index+size-1),fp,-1,-1,where); - if (size == 4) - { - Output_TriEx(*(index+0),*(index+size-1),*(index+2),fp,-1,-1,where); - return; - } - Output_TriEx(*(index+0),*(index+size-1),*(index+2),fp,-1,-1,where); - increasing = 2; - mode = 0; - } - if (size != 4) - { - /* We do not have a quad, we have something bigger. */ - decreasing = size - 1; - - do - { - /* Will be alternating diagonals, so we will be increasing - and decreasing around the polygon. - */ - if (mode) - { - Output_TriEx(*(index+increasing),*(index+decreasing),*(index+increasing+1),fp,-1,-1,where); - increasing++; - } - else - { - Output_TriEx(*(index+decreasing),*(index+increasing),*(index+decreasing-1),fp,-1,-1,where); - decreasing--; - } - mode = !mode; - } while ((decreasing - increasing) >= 2); - - } -} - - diff --git a/Tools/Stripe_u/struct.c b/Tools/Stripe_u/struct.c deleted file mode 100644 index f822b1da7..000000000 --- a/Tools/Stripe_u/struct.c +++ /dev/null @@ -1,549 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: struct.c - Contains routines that update structures, and micellaneous routines. -*/ -/*---------------------------------------------------------------------*/ - -#include -#include -#include "polverts.h" -#include "ties.h" -#include "output.h" -#include "triangulate.h" -#include "sturcts.h" -#include "options.h" -#include "common.h" -#include "util.h" - -int out1 = -1; -int out2 = -1; - -int Get_Edge(int *edge1,int *edge2,int *index,int face_id, - int size, int id1, int id2) -{ - /* Put the edge that is adjacent to face_id into edge1 - and edge2. For each edge see if it is adjacent to - face_id. Id1 and id2 is the input edge, so see if - the orientation is reversed, and save it in reversed. - */ - register int x; - int reversed = -1; - BOOL set = FALSE; - - for (x=0; x< size; x++) - { - if (x == (size-1)) - { - if ((*(index) == id1) && (*(index+size-1)==id2)) - { - if (set) - return 1; - reversed = 1; - } - else if ((*(index) == id2) && (*(index+size-1)==id1)) - { - if (set) - return 0; - reversed = 0; - } - - if (Look_Up(*(index),*(index+size-1),face_id)) - { - if ( (out1 != -1) && ( (out1 == *(index)) || (out1 == *(index+size-1)) ) && - ( (out2 == *(index)) || (out2 == *(index+size-1)) )) - { - set = TRUE; - *edge1 = *(index); - *edge2 = *(index+size-1); - } - else if (out1 == -1) - { - set = TRUE; - *edge1 = *(index); - *edge2 = *(index+size-1); - } - if ((reversed != -1) && (set)) - return reversed; - } - } - else - { - if ((*(index+x) == id1) && (*(index+x+1)==id2)) - { - if (set) - return 0; - reversed = 0; - } - else if ((*(index+x) == id2) && (*(index+x+1)==id1)) - { - if (set) - return 1; - reversed = 1; - } - - if (Look_Up(*(index+x),*(index+x+1),face_id)) - { - if ( (out1 != -1) && ( (out1 == *(index+x)) || (out1 == *(index+x+1)) ) && - ((out2 == *(index+x)) || (out2 == *(index+x+1)))) - { - set = TRUE; - *edge1 = *(index+x); - *edge2 = *(index+x+1); - } - else if (out1 == -1) - { - set = TRUE; - *edge1 = *(index+x); - *edge2 = *(index+x + 1); - } - if ((reversed != -1) && (set)) - return reversed; - } - } - } - if ((x == size) && (reversed != -1)) - { - /* Could not find the output edge */ - printf("Error in the Lookup %d %d %d %d %d %d %d %d\n",face_id,id1,id2,reversed,*edge1,*edge2,out1,out2); - exit(0); - } - return reversed; -} - - -void Update_Face(int *next_bucket, int *min_face, int face_id, int *e1, - int *e2,int temp1,int temp2,int *ties) -{ - /* We have a face id that needs to be decremented. - We have to determine where it is in the structure, - so that we can decrement it. - */ - /* The number of adjacencies may have changed, so to locate - it may be a little tricky. However we know that the number - of adjacencies is less than or equal to the original number - of adjacencies, - */ - int y,size,tally=0; - ListHead *pListHead; - PF_FACES temp = NULL; - PLISTINFO lpListInfo; - static int each_poly = 0; - BOOL there = FALSE; - - pListHead = PolFaces[face_id]; - temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); - /* Check each edge of the face and tally the number of adjacent - polygons to this face. - */ - if ( temp != NULL ) - { - /* Size of the polygon */ - size = temp->nPolSize; - /* We did it already */ - if (size == 1) - return; - for (y = 0; y< size; y++) - { - /* If we are doing partial triangulation, we must check - to see whether the edge is still there in the polygon, - since we might have done a portion of the polygon - and saved the rest for later. - */ - if (y != (size-1)) - { - if( ((temp1 == *(temp->pPolygon+y)) && (temp2 ==*(temp->pPolygon+y+1))) - || ((temp2 == *(temp->pPolygon+y)) && (temp1 ==*(temp->pPolygon+y+1)))) - /* edge is still there we are ok */ - there = TRUE; - } - else - { - if( ((temp1 == *(temp->pPolygon)) && (temp2 == *(temp->pPolygon+size-1))) - || ((temp2 == *(temp->pPolygon)) && (temp1 ==*(temp->pPolygon+size-1)))) - /* edge is still there we are ok */ - there = TRUE; - } - } - - if (!there) - /* Original edge was already used, we cannot use this polygon */ - return; - - /* We have a starting point to start our search to locate - this polygon. - */ - - /* Check to see if this polygon was done */ - lpListInfo = Done(face_id,59,&y); - - if (lpListInfo == NULL) - return; - - /* Was not done, but there is an error in the adjacency calculations */ - if (y == 0) - { - printf("There is an error in finding the adjacencies\n"); - exit(0); - } - - /* Now put the face in the proper bucket depending on tally. */ - /* First add it to the new bucket, then remove it from the old */ - Add_Sgi_Adj(y-1,face_id); - RemoveList(array[y],lpListInfo); - - /* Save it if it was the smallest seen so far since then - it will be the next face - Here we will have different options depending on - what we want for resolving ties: - 1) First one we see we will use - 2) Random resolving - 3) Look ahead - 4) Alternating direction - */ - /* At a new strip */ - if (*next_bucket == 60) - *ties = *ties + each_poly; - /* Have a tie */ - if (*next_bucket == (y-1)) - { - Add_Ties(face_id); - each_poly++; - } - /* At a new minimum */ - if (*next_bucket > (y-1)) - { - *next_bucket = y-1; - *min_face = face_id; - *e1 = temp1; - *e2 = temp2; - each_poly = 0; - Clear_Ties(); - Add_Ties(face_id); - } - } -} - - -void Delete_Adj(int id1, int id2,int *next_bucket,int *min_face, - int current_face,int *e1,int *e2,int *ties) -{ - /* Find the face that is adjacent to the edge and is not the - current face. Delete one adjacency from it. Save the min - adjacency seen so far. - */ - register int count=0; - PF_EDGES temp = NULL; - ListHead *pListHead; - int next_face; - - /* Always want smaller id first */ - switch_lower(&id1,&id2); - - pListHead = PolEdges[id1]; - temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count); - if (temp == NULL) - /* It could be a new edge that we created. So we can - exit, since there is not a face adjacent to it. - */ - return; - while (temp->edge[0] != id2) - { - count++; - temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count); - if (temp == NULL) - /* Was a new edge that was created and therefore - does not have anything adjacent to it - */ - return; - } - /* Was not adjacent to anything else except itself */ - if (temp->edge[2] == -1) - return; - - /* Was adjacent to something */ - else - { - if (temp->edge[2] == current_face) - next_face = temp->edge[1]; - else - next_face = temp->edge[2]; - } - /* We have the other face adjacent to this edge, it is - next_face. Now we need to decrement this faces' adjacencies. - */ - Update_Face(next_bucket, min_face, next_face,e1,e2,id1,id2,ties); -} - - -int Change_Face(int face_id,int in1,int in2, - ListHead *pListHead, P_ADJACENCIES temp, BOOL no_check) -{ - /* We are doing a partial triangulation and we need to - put the new face of triangle into the correct bucket - */ - int input_adj,y; - - /* Find the old number of adjacencies to this face, - so we know where to delete it from - */ - y = Old_Adj(face_id); - - /* Do we need to change the adjacency? Maybe the edge on the triangle - that was outputted was not adjacent to anything. We know if we - have to check by "check". We came out on the output edge - that we needed, then we know that the adjacencies will decrease - by exactly one. - */ - if (!no_check) - { - input_adj = Number_Adj(in1,in2,face_id); - /* If there weren't any then don't do anything */ - if (input_adj == 0) - return y; - } - - RemoveList(pListHead,(PLISTINFO)temp); - /* Before we had a quad with y adjacencies. The in edge - did not have an adjacency, since it was just deleted, - since we came in on it. The outedge must have an adjacency - otherwise we would have a bucket 0, and would not be in this - routine. Therefore the new adjacency must be y-1 - */ - - Add_Sgi_Adj(y-1,face_id); - return (y-1); -} - -int Update_Adjacencies(int face_id, int *next_bucket, int *e1, int *e2, - int *ties) -{ - /* Give the face with id face_id, we want to decrement - all the faces that are adjacent to it, since we will - be deleting face_id from the data structure. - We will return the face that has the least number - of adjacencies. - */ - PF_FACES temp = NULL; - ListHead *pListHead; - int size,y,min_face = -1; - - *next_bucket = 60; - pListHead = PolFaces[face_id]; - temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); - - if ( temp == NULL ) - { - printf("The face was already deleted, there is an error\n"); - exit(0); - } - - /* Size of the polygon */ - size = temp->nPolSize; - for (y = 0; y< size; y++) - { - if (y != (size-1)) - Delete_Adj(*(temp->pPolygon+y),*(temp->pPolygon+y+1), - next_bucket,&min_face,face_id,e1,e2,ties); - else - Delete_Adj(*(temp->pPolygon),*(temp->pPolygon+(size-1)), - next_bucket,&min_face,face_id,e1,e2,ties); - } - return (min_face); -} - - -void Find_Adj_Tally(int id1, int id2,int *next_bucket,int *min_face, - int current_face,int *ties) -{ - /* Find the face that is adjacent to the edge and is not the - current face. Save the min adjacency seen so far. - */ - int size,each_poly=0,y,tally=0,count=0; - PF_EDGES temp = NULL; - PF_FACES temp2 = NULL; - ListHead *pListHead; - int next_face; - BOOL there = FALSE; - - - /* Always want smaller id first */ - switch_lower(&id1,&id2); - - pListHead = PolEdges[id1]; - temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count); - if (temp == NULL) - /* This was a new edge that was created, so it is - adjacent to nothing. - */ - return; - - while (temp->edge[0] != id2) - { - count++; - temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count); - if (temp == NULL) - /* This was a new edge that we created */ - return; - } - /* Was not adjacent to anything else except itself */ - if (temp->edge[2] == -1) - return; - else - { - if (temp->edge[2] == current_face) - next_face = temp->edge[1]; - else - next_face = temp->edge[2]; - } - /* We have the other face adjacent to this edge, it is - next_face. Find how many faces it is adjacent to. - */ - pListHead = PolFaces[next_face]; - temp2 = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); - /* Check each edge of the face and tally the number of adjacent - polygons to this face. This will be the original number of - polygons adjacent to this polygon, we must then see if this - number has been decremented - */ - if ( temp2 != NULL ) - { - /* Size of the polygon */ - size = temp2->nPolSize; - /* We did it already */ - if (size == 1) - return; - for (y = 0; y< size; y++) - { - /* Make sure that the edge is still in the - polygon and was not deleted, because if the edge was - deleted, then we used it already. - */ - if (y != (size-1)) - { - if( ((id1 == *(temp2->pPolygon+y)) && (id2 ==*(temp2->pPolygon+y+1))) - || ((id2 == *(temp2->pPolygon+y)) && (id1 ==*(temp2->pPolygon+y+1)))) - /* edge is still there we are ok */ - there = TRUE; - } - else - { - if( ((id1 == *(temp2->pPolygon)) && (id2 ==*(temp2->pPolygon+size-1))) - || ((id2 == *(temp2->pPolygon)) && (id1 ==*(temp2->pPolygon+size-1)))) - /* edge is still there we are ok */ - there = TRUE; - } - } - - if (!there) - /* Edge already used and deleted from the polygon*/ - return; - - /* See if the face was already deleted, and where - it is if it was not - */ - if (Done(next_face,size,&y) == NULL) - return; - - /* Save it if it was the smallest seen so far since then - it will be the next face - Here we will have different options depending on - what we want for resolving ties: - 1) First one we see we will use - 2) Random resolving - 3) Look ahead - 4) Alternating direction - */ - - /* At a new strip */ - if (*next_bucket == 60) - *ties = *ties + each_poly; - /* Have a tie */ - if (*next_bucket == (y-1)) - { - Add_Ties(next_face); - each_poly++; - } - /* At a new minimum */ - if (*next_bucket > (y-1)) - { - *next_bucket = y-1; - *min_face = next_face; - each_poly = 0; - Clear_Ties(); - Add_Ties(next_face); - } - } -} - - -int Min_Face_Adj(int face_id, int *next_bucket, int *ties) -{ - /* Used for the Partial triangulation to find the next - face. It will return the minimum adjacency face id - found at this face. - */ - PF_FACES temp = NULL; - ListHead *pListHead; - int size,y,min_face,test_face; - - *next_bucket = 60; - pListHead = PolFaces[face_id]; - temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); - - if ( temp == NULL ) - { - printf("The face was already deleted, there is an error\n"); - exit(0); - } - - /* Size of the polygon */ - size = temp->nPolSize; - for (y = 0; y< size; y++) - { - if (y != (size-1)) - Find_Adj_Tally(*(temp->pPolygon+y),*(temp->pPolygon+y+1), - next_bucket,&min_face,face_id,ties); - else - Find_Adj_Tally(*(temp->pPolygon),*(temp->pPolygon+(size-1)), - next_bucket,&min_face,face_id,ties); - } - /* Maybe we can do better by triangulating the face, because - by triangulating the face we will go to a polygon of lesser - adjacencies - */ - if (size == 4) - { - /* Checking for a quad whether to do the whole polygon will - result in better performance because the triangles in the polygon - have less adjacencies - */ - Check_In_Quad(face_id,&test_face); - if (*next_bucket > test_face) - /* We can do better by going through the polygon */ - min_face = face_id; - } - - /* We have a polygon with greater than 4 sides, check to see if going - inside is better than going outside the polygon for the output edge. - */ - else - { - Check_In_Polygon(face_id,&test_face,size); - if (*next_bucket > test_face) - /* We can do better by going through the polygon */ - min_face = face_id; - } - - return (min_face); -} - - - diff --git a/Tools/Stripe_u/struct.h b/Tools/Stripe_u/struct.h deleted file mode 100644 index 6eb036cb4..000000000 --- a/Tools/Stripe_u/struct.h +++ /dev/null @@ -1,6 +0,0 @@ - -struct vert_struct { - VRDATA x, y, z; /* point coordinates */ -}; - - diff --git a/Tools/Stripe_u/structex.c b/Tools/Stripe_u/structex.c deleted file mode 100644 index 06adba7b5..000000000 --- a/Tools/Stripe_u/structex.c +++ /dev/null @@ -1,553 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: structex.c - This file contains routines that are used for various functions in - the local algorithm. -*/ -/*---------------------------------------------------------------------*/ - -#include -#include -#include "polverts.h" -#include "ties.h" -#include "outputex.h" -#include "triangulatex.h" -#include "sturctsex.h" -#include "options.h" -#include "common.h" -#include "util.h" - -int out1Ex = -1; -int out2Ex = -1; - -int Get_EdgeEx(int *edge1,int *edge2,int *index,int face_id, - int size, int id1, int id2) -{ - /* Put the edge that is adjacent to face_id into edge1 - and edge2. For each edge see if it is adjacent to - face_id. Id1 and id2 is the input edge, so see if - the orientation is reversed, and save it in reversed. - */ - int x; - int reversed = -1; - BOOL set = FALSE; - - for (x=0; x< size; x++) - { - if (x == (size-1)) - { - if ((*(index) == id1) && (*(index+size-1)==id2)) - { - if (set) - return 1; - reversed = 1; - } - else if ((*(index) == id2) && (*(index+size-1)==id1)) - { - if (set) - return 0; - reversed = 0; - } - - if (Look_Up(*(index),*(index+size-1),face_id)) - { - if ( (out1Ex != -1) && ( (out1Ex == *(index)) || (out1Ex == *(index+size-1)) ) && - ( (out2Ex == *(index)) || (out2Ex == *(index+size-1)) )) - { - set = TRUE; - *edge1 = *(index); - *edge2 = *(index+size-1); - } - else if (out1Ex == -1) - { - set = TRUE; - *edge1 = *(index); - *edge2 = *(index+size-1); - } - if ((reversed != -1) && (set)) - return reversed; - } - } - else - { - if ((*(index+x) == id1) && (*(index+x+1)==id2)) - { - if (set) - return 0; - reversed = 0; - } - else if ((*(index+x) == id2) && (*(index+x+1)==id1)) - { - if (set) - return 1; - reversed = 1; - } - - if (Look_Up(*(index+x),*(index+x+1),face_id)) - { - if ( (out1Ex != -1) && ( (out1Ex == *(index+x)) || (out1Ex == *(index+x+1)) ) && - ((out2Ex == *(index+x)) || (out2Ex == *(index+x+1)))) - { - set = TRUE; - *edge1 = *(index+x); - *edge2 = *(index+x+1); - } - else if (out1Ex == -1) - { - set = TRUE; - *edge1 = *(index+x); - *edge2 = *(index+x + 1); - } - if ((reversed != -1) && (set)) - return reversed; - } - } - } - if ((x == size) && (reversed != -1)) - { - /* Could not find the output edge */ - printf("Error in the Lookup %d %d %d %d %d %d %d %d\n",face_id,id1,id2,reversed,*edge1,*edge2,out1Ex,out2Ex); - exit(0); - } - return reversed; -} - - -void Update_FaceEx(int *next_bucket, int *min_face, int face_id, int *e1, - int *e2,int temp1,int temp2,int *ties) -{ - /* We have a face id that needs to be decremented. - We have to determine where it is in the structure, - so that we can decrement it. - */ - /* The number of adjacencies may have changed, so to locate - it may be a little tricky. However we know that the number - of adjacencies is less than or equal to the original number - of adjacencies, - */ - int y,size,tally=0; - ListHead *pListHead; - PF_FACES temp = NULL; - PLISTINFO lpListInfo; - static int each_poly = 0; - BOOL there = FALSE; - - pListHead = PolFaces[face_id]; - temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); - /* Check each edge of the face and tally the number of adjacent - polygons to this face. - */ - if ( temp != NULL ) - { - /* Size of the polygon */ - size = temp->nPolSize; - for (y = 0; y< size; y++) - { - /* If we are doing partial triangulation, we must check - to see whether the edge is still there in the polygon, - since we might have done a portion of the polygon - and saved the rest for later. - */ - if (y != (size-1)) - { - if( ((temp1 == *(temp->pPolygon+y)) && (temp2 ==*(temp->pPolygon+y+1))) - || ((temp2 == *(temp->pPolygon+y)) && (temp1 ==*(temp->pPolygon+y+1)))) - /* edge is still there we are ok */ - there = TRUE; - } - else - { - if( ((temp1 == *(temp->pPolygon)) && (temp2 == *(temp->pPolygon+size-1))) - || ((temp2 == *(temp->pPolygon)) && (temp1 ==*(temp->pPolygon+size-1)))) - /* edge is still there we are ok */ - there = TRUE; - } - } - - if (!there) - /* Original edge was already used, we cannot use this polygon */ - return; - - /* We have a starting point to start our search to locate - this polygon. - */ - - /* Check to see if this polygon was done */ - lpListInfo = Done(face_id,59,&y); - - if (lpListInfo == NULL) - return; - - /* Was not done, but there is an error in the adjacency calculations */ - /* If more than one edge is adj to it then maybe it was not updated */ - if (y == 0) - return; - - /* Now put the face in the proper bucket depending on tally. */ - /* First add it to the new bucket, then remove it from the old */ - Add_Sgi_Adj(y-1,face_id); - RemoveList(array[y],lpListInfo); - - /* Save it if it was the smallest seen so far since then - it will be the next face - Here we will have different options depending on - what we want for resolving ties: - 1) First one we see we will use - 2) Random resolving - 3) Look ahead - 4) Alternating direction - */ - /* At a new strip */ - if (*next_bucket == 60) - *ties = *ties + each_poly; - /* Have a tie */ - if (*next_bucket == (y-1)) - { - Add_Ties(face_id); - each_poly++; - } - /* At a new minimum */ - if (*next_bucket > (y-1)) - { - *next_bucket = y-1; - *min_face = face_id; - *e1 = temp1; - *e2 = temp2; - each_poly = 0; - Clear_Ties(); - Add_Ties(face_id); - } - } -} - - -void Delete_AdjEx(int id1, int id2,int *next_bucket,int *min_face, - int current_face,int *e1,int *e2,int *ties) -{ - /* Find the face that is adjacent to the edge and is not the - current face. Delete one adjacency from it. Save the min - adjacency seen so far. - */ - register int count=0; - PF_EDGES temp = NULL; - ListHead *pListHead; - int next_face; - - /* Always want smaller id first */ - switch_lower(&id1,&id2); - - pListHead = PolEdges[id1]; - temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count); - if (temp == NULL) - /* It could be a new edge that we created. So we can - exit, since there is not a face adjacent to it. - */ - return; - while (temp->edge[0] != id2) - { - count++; - temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count); - if (temp == NULL) - /* Was a new edge that was created and therefore - does not have anything adjacent to it - */ - return; - } - /* Was not adjacent to anything else except itself */ - if (temp->edge[2] == -1) - return; - - /* Was adjacent to something */ - else - { - if (temp->edge[2] == current_face) - next_face = temp->edge[1]; - else - next_face = temp->edge[2]; - } - /* We have the other face adjacent to this edge, it is - next_face. Now we need to decrement this faces' adjacencies. - */ - Update_FaceEx(next_bucket, min_face, next_face,e1,e2,id1,id2,ties); -} - -int Change_FaceEx(int face_id,int in1,int in2, - ListHead *pListHead, P_ADJACENCIES temp, BOOL no_check) -{ - /* We are doing a partial triangulation and we need to - put the new face of triangle into the correct bucket - */ - int input_adj,y; - P_ADJACENCIES pfNode,lpListInfo; - - /* Find the old number of adjacencies to this face, - so we know where to delete it from - */ - y = Old_Adj(face_id); - pListHead = array[y]; - - pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) ); - if ( pfNode ) - pfNode->face_id = face_id; - lpListInfo = (P_ADJACENCIES) (SearchList(array[y], pfNode, - (int (*)(void *,void *)) (Compare))); - if (lpListInfo == NULL) - { - printf("There is an error finding the next polygon3 %d\n",face_id); - exit(0); - } - - /* Do we need to change the adjacency? Maybe the edge on the triangle - that was outputted was not adjacent to anything. We know if we - have to check by "check". We came out on the output edge - that we needed, then we know that the adjacencies will decrease - by exactly one. - */ - if (!no_check) - { - input_adj = Number_Adj(in1,in2,face_id); - /* If there weren't any then don't do anything */ - if (input_adj == 0) - return y; - } - - RemoveList(pListHead,(PLISTINFO)/*(temp*/lpListInfo); - /* Before we had a quad with y adjacencies. The in edge - did not have an adjacency, since it was just deleted, - since we came in on it. The outedge must have an adjacency - otherwise we would have a bucket 0, and would not be in this - routine. Therefore the new adjacency must be y-1 - */ - - Add_Sgi_Adj(y-1,face_id); - return (y-1); -} - -int Update_AdjacenciesEx(int face_id, int *next_bucket, int *e1, int *e2, - int *ties) -{ - /* Give the face with id face_id, we want to decrement - all the faces that are adjacent to it, since we will - be deleting face_id from the data structure. - We will return the face that has the least number - of adjacencies. - */ - PF_FACES temp = NULL; - ListHead *pListHead; - int size,y,min_face = -1; - - *next_bucket = 60; - pListHead = PolFaces[face_id]; - temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); - - if ( temp == NULL ) - { - printf("The face was already deleted, there is an error\n"); - exit(0); - } - - /* Size of the polygon */ - size = temp->nPolSize; - for (y = 0; y< size; y++) - { - if (y != (size-1)) - Delete_AdjEx(*(temp->pPolygon+y),*(temp->pPolygon+y+1), - next_bucket,&min_face,face_id,e1,e2,ties); - else - Delete_AdjEx(*(temp->pPolygon),*(temp->pPolygon+(size-1)), - next_bucket,&min_face,face_id,e1,e2,ties); - } - return (min_face); -} - - - -void Find_Adj_TallyEx(int id1, int id2,int *next_bucket,int *min_face, - int current_face,int *ties) -{ - /* Find the face that is adjacent to the edge and is not the - current face. Save the min adjacency seen so far. - */ - int size,each_poly=0,y,tally=0,count=0; - PF_EDGES temp = NULL; - PF_FACES temp2 = NULL; - ListHead *pListHead; - int next_face; - BOOL there = FALSE; - - - /* Always want smaller id first */ - switch_lower(&id1,&id2); - - pListHead = PolEdges[id1]; - temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count); - if (temp == NULL) - /* This was a new edge that was created, so it is - adjacent to nothing. - */ - return; - while (temp->edge[0] != id2) - { - count++; - temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count); - if (temp == NULL) - /* This was a new edge that we created */ - return; - } - /* Was not adjacent to anything else except itself */ - if (temp->edge[2] == -1) - return; - else - { - if (temp->edge[2] == current_face) - next_face = temp->edge[1]; - else - next_face = temp->edge[2]; - } - /* We have the other face adjacent to this edge, it is - next_face. Find how many faces it is adjacent to. - */ - pListHead = PolFaces[next_face]; - temp2 = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); - /* Check each edge of the face and tally the number of adjacent - polygons to this face. This will be the original number of - polygons adjacent to this polygon, we must then see if this - number has been decremented - */ - if ( temp2 != NULL ) - { - /* Size of the polygon */ - size = temp2->nPolSize; - for (y = 0; y< size; y++) - { - /* Make sure that the edge is still in the - polygon and was not deleted, because if the edge was - deleted, then we used it already. - */ - if (y != (size-1)) - { - if( ((id1 == *(temp2->pPolygon+y)) && (id2 ==*(temp2->pPolygon+y+1))) - || ((id2 == *(temp2->pPolygon+y)) && (id1 ==*(temp2->pPolygon+y+1)))) - /* edge is still there we are ok */ - there = TRUE; - } - else - { - if( ((id1 == *(temp2->pPolygon)) && (id2 ==*(temp2->pPolygon+size-1))) - || ((id2 == *(temp2->pPolygon)) && (id1 ==*(temp2->pPolygon+size-1)))) - /* edge is still there we are ok */ - there = TRUE; - } - } - - if (!there) - /* Edge already used and deleted from the polygon*/ - return; - - /* See if the face was already deleted, and where - it is if it was not - */ - if (Done(next_face,size,&y) == NULL) - return; - - /* Save it if it was the smallest seen so far since then - it will be the next face - Here we will have different options depending on - what we want for resolving ties: - 1) First one we see we will use - 2) Random resolving - 3) Look ahead - 4) Alternating direction - */ - - /* At a new strip */ - if (*next_bucket == 60) - *ties = *ties + each_poly; - /* Have a tie */ - if (*next_bucket == (y-1)) - { - Add_Ties(next_face); - each_poly++; - } - /* At a new minimum */ - if (*next_bucket > (y-1)) - { - *next_bucket = y-1; - *min_face = next_face; - each_poly = 0; - Clear_Ties(); - Add_Ties(next_face); - } - } -} - - -int Min_Face_AdjEx(int face_id, int *next_bucket, int *ties) -{ - /* Used for the Partial triangulation to find the next - face. It will return the minimum adjacency face id - found at this face. - */ - PF_FACES temp = NULL; - ListHead *pListHead; - int size,y,min_face,test_face; - - *next_bucket = 60; - pListHead = PolFaces[face_id]; - temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); - - if ( temp == NULL ) - { - printf("The face was already deleted, there is an error\n"); - exit(0); - } - - /* Size of the polygon */ - size = temp->nPolSize; - for (y = 0; y< size; y++) - { - if (y != (size-1)) - Find_Adj_TallyEx(*(temp->pPolygon+y),*(temp->pPolygon+y+1), - next_bucket,&min_face,face_id,ties); - else - Find_Adj_TallyEx(*(temp->pPolygon),*(temp->pPolygon+(size-1)), - next_bucket,&min_face,face_id,ties); - } - /* Maybe we can do better by triangulating the face, because - by triangulating the face we will go to a polygon of lesser - adjacencies - */ - if (size == 4) - { - /* Checking for a quad whether to do the whole polygon will - result in better performance because the triangles in the polygon - have less adjacencies - */ - Check_In_Quad(face_id,&test_face); - if (*next_bucket > test_face) - /* We can do better by going through the polygon */ - min_face = face_id; - } - - /* We have a polygon with greater than 4 sides, check to see if going - inside is better than going outside the polygon for the output edge. - */ - else - { - Check_In_Polygon(face_id,&test_face,size); - if (*next_bucket > test_face) - /* We can do better by going through the polygon */ - min_face = face_id; - } - - return (min_face); -} - - diff --git a/Tools/Stripe_u/sturcts.h b/Tools/Stripe_u/sturcts.h deleted file mode 100644 index 07a2bbf97..000000000 --- a/Tools/Stripe_u/sturcts.h +++ /dev/null @@ -1,31 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: sturcts.h ------------------------------------------------------------------------*/ - -#define EVEN(x) (((x) & 1) == 0) - -BOOL Get_Edge(); -void add_vert_id(); -void Update_Face(); -int Min_Adj(); -int Min_Face_Adj(); -int Change_Face(); -void Delete_Adj(); -int Update_Adjacencies(); -int Get_Output_Edge(); -int Find_Face(); - - - - - - - diff --git a/Tools/Stripe_u/sturctsex.h b/Tools/Stripe_u/sturctsex.h deleted file mode 100644 index 550228306..000000000 --- a/Tools/Stripe_u/sturctsex.h +++ /dev/null @@ -1,28 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE:sturctsex.h ------------------------------------------------------------------------*/ - -#define EVEN(x) (((x) & 1) == 0) - -BOOL Get_EdgeEx(); -void add_vert_idEx(); -void Update_FaceEx(); -int Min_Face_AdjEx(); -int Change_FaceEx(); -void Delete_AdjEx(); -int Number_AdjEx(); -int Update_AdjacenciesEx(); - - - - - - diff --git a/Tools/Stripe_u/ties.c b/Tools/Stripe_u/ties.c deleted file mode 100644 index e1a64545c..000000000 --- a/Tools/Stripe_u/ties.c +++ /dev/null @@ -1,304 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: ties.c - This file will contain all the routines used to determine the next face if there - is a tie -*/ -/*---------------------------------------------------------------------*/ - -#include -#include "polverts.h" -#include "ties.h" -#include "sturctsex.h" -#include "triangulatex.h" -#include "options.h" -#include "common.h" -#include "util.h" - -#define MAX_TIE 60 -int ties_array[60]; -int last = 0; - -void Clear_Ties() -{ - /* Clear the buffer, because we do not have the tie - any more that we had before */ - last = 0; -} - -void Add_Ties(int id) -{ - /* We have a tie to add to the buffer */ - ties_array[last++] = id; -} - -int Alternate_Tie() -{ - /* Alternate in what we choose to break the tie - We are just alternating between the first and - second thing that we found - */ - static int x = 0; - register int t; - - t = ties_array[x]; - x++; - if (x == 2) - x = 0; - return t; -} - -int Random_Tie() -{ - /* Randomly choose the next face with which - to break the tie - */ - register int num; - - num = rand(); - while (num >= last) - num = num/20; - return (ties_array[num]); -} - -int Look_Ahead(int id) -{ - /* Look ahead at this face and save the minimum - adjacency of all the faces that are adjacent to - this face. - */ - return Min_Adj(id); -} - -int Random_Look(int id[],int count) -{ - /* We had a tie within a tie in the lookahead, - break it randomly - */ - register int num; - - num = rand(); - while (num >= count) - num = num/20; - return (id[num]); -} - - -int Look_Ahead_Tie() -{ - /* Look ahead and find the face to go to that - will give the least number of adjacencies - */ - int id[60],t,x,f=0,min = 60; - - for (x = 0; x < last; x++) - { - t = Look_Ahead(ties_array[x]); - /* We have a tie */ - if (t == min) - id[f++] = ties_array[x]; - if (t < min) - { - f = 0; - min = t; - id[f++] = ties_array[x]; - } - } - /* No tie within the tie */ - if ( f == 1) - return id[0]; - /* Or ties, but we are at the end of strips */ - if (min == 0) - return id[0]; - return (Random_Look(id,f)); -} - - -int Sequential_Tri(int *index) -{ - /* We have a triangle and need to break the ties at it. - We will choose the edge that is sequential. There - is definitely one since we know we have a triangle - and that there is a tie and there are only 2 edges - for the tie. - */ - int reversed, e1,e2,e3,output1,output2,output3,output4; - - /* e2 and e3 are the input edge to the triangle */ - Last_Edge(&e1,&e2,&e3,0); - - if ((e2 == 0) && (e3 == 0)) - /* Starting the strip, don't need to do this */ - return ties_array[0]; - - /* For the 2 ties find the edge adjacent to face id */ - reversed = Get_EdgeEx(&output1,&output2,index,ties_array[0],3,0,0); - reversed = Get_EdgeEx(&output3,&output4,index,ties_array[1],3,0,0); - - if ((output1 == e3) || (output2 == e3)) - return ties_array[0]; - if ((output3 == e3) || (output4 == e3)) - return ties_array[1]; - printf("There is an error trying to break sequential triangle \n"); -} - -int Sequential_Quad(int *index, int triangulate) -{ - /* We have a quad that need to break its ties, we will try - and choose a side that is sequential, otherwise use lookahead - */ - int reversed,output1,output2,x,e1,e2,e3; - - /* e2 and e3 are the input edge to the quad */ - Last_Edge(&e1,&e2,&e3,0); - - /* No input edge */ - if ((e2 == 0) && (e3 == 0)) - return ties_array[0]; - - /* Go through the ties and see if there is a sequential one */ - for (x = 0; x < last; x++) - { - reversed = Get_EdgeEx(&output1,&output2,index,ties_array[x],4,0,0); - /* Partial and whole triangulation will have different requirements */ - if (((output1 == e3) || (output2 == e3)) && (triangulate == PARTIAL)) - return ties_array[x]; - if (((output1 != e3) && (output1 != e2) && - (output2 != e3) && (output2 != e2))) - return ties_array[x]; - } - /* There was not a tie that was sequential */ - return Look_Ahead_Tie(); -} - -void Whole_Output(int in1,int in2, int *index, int size, int *out1, int *out2) -{ - /* Used to sequentially break ties in the whole triangulation for polygons - greater than 4 sides. We will find the output edge that is good - for sequential triangulation. - */ - - int half; - - /* Put the input edge first in the list */ - Rearrange_IndexEx(index,size); - - if (!(EVEN(size))) - { - if (*(index) == in1) - half = size/2 ; - else - half = size/2 +1; - } - else - half = size/2; - - *out1 = *(index+half); - *out2 = *(index+half+1); -} - -int Sequential_Poly(int size, int *index, int triangulate) -{ - /* We have a polygon of greater than 4 sides and wish to break the - tie in the most sequential manner. - */ - - int x,reversed,output1,output2,e1,e2,e3,saved1=-1,saved2=-1,output3,output4; - - /* e2 and e3 are the input edge to the quad */ - Last_Edge(&e1,&e2,&e3,0); - - /* If we are using whole, find the output edge that is sequential */ - if (triangulate == WHOLE) - Whole_Output(e2,e3,index,size,&output3,&output4); - - /* No input edge */ - if ((e2 == 0) && (e3 == 0)) - return ties_array[0]; - - for (x = 0; x < last ; x++) - { - reversed = Get_EdgeEx(&output1,&output2,index,ties_array[x],size,0,0); - /* Partial that can be removed in just one triangle */ - if (((output1 == e3) || (output2 == e3)) && (triangulate == PARTIAL)) - saved1 = ties_array[x]; - /* Partial removed in more than one triangle */ - if ((output1 != e3) && (output1 != e2) && (output2 != e3) && (output2 != e2) && - (triangulate == PARTIAL) && (saved2 != -1)) - saved2 = ties_array[x]; - /* Whole is not so easy, since the whole polygon must be done. Given - an input edge there is only one way to come out, approximately half - way around the polygon. - */ - if (((output1 == output3) && (output2 == output4)) || - ((output1 == output4) && (output2 == output3)) && - (triangulate == WHOLE)) - return ties_array[x]; - } - - if (saved1 != -1) - return saved1; - if (saved2 != -1) - return saved2; - - /* There was not a tie that was sequential */ - return Look_Ahead_Tie(); -} - -int Sequential_Tie(int face_id,int triangulate) -{ - /* Break the tie by choosing the face that will - not give us a swap and is sequential. If there - is not one, then do the lookahead to break the - tie. - */ - /* Separate into 3 cases for simplicity, if the current - polygon has 3 sides, 4 sides or if the sides were - greater. We can do the smaller cases faster, so that - is why I separated the cases. - */ - - ListHead *pListFace; - PF_FACES face; - - /* Get the polygon with id face_id */ - pListFace = PolFaces[face_id]; - face = (PF_FACES) PeekList(pListFace,LISTHEAD,0); - - if (face->nPolSize == 3) - return(Sequential_Tri(face->pPolygon)); - if (face->nPolSize == 4) - return(Sequential_Quad(face->pPolygon,triangulate)); - else - return(Sequential_Poly(face->nPolSize,face->pPolygon,triangulate)); - -} - -int Get_Next_Face(int t, int face_id, int triangulate) -{ - /* Get the next face depending on what - the user specified - */ - - /* Did not have a tie, don't do anything */ - if (last == 1) - return(ties_array[0]); - if (t == RANDOM) - return Random_Tie(); - if (t == ALTERNATE) - return Alternate_Tie(); - if (t == LOOK) - return Look_Ahead_Tie(); - if (t == SEQUENTIAL) - return Sequential_Tie(face_id,triangulate); - - printf("Illegal option specified for ties, using first \n"); - return (ties_array[0]); -} diff --git a/Tools/Stripe_u/ties.h b/Tools/Stripe_u/ties.h deleted file mode 100644 index 97e051765..000000000 --- a/Tools/Stripe_u/ties.h +++ /dev/null @@ -1,15 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: ties.h ------------------------------------------------------------------------*/ - -void Clear_Ties(); -void Add_Ties(); -int Get_Next_Face(); diff --git a/Tools/Stripe_u/triangulate.h b/Tools/Stripe_u/triangulate.h deleted file mode 100644 index de612119f..000000000 --- a/Tools/Stripe_u/triangulate.h +++ /dev/null @@ -1,23 +0,0 @@ - -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: triangulate.h ------------------------------------------------------------------------*/ - -void Blind_Triangulate(); -void Non_Blind_Triangulate(); -int Adjacent(); -void Delete_From_List(); -void Triangulate_Polygon(); -void Rearrange_Index(); -void Find_Local_Strips(); - - - diff --git a/Tools/Stripe_u/triangulatex.h b/Tools/Stripe_u/triangulatex.h deleted file mode 100644 index 1710f0182..000000000 --- a/Tools/Stripe_u/triangulatex.h +++ /dev/null @@ -1,23 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: triangulatex.h ------------------------------------------------------------------------*/ - -enum swap_type -{ ON, OFF}; - -void SGI_StripEx(); -void Blind_TriangulateEx(); -void Non_Blind_TriangulateEx(); -int AdjacentEx(); -void Delete_From_ListEx(); -void Triangulate_PolygonEx(); -void Rearrange_IndexEx(); -void Find_StripsEx(); diff --git a/Tools/Stripe_u/util.c b/Tools/Stripe_u/util.c deleted file mode 100644 index f17fe5f7c..000000000 --- a/Tools/Stripe_u/util.c +++ /dev/null @@ -1,272 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: util.c - This file contains routines that are used for various functions -*/ -/*---------------------------------------------------------------------*/ - - -#include -#include "polverts.h" - -void switch_lower (int *x, int *y) -{ - register int temp; - - /* Put lower value in x */ - if (*y < *x) - { - temp = *x; - *x = *y; - *y = temp; - } -} - -BOOL member(int x , int id1, int id2, int id3) -{ - /* Is x in the triangle specified by id1,id2,id3 */ - if ((x != id1) && (x != id2) && (x != id3)) - return FALSE; - return TRUE; -} - - -int Compare (P_ADJACENCIES node1, P_ADJACENCIES node2) -{ - /* This will only return whether 2 adjacency nodes - are equivalent. - */ - if (node1->face_id == node2->face_id) - return TRUE; - else - return FALSE; -} - - -BOOL Exist(int face_id, int id1, int id2) -{ - /* Does the edge specified by id1 and id2 exist in this - face currently? Maybe we deleted in partial triangulation - */ - ListHead *pListHead; - PF_FACES temp; - register int x,size; - BOOL a=FALSE,b =FALSE; - - pListHead = PolFaces[face_id]; - temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); - size = temp->nPolSize; - for (x=0; xpPolygon+x) == id1) - a = TRUE; - if (*(temp->pPolygon+x) == id2) - b = TRUE; - if (a && b) - return TRUE; - } - return FALSE; -} - -int Get_Next_Id(int *index,int e3, int size) -{ - /* Return the id following e3 in the list of vertices */ - - register int x; - - for (x = 0; x< size; x++) - { - if ((*(index+x) == e3) && (x != (size-1))) - return *(index+x+1); - else if (*(index+x) == e3) - return *(index); - } - printf("There is an error in the next id\n"); - exit(0); -} - -int Different (int id1,int id2,int id3,int id4,int id5, int id6, int *x, int *y) -{ - /* Find the vertex in the first 3 numbers that does not exist in - the last three numbers - */ - if ((id1 != id4) && (id1 != id5) && (id1 != id6)) - { - *x = id2; - *y = id3; - return id1; - } - if ((id2 != id4) && (id2 != id5) && (id2 != id6)) - { - *x = id1; - *y = id3; - return id2; - } - if ((id3 != id4) && (id3 != id5) && (id3 != id6)) - { - *x = id1; - *y = id2; - return id3; - } - - /* Because there are degeneracies in the data, this might occur */ - *x = id5; - *y = id6; - return id4; -} - -int Return_Other(int *index,int e1,int e2) -{ - /* We have a triangle and want to know the third vertex of it */ - register int x; - - for (x=0;x<3;x++) - { - if ((*(index+x) != e1) && (*(index+x) != e2)) - return *(index+x); - } - /* If there is a degenerate triangle return arbitrary */ - return e1; -} - -int Get_Other_Vertex(int id1,int id2,int id3,int *index) -{ - /* We have a list index of 4 numbers and we wish to - return the number that is not id1,id2 or id3 - */ - register int x; - - for (x=0; x<4; x++) - { - if ((*(index+x) != id1) && (*(index+x) != id2) && - (*(index+x) != id3)) - return *(index+x); - } - /* If there is some sort of degeneracy this might occur, - return arbitrary - */ - if (x==4) - return id1; -} - - -PLISTINFO Done(int face_id, int size, int *bucket) -{ - /* Check to see whether the polygon with face_id was used - already, return NULL if it was, otherwise return a pointer to the face. - */ - P_ADJACENCIES pfNode; - register int y; - PLISTINFO lpListInfo; - - pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) ); - if ( pfNode ) - pfNode->face_id = face_id; - - for (y=size; ; y--) - { - lpListInfo = SearchList(array[y], pfNode, - (int (*)(void *,void *)) (Compare)); - if (lpListInfo != NULL) - { - *bucket = y; - return lpListInfo; - } - if (y == 0) - /* This adjacent face was done already */ - return lpListInfo; - } - free (pfNode); -} - -void Output_Edge(int *index,int e2,int e3,int *output1,int *output2) -{ - /* Given a quad and an input edge return the other 2 vertices of the - quad. - */ - - *output1 = -1; - *output2 = -1; - - if ((*(index) != e2) && (*(index) != e3)) - *output1 = *(index); - - if ((*(index+1) != e2) && (*(index+1) != e3)) - { - if (*output1 == -1) - *output1 = *(index+1); - else - { - *output2 = *(index+1); - return; - } - } - - if ((*(index+2) != e2) && (*(index+2) != e3)) - { - if (*output1 == -1) - *output1 = *(index+2); - else - { - *output2 = *(index+2); - return; - } - } - - *output2 = *(index+3); -} - - -void First_Edge(int *id1,int *id2, int *id3) -{ - /* Get the first triangle in the strip we just found, we will use this to - try to extend backwards in the strip - */ - - ListHead *pListHead; - register int num; - P_STRIPS temp1,temp2,temp3; - - pListHead = strips[0]; - num = NumOnList(pListHead); - - /* Did not have a strip */ - if (num < 3) - return; - - temp1 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 0); - temp2 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 1); - temp3 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 2); - *id1 = temp1->face_id; - *id2 = temp2->face_id; - *id3 = temp3->face_id; - -} - -void Last_Edge(int *id1, int *id2, int *id3, BOOL save) -{ - /* We need the last edge that we had */ - static int v1, v2, v3; - - if (save) - { - v1 = *id1; - v2 = *id2; - v3 = *id3; - } - else - { - *id1 = v1; - *id2 = v2; - *id3 = v3; - } -} - - diff --git a/Tools/Stripe_u/util.h b/Tools/Stripe_u/util.h deleted file mode 100644 index 2b43a4d35..000000000 --- a/Tools/Stripe_u/util.h +++ /dev/null @@ -1,24 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: util.h ------------------------------------------------------------------------*/ - -void switch_lower (); -int Compare (); -BOOL Exist(); -int Get_Next_Id(); -int Different(); -int Return_Other(); -int Get_Other_Vertex(); -PLISTINFO Done(); -void Output_Edge(); -void Last_Edge(); -void First_Edge(); -BOOL member(); diff --git a/Tools/Stripe_w/Makefile.am b/Tools/Stripe_w/Makefile.am deleted file mode 100644 index ac0280b8a..000000000 --- a/Tools/Stripe_w/Makefile.am +++ /dev/null @@ -1,27 +0,0 @@ -bin_PROGRAMS = strips - -strips_SOURCES = \ - add.c add.h \ - bands.c \ - common.c common.h \ - extend.h \ - free.c free.h \ - global.h \ - init.c init.h \ - local.c local.h \ - newpolve.c \ - options.c options.h \ - output.c output.h \ - outputex.c outputex.h \ - partial.c partial.h \ - polverts.h polyvertsex.h \ - queue.c queue.h \ - sgi_triang.c sgi_triangex.c \ - struct.c \ - structex.c \ - sturcts.h sturctsex.h \ - ties.c ties.h \ - triangulate.h triangulatex.h \ - util.c util.h - -strips_LDADD = $(base_LIBS) diff --git a/Tools/Stripe_w/add.c b/Tools/Stripe_w/add.c deleted file mode 100644 index ef6e673d8..000000000 --- a/Tools/Stripe_w/add.c +++ /dev/null @@ -1,384 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: add.c - This file contains the procedure code that will add information - to our data structures. -*/ -/*---------------------------------------------------------------------*/ - -#include -#include -#include -#include -#include "global.h" -#include "queue.h" -#include "polverts.h" -#include "triangulate.h" -#include "ties.h" -#include "outputex.h" -#include "options.h" -#include "local.h" - -BOOL new_vertex(double difference, int id1,int id2, - struct vert_struct *n) -{ - /* Is the difference between id1 and id2 (2 normal vertices that - mapped to the same vertex) greater than the - threshold that was specified? - */ - struct vert_struct *pn1,*pn2; - double dot_product; - double distance1, distance2,distance; - double rad; - char arg1[100]; - char arg2[100]; - - pn1 = n + id1; - pn2 = n + id2; - - dot_product = ((pn1->x) * (pn2->x)) + - ((pn1->y) * (pn2->y)) + - ((pn1->z) * (pn2->z)); - /* Get the absolute value */ - if (dot_product < 0) - dot_product = dot_product * -1; - - distance1 = sqrt( (pn1->x * pn1->x) + - (pn1->y * pn1->y) + - (pn1->z * pn1->z) ); - distance2 = sqrt( (pn2->x * pn2->x) + - (pn2->y * pn2->y) + - (pn2->z * pn2->z) ); - distance = distance1 * distance2; - - rad = acos((double)dot_product/(double)distance); - /* convert to degrees */ - rad = (180 * rad)/PI; - - if ( rad <= difference) - return FALSE; - - /* double checking because of imprecision with floating - point acos function - */ - sprintf( arg1,"%.5f", rad ); - sprintf( arg2,"%.5f", difference ); - if ( strcmp( arg1, arg2 ) <=0 ) - return( FALSE ); - if ( rad <= difference) - return FALSE; - else - return TRUE; -} - -BOOL Check_VN(int vertex,int normal, struct vert_added *added) -{ - /* Check to see if we already added this vertex and normal */ - register int x,n; - - n = (added+vertex)->num; - for (x = 0; x < n; x++) - { - if (*((added+vertex)->normal+x) == normal) - return TRUE; - } - return FALSE; -} - -BOOL norm_array(int id, int vertex, double normal_difference, - struct vert_struct *n, int num_vert) -{ - static int last; - static struct vert_added *added; - register int x; - static BOOL first = TRUE; - - if (first) - { - /* This is the first time that we are in here, so we will allocate - a structure that will save the vertices that we added, so that we - do not add the same thing twice - */ - first = FALSE; - added = (struct vert_added *) malloc (sizeof (struct vert_added ) * num_vert); - /* The number of vertices added for each vertex must be initialized to - zero - */ - for (x = 0; x < num_vert; x++) - (added+x)->num = 0; - } - - if (vertex) - /* Set the pointer to the vertex, we will be calling again with the - normal to fill it with - */ - last = id; - else - { - /* Fill the pointer with the id of the normal */ - if (*(vert_norms + last) == 0) - *(vert_norms + last) = id; - else if ((*(vert_norms + last) != id) && ((int)normal_difference != 360)) - { - /* difference is big enough, we need to create a new vertex */ - if (new_vertex(normal_difference,id,*(vert_norms + last),n)) - { - /* First check to see if we added this vertex and normal already */ - if (Check_VN(last,id,added)) - return FALSE; - /* OK, create the new vertex, and have its id = the number of vertices - and its normal what we have here - */ - vert_norms = realloc(vert_norms, sizeof(int) * (num_vert + 1)); - if (!vert_norms) - { - printf("Allocation error - aborting\n"); - exit(1); - } - *(vert_norms + num_vert) = id; - /* We created a new vertex, now put it in our added structure so - we do not add the same thing twice - */ - (added+last)->num = (added+last)->num + 1; - if ((added+last)->num == 1) - { - /* First time */ - (added+last)->normal = (int *) malloc (sizeof (int ) * 1); - *((added+last)->normal) = id; - } - else - { - /* Not the first time, reallocate space */ - (added+last)->normal = realloc((added+last)->normal,sizeof(int) * (added+last)->num); - *((added+last)->normal+((added+last)->num-1)) = id; - } - return TRUE; - } - } - } - return FALSE; -} - -void add_texture(int id,BOOL vertex) -{ - /* Save the texture with its vertex for future use when outputting */ - static int last; - - if (vertex) - last = id; - else - *(vert_texture+last) = id; -} - -int add_vert_id(int id, int index_count) -{ - register int x; - - /* Test if degenerate, if so do not add degenerate vertex */ - for (x = 1; x < index_count ; x++) - { - if (ids[x] == id) - return 0; - } - ids[index_count] = id; - return 1; -} - -void add_norm_id(int id, int index_count) -{ - norms[index_count] = id; -} - -void AddNewFace(int ids[STRIP_MAX], int vert_count, int face_id, - int norms[STRIP_MAX]) -{ - PF_FACES pfNode; - int *pTempInt; - int *pnorms; - F_EDGES **pTempVertptr; - int *pTempmarked, *pTempwalked; - register int y,count = 0; - - /* Add a new face into our face data structure */ - - pfNode = (PF_FACES) malloc(sizeof(F_FACES) ); - if ( pfNode ) - { - pfNode->pPolygon = (int*) malloc(sizeof(int) * (vert_count) ); - pfNode->pNorms = (int*) malloc(sizeof(int) * (vert_count) ); - pfNode->VertandId = (F_EDGES**)malloc(sizeof(F_EDGES*) * (vert_count)); - pfNode->marked = (int*)malloc(sizeof(int) * (vert_count)); - pfNode->walked = (int*)malloc(sizeof(int) * (vert_count)); - } - pTempInt =pfNode->pPolygon; - pnorms = pfNode->pNorms; - pTempmarked = pfNode->marked; - pTempwalked = pfNode->walked; - pTempVertptr = pfNode->VertandId; - pfNode->nPolSize = vert_count; - pfNode->seen = -1; - pfNode->seen2 = -1; - for (y=1;y<=vert_count;y++) - { - *(pTempInt + count) = ids[y]; - *(pnorms + count) = norms[y]; - *(pTempmarked + count) = FALSE; - *(pTempwalked + count) = -1; - *(pTempVertptr+count) = NULL; - count++; - } - AddHead(PolFaces[face_id-1],(PLISTINFO) pfNode); -} - - -void CopyFace(int ids[STRIP_MAX], int vert_count, int face_id, - int norms[STRIP_MAX]) -{ - PF_FACES pfNode; - int *pTempInt; - int *pnorms; - F_EDGES **pTempVertptr; - int *pTempmarked, *pTempwalked; - register int y,count = 0; - - /* Copy a face node into a new node, used after the global algorithm - is run, so that we can save whatever is left into a new structure - */ - - pfNode = (PF_FACES) malloc(sizeof(F_FACES) ); - if ( pfNode ) - { - pfNode->pPolygon = (int*) malloc(sizeof(int) * (vert_count) ); - pfNode->pNorms = (int*) malloc(sizeof(int) * (vert_count) ); - pfNode->VertandId = (F_EDGES**)malloc(sizeof(F_EDGES*) * (vert_count)); - pfNode->marked = (int*)malloc(sizeof(int) * (vert_count)); - pfNode->walked = (int*)malloc(sizeof(int) * (vert_count)); - } - pTempInt =pfNode->pPolygon; - pnorms = pfNode->pNorms; - pTempmarked = pfNode->marked; - pTempwalked = pfNode->walked; - pTempVertptr = pfNode->VertandId; - pfNode->nPolSize = vert_count; - pfNode->seen = -1; - pfNode->seen2 = -1; - for (y=0;y v2) - { - t = v1; - v1 = v2; - v2 = t; - } - - pListHead = PolEdges[v1]; - temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count); - if (temp == NULL) - { - printf("Have the wrong edge \n:"); - exit(1); - } - - while (flag) - { - if (v2 == temp->edge[0]) - return; - else - temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,++count); - } -} - -void Add_AdjEdge(int v1,int v2,int fnum,int index1 ) -{ - PF_EDGES temp = NULL; - PF_FACES temp2 = NULL; - PF_EDGES pfNode; - ListHead *pListHead; - ListHead *pListFace; - BOOL flag = TRUE; - register int count = 0; - register int t,v3 = -1; - - if (v1 > v2) - { - t = v1; - v1 = v2; - v2 = t; - } - pListFace = PolFaces[fnum]; - temp2 = (PF_FACES) PeekList(pListFace,LISTHEAD,0); - pListHead = PolEdges[v1]; - temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count); - if (temp == NULL) - flag = FALSE; - count++; - while (flag) - { - if (v2 == temp->edge[0]) - { - /* If greater than 2 polygons adjacent to an edge, then we will - only save the first 2 that we found. We will have a small performance - hit, but this does not happen often. - */ - if (temp->edge[2] == -1) - temp->edge[2] = fnum; - else - v3 = temp->edge[2]; - flag = FALSE; - } - else - { - temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count); - count++; - if (temp == NULL) - flag = FALSE; - } - } - - /* Did not find it */ - if (temp == NULL) - { - pfNode = (PF_EDGES) malloc(sizeof(F_EDGES) ); - if ( pfNode ) - { - pfNode->edge[0] = v2; - pfNode->edge[1] = fnum; - pfNode->edge[2] = v3; - AddTail( PolEdges[v1], (PLISTINFO) pfNode ); - } - else - { - printf("Out of memory!\n"); - exit(1); - } - - *(temp2->VertandId+index1) = pfNode; - } - else - *(temp2->VertandId+index1) = temp; -} diff --git a/Tools/Stripe_w/add.h b/Tools/Stripe_w/add.h deleted file mode 100644 index fb37f729a..000000000 --- a/Tools/Stripe_w/add.h +++ /dev/null @@ -1,31 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: add.h ------------------------------------------------------------------------*/ - -#include "global.h" - -BOOL new_vertex(double difference, int id1,int id2, - struct vert_struct *n); -BOOL Check_VN(int vertex,int normal, struct vert_added *added); -BOOL norm_array(int id, int vertex, double normal_difference, - struct vert_struct *n, int num_vert); -void add_texture(int id,BOOL vertex); -int add_vert_id(int id, int index_count); -void add_norm_id(int id, int index_count); -void AddNewFace(int ids[STRIP_MAX], int vert_count, int face_id, - int norms[STRIP_MAX]); -void CopyFace(int ids[STRIP_MAX], int vert_count, int face_id, - int norms[STRIP_MAX]); -void Add_Edge(int v1,int v2); -void Add_AdjEdge(int v1,int v2,int fnum,int index1 ); - - - diff --git a/Tools/Stripe_w/bands.c b/Tools/Stripe_w/bands.c deleted file mode 100644 index 161e8ccde..000000000 --- a/Tools/Stripe_w/bands.c +++ /dev/null @@ -1,569 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: bands.c - This file contains the main procedure code that will read in the - object and then call the routines that produce the triangle strips. -*/ -/*---------------------------------------------------------------------*/ - - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include -#include -#include -#include "global.h" -#include "polverts.h" -#include "triangulate.h" -#include "ties.h" -#include "outputex.h" -#include "options.h" -#include "local.h" -#include "init.h" -#include "free.h" -#include "add.h" - -/* TIMING for Windows */ -#ifdef WIN32 -# include -# include -/* TIMING for UNIX */ -#else -# include -# include -# include -# if defined(__FreeBSD__) -# ifndef HZ -# include -# define HZ CLK_TCK -# endif /* HZ */ -# else - extern long times( ); -# endif /* __FreeBSD__ */ - long elapsed() -{ - static long total = 0; - long cpu_time, dummy; - struct tms buffer; - times(&buffer); - dummy = buffer.tms_utime + buffer.tms_stime + - buffer.tms_cutime + buffer.tms_cstime; - cpu_time = ((dummy - total) * 1000) / HZ; - total = dummy; - return(cpu_time); -} -#endif /* WIN32 */ - - -int norms[STRIP_MAX]; -int *vert_norms; -int *vert_texture; - - -void get_time() -{ - /* For timing */ -#ifdef WIN32 - struct timeb timebuffer; - char *timeline; -#else - long timer; -#endif - - -#ifdef WIN32 - ftime( &timebuffer ); - timeline = ctime( & ( timebuffer.time ) ); - printf( "The time is %.19s.%hu %s", timeline, timebuffer.millitm, &timeline[20] ); -#else - timer = elapsed(); - printf("The time is %ld\n",timer); -#endif -} - -/* -** - Here the main program begins. It will start by loading in a .obj file - then it will convert the polygonal model into triangle strips. -** -*/ - -int main (int argc,char *argv[]) -{ - char *fname, *oname, *all,buff[255], *ptr, *ptr2; - FILE *file, *bands; - int face_id=0; - int vert_count=0; - int loop=0; - int num=0; - int num2=0; - - float center[3]; - int temp[STRIP_MAX],vertex,strips, swaps,tempi,cost,triangles; - int f,t,tr,g; - char *file_open; - int num_vert = 0, - num_faces = 0, - num_nvert = 0, - num_edges = 0, - num_texture = 0, - num_tris = 0; - double fra = 0.0; - BOOL texture, normal, normal_and_texture,quads = FALSE; - - /* Options variables */ - double norm_difference; - - /* Structures for the object */ - struct vert_struct *vertices = NULL, - *nvertices = NULL, - *pvertices = NULL, - *pnvertices = NULL; - - get_time(); - - /* - Scan the file once to find out the number of vertices, - vertice normals, and faces so we can set up some memory - structures - */ - /* Interpret the options specified */ - norm_difference = get_options(argc,argv,&f,&t,&tr,&g); - if (f == BINARY) - file_open = "rb"; - else - file_open = "r"; - - fname = argv[argc-2]; - oname = argv[argc-1]; - - printf ("Input file: %s Output file: %s\n", fname, oname); - printf ("Scanning...%s ",file_open); - - - /* File that will contain the triangle strip data */ - - bands = fopen(oname, "w"); - - /* File can be in binary for faster reading */ - if (file = fopen (fname,file_open)) - { - while (!feof (file)) - { - /* Read a line */ - if (f == BINARY) - fread (buff,sizeof(char) * 255,1, file); - else - fgets (buff, sizeof(char) * 255, file); - num++; - - printf("%d\r",num); - - - /* At a vertex */ - if (*buff == 'v') - { - /* At a normal */ - if (*(buff+1)=='n') - num_nvert++; - else if (*(buff+1)=='t') - num_texture++; - /* At a regular vertex */ - else - num_vert++; - } - /* At a face */ - else if (*buff == 'f') - { - num_faces++; - strtok(buff, " "); - tempi = 0; - while (strtok(NULL, " ") != NULL) tempi++; - num_tris += tempi - 2; - } - } - fclose (file); - } - else - { - printf("Error in the file name\n"); - exit(1); - } - - printf("%s pass 1\n",fname); - - /* Allocate structures for the information */ - Start_Face_Struct(num_faces); - vertices = (struct vert_struct *) - malloc (sizeof (struct vert_struct) * num_vert); - - if (num_nvert > 0) { - nvertices = (struct vert_struct *) - malloc (sizeof (struct vert_struct) * num_nvert); - vert_norms = (int *) malloc (sizeof (int) * num_vert); - /* - Initialize entries to zero, in case there are 2 hits - to the same vertex we will know it - used for determining - the normal difference - */ - init_vert_norms(num_vert); - } else { - nvertices = NULL; - } - - if (num_texture > 0) { - vert_texture = (int *) malloc (sizeof(int) * num_vert); - init_vert_texture(num_vert); - } - - /* - Set up the temporary 'p' pointers - */ - pvertices = vertices; - pnvertices = nvertices; - - /* Load the object into memory */ - /*printf (" Loading...");*/ - - fprintf(bands,"#%s: a triangle strip representation created by STRIPE.\n#This is a .objf file\n#by Francine Evans\n",fname); - - /* File will be put in a list for faster execution if file is in binary */ - if (file = fopen(fname,file_open)) { - if (f == BINARY) { - all = (char *) malloc (sizeof(char) * 255 * num); - fread(all,sizeof(char) * 255 * num, 1, file); - ptr = all; - } else { - ptr = (char *) malloc (sizeof(char) * 255 * num); - } - } - - - while (num > 0) { - num--; - - printf("%d\r",num); - - if (f == ASCII) { - fgets (ptr, sizeof(char) * 255, file); - } else { - ptr = ptr + 255; - } - - /* Load in vertices/normals */ - if (*ptr == 'v') { - if (*(ptr+1)=='n') { - sscanf (ptr+3,"%lf%lf%lf", - &(pnvertices->x), - &(pnvertices->y), - &(pnvertices->z)); - fprintf(bands,"vn %f %f %f\n", - pnvertices->x,pnvertices->y,pnvertices->z); - ++pnvertices; - } else if (*(ptr+1)=='t') { - sscanf (ptr+3,"%f%f%f",¢er[0],¢er[1],¢er[2]); - fprintf(bands,"vt %f %f %f\n",center[0],center[1],center[2]); - } else { - sscanf (ptr+2,"%lf%lf%lf", - &(pvertices->x), - &(pvertices->y), - &(pvertices->z)); - fprintf(bands,"v %f %f %f\n", - pvertices->x,pvertices->y,pvertices->z); - ++pvertices; - } - } else if (*ptr == 'f') { - /* Read in faces */ - num2 = 0; - face_id++; - ptr2 = ptr+1; - normal = FALSE; texture = FALSE, normal_and_texture = FALSE; - while (*ptr2) { - if (*ptr2 >='0' && *ptr2 <='9') { - num2++; - ++ptr2; - while (*ptr2 && (*ptr2!=' ' && *ptr2!='/')) { - ptr2++; - } - /* There are normals in this line */ - if (*ptr2 == '/') { - if (*(ptr2+1) == '/') { - normal = TRUE; - } else { - texture = TRUE; - } - } else if (*ptr2 == ' ') { - if ((num2 == 3) && (texture)) { - normal_and_texture = TRUE; - } - } - } else { - ++ptr2; - } - } - - ptr2 = ptr+1; - - /* - loop on the number of numbers in this line of face data - */ - vert_count = 0; - - for (loop=0;loop'9') { - if (*ptr2 == '-') { - break; - } - ptr2++; - } - vertex = atoi(ptr2)-1; - if (vertex < 0) { - vertex = num_vert + vertex; - *ptr2 = ' '; - ptr2++; - } - /* - If there are either normals or textures with the vertices - in this file, the data alternates so we must read it this way - */ - if ( (normal) && (!normal_and_texture)) { - if (loop%2) { - add_norm_id(vertex,vert_count); - /* - Test here to see if we added a new vertex, since the - vertex has more than one normal and the 2 normals are greater - than the threshold specified - */ - if (norm_array(vertex,0,norm_difference,nvertices,num_vert)) { - /* - Add a new vertex and change the - id of the vertex that we just read to the id of the new - vertex that we just added - */ - /* - Put it in the output file, note the added vertices will - be after the normals and separated from the rest of the - vertices. Will not affect our viewer - */ - fprintf(bands,"v %f %f %f\n", - (vertices + temp[vert_count - 1])->x, - (vertices + temp[vert_count - 1])->y, - (vertices + temp[vert_count - 1])->z); - num_vert++; - temp[vert_count - 1] = num_vert - 1; - if (!(add_vert_id(num_vert - 1,vert_count))) { - vert_count--; - } - } - } else { - /* the vertex */ - temp[vert_count] = vertex ; - vert_count++; - if (!(add_vert_id(vertex,vert_count))) { - vert_count--; - } - norm_array(vertex,1,norm_difference,nvertices,num_vert); - } - } else if (normal_and_texture) { - /* Else there are vertices and textures with the data */ - if( !((loop+1)%3)) { - add_norm_id(vertex,vert_count); - /* - Test here to see if we added a new vertex, since the - vertex has more than one normal and the 2 normals are greater - than the threshold specified - */ - if (norm_array(vertex,0,norm_difference,nvertices,num_vert)) { - /* - Add a new vertex and change the - id of the vertex that we just read to the id of the new - vertex that we just added - */ - /* - Put it in the output file, note the added vertices will - be after the normals and separated from the rest of the - vertices. Will not affect our viewer - */ - fprintf(bands,"v %f %f %f\n", - (vertices + temp[vert_count - 1])->x, - (vertices + temp[vert_count - 1])->y, - (vertices + temp[vert_count - 1])->z); - num_vert++; - temp[vert_count - 1] = num_vert - 1; - if (!(add_vert_id(num_vert - 1,vert_count))) { - vert_count--; - } - } - } else if ((loop == 0) || (*(ptr2-1) == ' ')) { - /* the vertex */ - temp[vert_count] = vertex ; - vert_count++; - if (vert_count == 4) { - quads = TRUE; - } - if (!(add_vert_id(vertex,vert_count))) { - vert_count--; - } - add_texture(vertex,TRUE); - norm_array(vertex,1,norm_difference,nvertices,num_vert); - } else { - /* The texture */ - add_texture(vertex,FALSE); - } - } else if ( texture ) { - /* the vertex */ - if (!(loop%2)) { - temp[vert_count] = vertex ; - vert_count++; - if (vert_count == 4) - quads = TRUE; - add_texture(vertex,TRUE); - if (!(add_vert_id(vertex,vert_count))) - vert_count--; - norm_array(vertex,1,norm_difference,nvertices,num_vert); - } else { - /* texture */ - add_texture(vertex,FALSE); - } - } else { - /*** no nvertices ***/ - temp[vert_count] = vertex ; - vert_count++; - if (vert_count == 4) - quads = TRUE; - if (!(add_vert_id(vertex,vert_count))) - vert_count--; - } - while (*ptr2>='0' && *ptr2<='9') - ptr2++; - } - /* Done with the polygon */ - num_edges += vert_count; - /* add it to face structure */ - if (vert_count >= 3) - AddNewFace(ids,vert_count,face_id,norms); - else - face_id--; - if (vert_count == 4) - quads = TRUE; - } - else if ((g == TRUE) && (face_id > 0) - && ((*ptr == 'g') || (*ptr == 's') || (*ptr == 'm') || (*ptr == 'o'))) - { - /* - The user specified that the strips will be contained in each group - from the data file, so we just finished a group and will find the - triangle strips in it. - */ - Start_Edge_Struct(num_vert); - Find_Adjacencies(face_id); - if (quads) - { - Init_Table_SGI(); - Build_SGI_Table(num_vert,face_id); - /* Code for lengths of walks in each direction */ - /* Save_Walks(face_id,TRUE); */ - Save_Walks(face_id); - - /* Code for finding the bands */ - Find_Bands(face_id,bands,&swaps,&strips,&cost,&triangles,num_nvert,vert_norms,num_texture,vert_texture); - - /* - Remove the faces that we did so that we can - run the strip code on the rest of the faces that are left - */ - if (cost != 0) - { - printf("Total %d triangles with %d cost\n",triangles,cost); - Save_Rest(&face_id); - printf("We saved %d .... now doing the local algorithm\n",face_id); - fprintf(bands,"\n#local\n"); - End_Edge_Struct(num_vert); - Start_Edge_Struct(num_vert); - Find_Adjacencies(face_id); - } - } - - SGI_Strip(num_vert,face_id,bands,t,tr); - - /* Get the total cost */ - Output_TriEx(-1,-2,-3,NULL,-1,-20,cost); - - End_Face_Struct(num_faces); - End_Edge_Struct(num_vert); - cost = 0; - face_id = 0; - quads = FALSE; - Start_Face_Struct(num_faces-face_id); - num_faces = num_faces - face_id; - Free_Strips(); - } - } - - /* Done reading in all the information into data structures */ - num_faces = face_id; - fclose (file); - - printf("Input Done.\n\n"); - - free(vertices); - free(nvertices); - - printf ("Vertices: %d\nNormals: %d\nFaces: %d\n",num_vert,num_nvert,num_faces); - - Start_Edge_Struct(num_vert); - Find_Adjacencies(num_faces); - - /* Initialize it */ - Init_Table_SGI(); - /* Build it */ - Build_SGI_Table(num_vert,num_faces); - - InitStripTable(); - - if (quads) { - /* Code for lengths of walks in each direction */ - /* Save_Walks(num_faces,TRUE); */ - Save_Walks(num_faces); - - /* Code for finding the bands */ - Find_Bands(num_faces,bands,&swaps,&strips,&cost,&triangles,num_nvert,vert_norms,num_texture,vert_texture); - /*printf("Total %d triangles with %d cost\n",triangles,cost);*/ - - /* - Remove the faces that we did so that we can - run the strip code on the rest of the faces that are left - */ - Save_Rest(&num_faces); - /*printf("We saved %d .... now doing the local algorithm\n",num_faces);*/ - fprintf(bands,"\n#local\n"); - End_Edge_Struct(num_vert); - Start_Edge_Struct(num_vert); - Find_Adjacencies(num_faces); - } - - SGI_Strip(num_vert,num_faces,bands,t,tr); - - /* Get the total cost */ - Output_TriEx(-1,-2,-3,NULL,-1,-20,cost); - - End_Face_Struct(num_faces); - End_Edge_Struct(num_vert); - fclose(bands); - - get_time(); - - return(0); -} - diff --git a/Tools/Stripe_w/common.c b/Tools/Stripe_w/common.c deleted file mode 100644 index ca836e19f..000000000 --- a/Tools/Stripe_w/common.c +++ /dev/null @@ -1,810 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: common.c - This file contains common code used in both the local and global algorithm -*/ -/*---------------------------------------------------------------------*/ - - -#include -#include "polverts.h" -#include "extend.h" -#include "output.h" -#include "triangulate.h" -#include "util.h" -#include "add.h" - -int Old_Adj(int face_id) -{ - /* Find the bucket that the face_id is currently in, - because maybe we will be deleting it. - */ - PF_FACES temp = NULL; - ListHead *pListHead; - int size,y; - - pListHead = PolFaces[face_id]; - temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); - if ( temp == NULL ) - { - printf("The face was already deleted, there is an error\n"); - exit(0); - } - - size = temp->nPolSize; - if (Done(face_id,size,&y) == NULL) - { - printf("There is an error in finding the face\n"); - exit(0); - } - return y; -} - -int Number_Adj(int id1, int id2, int curr_id) -{ - /* Given edge whose endpoints are specified by id1 and id2, - determine how many polygons share this edge and return that - number minus one (since we do not want to include the polygon - that the caller has already). - */ - - int size,y,count=0; - PF_EDGES temp = NULL; - PF_FACES temp2 = NULL; - ListHead *pListHead; - BOOL there= FALSE; - - /* Always want smaller id first */ - switch_lower(&id1,&id2); - - pListHead = PolEdges[id1]; - temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count); - if (temp == NULL) - /* new edge that was created might not be here */ - return 0; - while (temp->edge[0] != id2) - { - count++; - temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count); - if (temp == NULL) - /* This edge was not there in the original, which - mean that we created it in the partial triangulation. - So it is adjacent to nothing. - */ - return 0; - } - /* Was not adjacent to anything else except itself */ - if (temp->edge[2] == -1) - return 0; - else - { - /* It was adjacent to another polygon, but maybe we did this - polygon already, and it was done partially so that this edge - could have been done - */ - if (curr_id != temp->edge[1]) - { - /* Did we use this polygon already?and it was deleted - completely from the structure - */ - pListHead = PolFaces[temp->edge[1]]; - temp2 = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); - if (Done(temp->edge[1],temp2->nPolSize,&size) == NULL) - return 0; - } - else - { - pListHead = PolFaces[temp->edge[2]]; - temp2 = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); - if (Done(temp->edge[2],temp2->nPolSize,&size)== NULL) - return 0; - } - - /* Now we have to check whether it was partially done, before - we can say definitely if it is adjacent. - Check each edge of the face and tally the number of adjacent - polygons to this face. - */ - if ( temp2 != NULL ) - { - /* Size of the polygon */ - size = temp2->nPolSize; - for (y = 0; y< size; y++) - { - /* If we are doing partial triangulation, we must check - to see whether the edge is still there in the polygon, - since we might have done a portion of the polygon - and saved the rest for later. - */ - if (y != (size-1)) - { - if( ((id1 == *(temp2->pPolygon+y)) && (id2 ==*(temp2->pPolygon+y+1))) - || ((id2 == *(temp2->pPolygon+y)) && (id1 ==*(temp2->pPolygon+y+1)))) - /* edge is still there we are ok */ - there = TRUE; - } - else - { - if( ((id1 == *(temp2->pPolygon)) && (id2 == *(temp2->pPolygon+size-1))) - || ((id2 == *(temp2->pPolygon)) && (id1 ==*(temp2->pPolygon+size-1)))) - /* edge is still there we are ok */ - there = TRUE; - } - } - } - - if (there ) - return 1; - return 0; - } -} - -int Min_Adj(int id) -{ - /* Used for the lookahead to break ties. It will - return the minimum adjacency found at this face. - */ - int y,numverts,t,x=60; - PF_FACES temp=NULL; - ListHead *pListHead; - - /* If polygon was used then we can't use this face */ - if (Done(id,59,&y) == NULL) - return 60; - - /* It was not used already */ - pListHead = PolFaces[id]; - temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); - if ( temp != NULL ) - { - numverts = temp->nPolSize; - for (y = 0; y< numverts; y++) - { - if (y != (numverts-1)) - t = Number_Adj(*(temp->pPolygon+y),*(temp->pPolygon+y+1),id); - else - t = Number_Adj(*(temp->pPolygon),*(temp->pPolygon+(numverts-1)),id); - if (t < x) - x = t; - } - } - if (x == -1) - { - printf("Error in the look\n"); - exit(0); - } - return x; -} - - - -void Edge_Least(int *index,int *new1,int *new2,int face_id,int size) -{ - /* We had a polygon without an input edge and now we re going to pick one - of the edges with the least number of adjacencies to be the input - edge - */ - register int x,value,smallest=60; - - for (x = 0; xpPolygon+y) == id2) && (*(temp->pPolygon+y+1) != id3)) - || ((*(temp->pPolygon+y) == id3) && (*(temp->pPolygon+y+1) != id2))) - { - saved[x++] = Number_Adj(*(temp->pPolygon+y),*(temp->pPolygon+y+1),face_id); - big_saved[z++] = saved[x-1]; - } - else - big_saved[z++] = Number_Adj(*(temp->pPolygon+y),*(temp->pPolygon+y+1),face_id); - } - else - { - if (((*(temp->pPolygon) == id2) && (*(temp->pPolygon+size-1) != id3)) - || ((*(temp->pPolygon) == id3) && (*(temp->pPolygon+size-1) != id2))) - { - saved[x++] = Number_Adj(*(temp->pPolygon),*(temp->pPolygon+size-1),face_id); - big_saved[z++] = saved[x-1]; - } - else - big_saved[z++] = Number_Adj(*(temp->pPolygon),*(temp->pPolygon+size-1),face_id); - } - } - /* There was an input edge */ - if (x == 2) - { - if (saved[0] < saved[1]) - /* Count the polygon that we will be cutting as another adjacency*/ - *min = saved[0] + 1; - else - *min = saved[1] + 1; - } - /* There was not an input edge */ - else - { - if (z != size) - { - printf("There is an error with the z %d %d\n",size,z); - exit(0); - } - *min = 60; - for (x = 0; x < size; x++) - { - if (*min > big_saved[x]) - *min = big_saved[x]; - } - } -} - - -void New_Face (int face_id, int v1, int v2, int v3) -{ - /* We want to change the face that was face_id, we will - change it to a triangle, since the rest of the polygon - was already outputtted - */ - ListHead *pListHead; - PF_FACES temp = NULL; - - pListHead = PolFaces[face_id]; - temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0); - /* Check each edge of the face and tally the number of adjacent - polygons to this face. - */ - if ( temp != NULL ) - { - /* Size of the polygon */ - if (temp->nPolSize != 4) - { - printf("There is a miscalculation in the partial\n"); - exit (0); - } - temp->nPolSize = 3; - *(temp->pPolygon) = v1; - *(temp->pPolygon+1) = v2; - *(temp->pPolygon+2) = v3; - } -} - -void New_Size_Face (int face_id) -{ - /* We want to change the face that was face_id, we will - change it to a triangle, since the rest of the polygon - was already outputtted - */ - ListHead *pListHead; - PF_FACES temp = NULL; - - pListHead = PolFaces[face_id]; - temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); - /* Check each edge of the face and tally the number of adjacent - polygons to this face. - */ - if ( temp != NULL ) - (temp->nPolSize)--; - else - printf("There is an error in updating the size\n"); -} - - - -void Check_In_Quad(int face_id,int *min) -{ - /* Check to see what the adjacencies are for the polygons that - are inside the quad, ie the 2 triangles that we can form. - */ - ListHead *pListHead; - int y,id1,id2,id3,x=0; - int saved[4]; - PF_FACES temp; - register int size = 4; - - pListHead = PolFaces[face_id]; - temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); - - /* Get the input edge that we came in on */ - Last_Edge(&id1,&id2,&id3,0); - - /* Now find the adjacencies for the inside triangles */ - for (y = 0; y< size; y++) - { - /* Will not do this if the edge is the input edge */ - if (y != (size-1)) - { - if ((((*(temp->pPolygon+y) == id2) && (*(temp->pPolygon+y+1) == id3))) || - (((*(temp->pPolygon+y) == id3) && (*(temp->pPolygon+y+1) == id2)))) - saved[x++] = -1; - else - { - if (x == 4) - { - printf("There is an error in the check in quad \n"); - exit(0); - } - /* Save the number of Adjacent Polygons to this edge */ - saved[x++] = Number_Adj(*(temp->pPolygon+y),*(temp->pPolygon+y+1),face_id); - } - } - else if ((((*(temp->pPolygon) == id2) && (*(temp->pPolygon+size-1) == id3))) || - (((*(temp->pPolygon) == id3) && (*(temp->pPolygon+size-1) == id2))) ) - saved[x++] = -1; - else - { - if (x == 4) - { - printf("There is an error in the check in quad \n"); - exit(0); - } - /* Save the number of Adjacent Polygons to this edge */ - saved[x++] = Number_Adj(*(temp->pPolygon),*(temp->pPolygon+size-1),face_id); - - } - } - if (x != 4) - { - printf("Did not enter all the values %d \n",x); - exit(0); - } - - *min = 10; - for (x=0; x<4; x++) - { - if (x!= 3) - { - if ((saved[x] != -1) && (saved[x+1] != -1) && - ((saved[x] + saved[x+1]) < *min)) - *min = saved[x] + saved[x+1]; - } - else - { - if ((saved[0] != -1) && (saved[x] != -1) && - ((saved[x] + saved[0]) < *min)) - *min = saved[0] + saved[x]; - } - } -} - - - -int Get_Output_Edge(int face_id, int size, int *index,int id2,int id3) -{ - /* Return the vertex adjacent to either input1 or input2 that - is adjacent to the least number of polygons on the edge that - is shared with either input1 or input2. - */ - register int x=0,y; - int saved[2]; - int edges[2][1]; - - for (y = 0; y < size; y++) - { - if (y != (size-1)) - { - if (((*(index+y) == id2) && (*(index+y+1) != id3)) - || ((*(index+y) == id3) && (*(index+y+1) != id2))) - { - saved[x++] = Number_Adj(*(index+y),*(index+y+1),face_id); - edges[x-1][0] = *(index+y+1); - } - else if (y != 0) - { - if (( (*(index+y) == id2) && (*(index+y-1) != id3) ) || - ( (*(index+y) == id3) && (*(index+y-1) != id2)) ) - { - saved[x++] = Number_Adj(*(index+y),*(index+y-1),face_id); - edges[x-1][0] = *(index+y-1); - } - } - else if (y == 0) - { - if (( (*(index) == id2) && (*(index+size-1) != id3) ) || - ( (*(index) == id3) && (*(index+size-1) != id2)) ) - { - saved[x++] = Number_Adj(*(index),*(index+size-1),face_id); - edges[x-1][0] = *(index+size-1); - } - } - - } - else - { - if (((*(index+size-1) == id2) && (*(index) != id3)) - || ((*(index+size-1) == id3) && (*(index) != id2))) - { - saved[x++] = Number_Adj(*(index),*(index+size-1),face_id); - edges[x-1][0] = *(index); - } - - if (( (*(index+size-1) == id2) && (*(index+y-1) != id3) ) || - ( (*(index+size-1) == id3) && (*(index+y-1) != id2)) ) - { - saved[x++] = Number_Adj(*(index+size-1),*(index+y-1),face_id); - edges[x-1][0] = *(index+y-1); - } - } - } - if ((x != 2)) - { - printf("There is an error in getting the input edge %d \n",x); - exit(0); - } - if (saved[0] < saved[1]) - return edges[0][0]; - else - return edges[1][0]; - -} - -void Get_Input_Edge(int *index,int id1,int id2,int id3,int *new1,int *new2,int size, - int face_id) -{ - /* We had a polygon without an input edge and now we are going to pick one - as the input edge. The last triangle was id1,id2,id3, we will try to - get an edge to have something in common with one of those vertices, otherwise - we will pick the edge with the least number of adjacencies. - */ - - register int x; - int saved[3]; - - saved[0] = -1; - saved[1] = -1; - saved[2] = -1; - - /* Go through the edges to see if there is one in common with one - of the vertices of the last triangle that we had, preferably id2 or - id3 since those are the last 2 things in the stack of size 2. - */ - for (x=0; x< size; x++) - { - if (*(index+x) == id1) - { - if (x != (size-1)) - saved[0] = *(index+x+1); - else - saved[0] = *(index); - } - - if (*(index+x) == id2) - { - if (x != (size-1)) - saved[1] = *(index+x+1); - else - saved[1] = *(index); - } - - if (*(index+x) == id3) - { - if (x != (size -1)) - saved[2] = *(index+x+1); - else - saved[2] = *(index); - } - } - /* Now see what we saved */ - if (saved[2] != -1) - { - *new1 = id3; - *new2 = saved[2]; - return; - } - else if (saved[1] != -1) - { - *new1 = id2; - *new2 = saved[1]; - return; - } - else if (saved[0] != -1) - { - *new1 = id1; - *new2 = saved[0]; - return; - } - /* We did not find anything so get the edge with the least number of adjacencies */ - Edge_Least(index,new1,new2,face_id,size); - -} - -int Find_Face(int current_face, int id1, int id2, int *bucket) -{ - /* Find the face that is adjacent to the edge and is not the - current face. - */ - register int size,y,count=0; - PF_EDGES temp = NULL; - PF_FACES temp2 = NULL; - ListHead *pListHead; - int next_face; - BOOL there = FALSE; - - - /* Always want smaller id first */ - switch_lower(&id1,&id2); - - pListHead = PolEdges[id1]; - temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count); - /* The input edge was a new edge */ - if (temp == NULL) - return -1; - - while (temp->edge[0] != id2) - { - count++; - temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count); - /* The input edge was a new edge */ - if (temp == NULL) - return -1; - } - /* Was not adjacent to anything else except itself */ - if (temp->edge[2] == -1) - return -1; - else - { - if (temp->edge[2] == current_face) - next_face = temp->edge[1]; - else - next_face = temp->edge[2]; - } - /* We have the other face adjacent to this edge, it is - next_face. - */ - pListHead = PolFaces[next_face]; - temp2 = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); - - /* See if the face was already deleted, and where - it is if it was not - */ - - if (Done(next_face,59,bucket) == NULL) - return -1; - - /* Make sure the edge is still in this polygon, and that it is not - done - */ - /* Size of the polygon */ - size = temp2->nPolSize; - for (y = 0; y< size; y++) - { - /* Make sure that the edge is still in the - polygon and was not deleted, because if the edge was - deleted, then we used it already. - */ - if (y != (size-1)) - { - if( ((id1 == *(temp2->pPolygon+y)) && (id2 ==*(temp2->pPolygon+y+1))) - || ((id2 == *(temp2->pPolygon+y)) && (id1 ==*(temp2->pPolygon+y+1)))) - /* edge is still there we are ok */ - there = TRUE; - } - else - { - if( ((id1 == *(temp2->pPolygon)) && (id2 ==*(temp2->pPolygon+size-1))) - || ((id2 == *(temp2->pPolygon)) && (id1 ==*(temp2->pPolygon+size-1)))) - /* edge is still there we are ok */ - there = TRUE; - } - } - - if (!there) - /* Edge already used and deleted from the polygon*/ - return -1; - else - return next_face; -} - -BOOL Look_Up(int id1,int id2,int face_id) -{ - /* See if the endpoints of the edge specified by id1 and id2 - are adjacent to the face with face_id - */ - register int count = 0; - PF_EDGES temp = NULL; - ListHead *pListHead; - - /* Always want smaller id first */ - switch_lower(&id1,&id2); - - pListHead = PolEdges[id1]; - temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count); - if (temp == NULL) - /* Was a new edge that we created */ - return 0; - - while (temp->edge[0] != id2) - { - count++; - temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count); - if (temp == NULL) - /* Was a new edge that we created */ - return 0; - } - /* Was not adjacent to anything else except itself */ - if ((temp->edge[2] == face_id) || (temp->edge[1] == face_id)) - { - /* Edge was adjacent to face, make sure that edge is - still there - */ - if (Exist(face_id,id1,id2)) - return 1; - else - return 0; - } - else - return 0; -} - - -void Add_Id_Strips(int id, int where) -{ - /* Just save the triangle for later */ - P_STRIPS pfNode; - - pfNode = (P_STRIPS) malloc(sizeof(Strips) ); - if ( pfNode ) - { - pfNode->face_id = id; - if (where == 1) - AddTail(strips[0],(PLISTINFO) pfNode); - /* We are backtracking in the strip */ - else - AddHead(strips[0],(PLISTINFO) pfNode); - } - else - { - printf("There is not enough memory to allocate for the strips\n"); - exit(0); - } -} - - -int Num_Adj(int id1, int id2) -{ - /* Given edge whose endpoints are specified by id1 and id2, - determine how many polygons share this edge and return that - number minus one (since we do not want to include the polygon - that the caller has already). - */ - - PF_EDGES temp = NULL; - ListHead *pListHead; - register count=-1; - - /* Always want smaller id first */ - switch_lower(&id1,&id2); - - pListHead = PolEdges[id1]; - temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count); - if (temp == NULL) - { - printf("There is an error in the creation of the table \n"); - exit(0); - } - while (temp->edge[0] != id2) - { - count++; - temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count); - if (temp == NULL) - { - printf("There is an error in the creation of the table\n"); - exit(0); - } - } - /* Was not adjacent to anything else except itself */ - if (temp->edge[2] == -1) - return 0; - return 1; -} - - -void Add_Sgi_Adj(int bucket,int face_id) -{ - /* This routine will add the face to the proper bucket, - depending on how many faces are adjacent to it (what the - value bucket should be). - */ - P_ADJACENCIES pfNode; - - pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) ); - if ( pfNode ) - { - pfNode->face_id = face_id; - AddHead(array[bucket],(PLISTINFO) pfNode); - } - else - { - printf("Out of memory for the SGI adj list!\n"); - exit(0); - } -} - -void Find_Adjacencies(int num_faces) -{ - register int x,y; - register int numverts; - PF_FACES temp=NULL; - ListHead *pListHead; - - /* Fill in the adjacencies data structure for all the faces */ - for (x=0;xnPolSize; - if (numverts != 1) - { - for (y = 0; y< numverts; y++) - { - if (y != (numverts-1)) - Add_AdjEdge(*(temp->pPolygon+y),*(temp->pPolygon+y+1),x,y); - - else - Add_AdjEdge(*(temp->pPolygon),*(temp->pPolygon+(numverts-1)),x,numverts-1); - - } - } - temp = NULL; - } - } -} - - diff --git a/Tools/Stripe_w/common.h b/Tools/Stripe_w/common.h deleted file mode 100644 index aca19824b..000000000 --- a/Tools/Stripe_w/common.h +++ /dev/null @@ -1,42 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: common.h ------------------------------------------------------------------------*/ - -void Add_AdjEdge(int v1,int v2,int fnum,int index1 ); -void Find_Adjacencies(int num_faces); -void Add_Sgi_Adj(int bucket,int face_id); -int Num_Adj(int id1, int id2); -void Add_Id_Strips(int id, int where); -BOOL Look_Up(int id1,int id2,int face_id); -int Number_Adj(int id1, int id2, int curr_id); -int Old_Adj(int face_id); -int Min_Adj(int id); -int Find_Face(int current_face, int id1, int id2, int *bucket); -void Edge_Least(int *index,int *new1,int *new2,int face_id,int size); -void Get_Input_Edge(int *index,int id1,int id2,int id3,int *new1,int *new2, - int size, int face_id); -int Get_Output_Edge(int face_id, int size, int *index,int id2,int id3); -void Check_In_Polygon(int face_id, int *min, int size); -void Check_In_Quad(int face_id,int *min); -void New_Size_Face (int face_id); -void New_Face (int face_id, int v1, int v2, int v3); - - - - - - - - - - - - diff --git a/Tools/Stripe_w/extend.h b/Tools/Stripe_w/extend.h deleted file mode 100644 index 78c135e3a..000000000 --- a/Tools/Stripe_w/extend.h +++ /dev/null @@ -1,17 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: extend.h ------------------------------------------------------------------------*/ - -int Bottom_Left(); -int Top_Left(); -void Start_Edge(); - - diff --git a/Tools/Stripe_w/free.c b/Tools/Stripe_w/free.c deleted file mode 100644 index ad655fcf7..000000000 --- a/Tools/Stripe_w/free.c +++ /dev/null @@ -1,112 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: free.c - This file contains the code used to free the data structures. -*/ -/*---------------------------------------------------------------------*/ - -#include -#include -#include "polverts.h" - -ListHead *array[60]; -int id_array[60]; -ListHead *strips[1]; -ListHead *all_strips[100000]; /* Assume max 100000 strips */ - -void ParseAndFreeList( ListHead *pListHead ) -{ - register int c,num; - - /* Freeing a linked list */ - num = NumOnList(pListHead); - for (c = 0; c< num; c++) - RemHead(pListHead); -} - -void FreePolygonNode( PF_VERTS pfVerts) -{ - /* Free a vertex node */ - if ( pfVerts->pPolygon ) - free( pfVerts->pPolygon ); - free( pfVerts ); - -} - -void Free_Strips() -{ - /* Free strips data structure */ - if (strips[0] == NULL) - return; - else - ParseAndFreeList(strips[0]); -} - -void FreeFaceNode( PF_FACES pfFaces) -{ - /* Free face node */ - if ( pfFaces->pPolygon ) - free( pfFaces->pPolygon ); - free( pfFaces ); -} - - -void FreeFaceTable(int nSize) -{ - register int nIndex; - - for ( nIndex=0; nIndex < nSize; nIndex++ ) - { - if ( PolFaces[nIndex] != NULL ) - ParseAndFreeList( PolFaces[nIndex] ); - } - free( PolFaces ); -} - -void FreeEdgeTable(int nSize) -{ - register int nIndex; - - for ( nIndex=0; nIndex < nSize; nIndex++ ) - { - if ( PolEdges[nIndex] != NULL ) - ParseAndFreeList( PolEdges[nIndex] ); - } - free( PolEdges ); -} - - -void Free_All_Strips() -{ - - ListHead *pListHead; - register int y; - - for (y =0; ; y++) - { - pListHead = all_strips[y]; - if (pListHead == NULL) - return; - else - ParseAndFreeList(all_strips[y]); - } -} - -void End_Face_Struct(int numfaces) -{ - FreeFaceTable(numfaces); -} - -void End_Edge_Struct(int numverts) -{ - FreeEdgeTable(numverts); -} - - diff --git a/Tools/Stripe_w/free.h b/Tools/Stripe_w/free.h deleted file mode 100644 index 4c1d055c6..000000000 --- a/Tools/Stripe_w/free.h +++ /dev/null @@ -1,22 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: free.h ------------------------------------------------------------------------*/ - -void Free_All_Strips(); -void ParseAndFreeList( ListHead *pListHead ); -void FreePolygonNode( PF_VERTS pfVerts); -void Free_Strips(); -void FreeFaceTable(int nSize); -void FreeEdgeTable(int nSize); -void End_Face_Struct(int numfaces); -void End_Edge_Struct(int numverts); - - diff --git a/Tools/Stripe_w/global.h b/Tools/Stripe_w/global.h deleted file mode 100644 index 3538f82f4..000000000 --- a/Tools/Stripe_w/global.h +++ /dev/null @@ -1,44 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: global.h ------------------------------------------------------------------------*/ - -#ifndef _GLOBAL_H -#define _GLOBAL_H - - -#define VRDATA double -#define STRIP_MAX 60 - -#define TRUE 1 -#define FALSE 0 - -#ifndef PI -#define PI 3.1415926573 -#endif - -#define ATOI(C) (C -'0') -#define X 0 -#define Y 1 -#define Z 2 -#define EVEN(x) (((x) & 1) == 0) -#define MAX_BAND 10000 - -struct vert_struct { - VRDATA x, y, z; /* point coordinates */ -}; - -extern int ids[STRIP_MAX]; -extern int norms[STRIP_MAX]; -extern int *vert_norms; -extern int *vert_texture; - - -#endif _GLOBAL_H diff --git a/Tools/Stripe_w/init.c b/Tools/Stripe_w/init.c deleted file mode 100644 index 2e0f25885..000000000 --- a/Tools/Stripe_w/init.c +++ /dev/null @@ -1,217 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: init.c - This file contains the initialization of data structures. -*/ -/*---------------------------------------------------------------------*/ - -#include -#include -#include "global.h" -#include "polverts.h" - -void init_vert_norms(int num_vert) -{ - /* Initialize vertex/normal array to have all zeros to - start with. - */ - register int x; - - for (x = 0; x < num_vert; x++) - *(vert_norms + x) = 0; -} - -void init_vert_texture(int num_vert) -{ - /* Initialize vertex/normal array to have all zeros to - start with. - */ - register int x; - - for (x = 0; x < num_vert; x++) - *(vert_texture + x) = 0; -} - -BOOL InitVertTable( int nSize ) -{ - register int nIndex; - - /* Initialize the vertex table */ - PolVerts = (ListHead**) malloc(sizeof(ListHead*) * nSize ); - if ( PolVerts ) - { - for ( nIndex=0; nIndex < nSize; nIndex++ ) - { - PolVerts[nIndex] = NULL; - } - return( TRUE ); - } - return( FALSE ); -} - -BOOL InitFaceTable( int nSize ) -{ - register int nIndex; - - /* Initialize the face table */ - PolFaces = (ListHead**) malloc(sizeof(ListHead*) * nSize ); - if ( PolFaces ) - { - for ( nIndex=0; nIndex < nSize; nIndex++ ) - { - PolFaces[nIndex] = NULL; - } - return( TRUE ); - } - return( FALSE ); -} - -BOOL InitEdgeTable( int nSize ) -{ - register int nIndex; - - /* Initialize the edge table */ - PolEdges = (ListHead**) malloc(sizeof(ListHead*) * nSize ); - if ( PolEdges ) - { - for ( nIndex=0; nIndex < nSize; nIndex++ ) - { - PolEdges[nIndex] = NULL; - } - return( TRUE ); - } - return( FALSE ); -} - - -void InitStripTable( ) -{ - - PLISTHEAD pListHead; - - /* Initialize the strip table */ - pListHead = ( PLISTHEAD ) malloc(sizeof(ListHead)); - if ( pListHead ) - { - InitList( pListHead ); - strips[0] = pListHead; - } - else - { - printf("Out of memory !\n"); - exit(0); - } - -} - -void Init_Table_SGI() -{ - PLISTHEAD pListHead; - int max_adj = 60; - register int x; - - /* This routine will initialize the table that will - have the faces sorted by the number of adjacent polygons - to it. - */ - - for (x=0; x< max_adj; x++) - { - /* We are allowing the max number of sides of a polygon - to be max_adj. - */ - pListHead = ( PLISTHEAD ) malloc(sizeof(ListHead)); - if ( pListHead ) - { - InitList( pListHead ); - array[x] = pListHead; - } - else - { - printf("Out of memory !\n"); - exit(0); - } - } -} - -void BuildVertTable( int nSize ) -{ - register int nIndex; - PLISTHEAD pListHead; - - for ( nIndex=0; nIndex < nSize; nIndex++ ) - { - pListHead = ( PLISTHEAD ) malloc(sizeof(ListHead)); - if ( pListHead ) - { - InitList( pListHead ); - PolVerts[nIndex] = pListHead; - } - else - return; - - } -} - - -void BuildFaceTable( int nSize ) -{ - register int nIndex; - PLISTHEAD pListHead; - - for ( nIndex=0; nIndex < nSize; nIndex++ ) - { - pListHead = ( PLISTHEAD ) malloc(sizeof(ListHead)); - if ( pListHead ) - { - InitList( pListHead ); - PolFaces[nIndex] = pListHead; - } - else - return; - - } -} - -void BuildEdgeTable( int nSize ) -{ - register int nIndex; - PLISTHEAD pListHead; - - for ( nIndex=0; nIndex < nSize; nIndex++ ) - { - pListHead = ( PLISTHEAD ) malloc(sizeof(ListHead)); - if ( pListHead ) - { - InitList( pListHead ); - PolEdges[nIndex] = pListHead; - } - else - return; - } -} - -void Start_Face_Struct(int numfaces) -{ - if (InitFaceTable(numfaces)) - { - BuildFaceTable(numfaces); - } -} - -void Start_Edge_Struct(int numverts) -{ - if (InitEdgeTable(numverts)) - { - BuildEdgeTable(numverts); - } -} - - diff --git a/Tools/Stripe_w/init.h b/Tools/Stripe_w/init.h deleted file mode 100644 index fe9a05fd7..000000000 --- a/Tools/Stripe_w/init.h +++ /dev/null @@ -1,30 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: init.h ------------------------------------------------------------------------*/ - -void init_vert_norms(int num_vert); -void init_vert_texture(int num_vert); -BOOL InitVertTable( int nSize ); -BOOL InitFaceTable( int nSize ); -BOOL InitEdgeTable( int nSize ); -void InitStripTable( ); -void Init_Table_SGI(); -void BuildVertTable( int nSize ); -void BuildFaceTable( int nSize ); -void BuildEdgeTable( int nSize ); -void Start_Face_Struct(int numfaces); -void Start_Edge_Struct(int numverts); - - - - - - diff --git a/Tools/Stripe_w/local.c b/Tools/Stripe_w/local.c deleted file mode 100644 index 3f3e69da1..000000000 --- a/Tools/Stripe_w/local.c +++ /dev/null @@ -1,119 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: local.c - This file contains the code that initializes the data structures for - the local algorithm, and starts the local algorithm going. -*/ -/*---------------------------------------------------------------------*/ - -#include -#include -#include "polverts.h" -#include "local.h" -#include "triangulatex.h" -#include "sturctsex.h" -#include "common.h" -#include "outputex.h" -#include "util.h" -#include "init.h" - -void Find_StripsEx(FILE *output, FILE *strip,int *ties, int tie, - int triangulate, int swaps, int *next_id) -{ - /* This routine will peel off the strips from the model */ - - ListHead *pListHead; - P_ADJACENCIES temp = NULL; - register int max,bucket=0; - BOOL whole_flag = TRUE; - int dummy = 0; - - /* Set the last known input edge to be null */ - Last_Edge(&dummy,&dummy,&dummy,1); - - /* Search for lowest adjacency polygon and output strips */ - while (whole_flag) - { - bucket = -1; - /* Search for polygons in increasing number of adjacencies */ - while (bucket < 59) - { - bucket++; - pListHead = array[bucket]; - max = NumOnList(pListHead); - if (max > 0) - { - temp = (P_ADJACENCIES) PeekList(pListHead,LISTHEAD,0); - if (temp == NULL) - { - printf("Error in the buckets%d %d %d\n",bucket,max,0); - exit(0); - } - Polygon_OutputEx(temp,temp->face_id,bucket,pListHead, - output,strip,ties,tie,triangulate,swaps,next_id,1); - /* Try to extend backwards, if the starting polygon in the - strip had 2 or more adjacencies to begin with - */ - if (bucket >= 2) - Extend_BackwardsEx(temp->face_id,output,strip,ties,tie,triangulate,swaps,next_id); - break; - } - } - /* Went through the whole structure, it is empty and we are done. - */ - if ((bucket == 59) && (max == 0)) - whole_flag = FALSE; - - /* We just finished a strip, send dummy data to signal the end - of the strip so that we can output it. - */ - else - { - Output_TriEx(-1,-2,-3,output,-1,-10,1); - Last_Edge(&dummy,&dummy,&dummy,1); - } - } -} - - -void SGI_Strip(int num_verts,int num_faces,FILE *output, - int ties,int triangulate) - -{ - FILE *strip; - int next_id = -1,t=0; - - strip = fopen("output.d","w"); - /* We are going to output and find triangle strips - according the the method that SGI uses, ie always - choosing as the next triangle in our strip the triangle - that has the least number of adjacencies. We do not have - all triangles and will be triangulating on the fly those - polygons that have more than 3 sides. - */ - - /* Build a table that has all the polygons sorted by the number - of polygons adjacent to it. - */ - /* Initialize it */ - Init_Table_SGI(); - /* Build it */ - Build_SGI_Table(num_verts,num_faces); - - /* We will have a structure to hold all the strips, until - outputted. - */ - InitStripTable(); - /* Now we have the structure built to find the polygons according - to the number of adjacencies. Now use the SGI Method to find - strips according to the adjacencies - */ - Find_StripsEx(output,strip,&t,ties,triangulate,ON,&next_id); -} diff --git a/Tools/Stripe_w/local.h b/Tools/Stripe_w/local.h deleted file mode 100644 index df5256f6a..000000000 --- a/Tools/Stripe_w/local.h +++ /dev/null @@ -1,20 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE:local.h ------------------------------------------------------------------------*/ - -void Local_Polygon_Output(); -void Local_Output_Tri(); -int Different(); -void Local_Non_Blind_Triangulate(); -void Local_Blind_Triangulate(); -void Local_Triangulate_Polygon(); -void SGI_Strip(int num_verts,int num_faces,FILE *output, - int ties,int triangulate); diff --git a/Tools/Stripe_w/newpolve.c b/Tools/Stripe_w/newpolve.c deleted file mode 100644 index 6267bbc42..000000000 --- a/Tools/Stripe_w/newpolve.c +++ /dev/null @@ -1,1659 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: newpolve.c - This routine contains the bulk of the code that will find the - patches of quads in the data model -*/ -/*---------------------------------------------------------------------*/ - -#include -#include "polverts.h" -#include "extend.h" -#include "output.h" -#include "triangulate.h" -#include "common.h" -#include "util.h" -#include "global.h" -#include "init.h" -#include "add.h" - -ListHead **PolVerts; -ListHead **PolFaces; -ListHead **PolEdges; -int length; -BOOL resetting = FALSE; -int ids[STRIP_MAX]; -int added_quad = 0; -BOOL reversed = FALSE; -int patch = 0; -extern int *vn; -extern int *vt; - -int Calculate_Walks(int lastvert,int y, PF_FACES temp2) -{ - /* Find the length of the walk */ - - int previous_edge1, previous_edge2; - register int nextvert,numverts,counter,walk=0; - BOOL flag; - F_EDGES *node; - ListHead *pListHead; - static int seen = 0; - - /* Find the edge that we are currently on */ - if (y != 3) - { - previous_edge1 = *(temp2->pPolygon +y); - previous_edge2 = *(temp2->pPolygon + y + 1); - } - else - { - previous_edge1 = *(temp2->pPolygon +y); - previous_edge2 = *(temp2->pPolygon); - } - - temp2->seen = seen; - counter = y; - - /*Find the adjacent face to this edge */ - node = *(temp2->VertandId+y); - if (node->edge[2] != lastvert) - nextvert = node->edge[2]; - else - nextvert = node->edge[1]; - - /* Keep walking in this direction until we cannot do so */ - while ((nextvert != lastvert) && (nextvert != -1)) - { - walk++; - pListHead = PolFaces[nextvert]; - temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0); - numverts = temp2->nPolSize; - if ((numverts != 4) || (temp2->seen == seen)) - { - walk--; - nextvert = -1; - } - else - { - temp2->seen = seen; - /* Find edge that is not adjacent to the previous one */ - counter = 0; - flag = TRUE; - while ((counter < 3) && (flag)) - { - if ( ((*(temp2->pPolygon+counter) == previous_edge1) || - (*(temp2->pPolygon+counter+1) == previous_edge2)) || - ((*(temp2->pPolygon+counter) == previous_edge2) || - (*(temp2->pPolygon+counter+1) == previous_edge1)) ) - counter++; - else - flag = FALSE; - } - /* Get the IDs of the next edge */ - if (counter < 3) - { - previous_edge1 = *(temp2->pPolygon + counter); - previous_edge2 = *(temp2->pPolygon + counter + 1); - } - else - { - previous_edge1 = *(temp2->pPolygon + counter); - previous_edge2 = *(temp2->pPolygon); - } - - node = *(temp2->VertandId + counter); - if (node->edge[1] == nextvert) - nextvert = node->edge[2]; - else - nextvert = node->edge[1]; - } - } - seen++; - return walk; -} - - -BOOL Check_Right(int last_seen,PF_FACES temp2,int y,int face_id) -{ - /* Check when we last saw the face to the right of the current - one. We want to have seen it just before we started this strip - */ - - F_EDGES *node; - ListHead *pListHead; - register int nextvert,oldy; - PF_FACES t; - - oldy = y; - if (y != 3) - y = y+1; - else - y = 0; - node = *(temp2->VertandId + y); - if (face_id == node->edge[1]) - nextvert = node->edge[2]; - else - nextvert = node->edge[1]; - - if (nextvert == -1) - return FALSE; - - pListHead = PolFaces[nextvert]; - t = (PF_FACES) PeekList(pListHead,LISTHEAD,0); - if (t->seen != (last_seen - 1)) - { - /* maybe because of the numbering, we are not - on the right orientation, so we have to check the - opposite one to be sure - */ - if (oldy != 0) - y = oldy-1; - else - y = 3; - node = *(temp2->VertandId + y); - if (face_id == node->edge[1]) - nextvert = node->edge[2]; - else - nextvert = node->edge[1]; - if (nextvert == -1) - return FALSE; - pListHead = PolFaces[nextvert]; - t = (PF_FACES) PeekList(pListHead,LISTHEAD,0); - if (t->seen != (last_seen - 1)) - return FALSE; - } - return TRUE; -} - - -int Update_and_Test(PF_FACES temp2,int y,BOOL first,int distance,int lastvert, int val) -{ - - static int last_seen = 17; - int previous_edge1, previous_edge2; - register int original_distance,nextvert,numverts,counter; - BOOL flag; - F_EDGES *node; - ListHead *pListHead; - - original_distance = distance; - /* Find the edge that we are currently on */ - if (y != 3) - { - previous_edge1 = *(temp2->pPolygon +y); - previous_edge2 = *(temp2->pPolygon + y + 1); - } - else - { - previous_edge1 = *(temp2->pPolygon +y); - previous_edge2 = *(temp2->pPolygon); - } - - temp2->seen = val; - temp2->seen2 = val; - - node = *(temp2->VertandId+y); - if (lastvert != node->edge[2]) - nextvert = node->edge[2]; - else - nextvert = node->edge[1]; - - /* Keep walking in this direction until we cannot do so or - we go to distance */ - while ((distance > 0) && (nextvert != lastvert) && (nextvert != -1)) - { - distance--; - - pListHead = PolFaces[nextvert]; - temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0); - temp2->seen = val; - - if (temp2->seen2 == val) - { - last_seen++; - return (original_distance - distance); - } - - temp2->seen2 = val; - - numverts = temp2->nPolSize; - - if (numverts != 4) - nextvert = -1; - - else if ((!first) && (!(Check_Right(last_seen,temp2,y,nextvert)))) - { - last_seen++; - return (original_distance - distance); - } - else - { - /* Find edge that is not adjacent to the previous one */ - counter = 0; - flag = TRUE; - while ((counter < 3) && (flag)) - { - if ( ((*(temp2->pPolygon+counter) == previous_edge1) || - (*(temp2->pPolygon+counter+1) == previous_edge2)) || - ((*(temp2->pPolygon+counter) == previous_edge2) || - (*(temp2->pPolygon+counter+1) == previous_edge1)) ) - counter++; - else - flag = FALSE; - } - /* Get the IDs of the next edge */ - if (counter < 3) - { - previous_edge1 = *(temp2->pPolygon + counter); - previous_edge2 = *(temp2->pPolygon + counter + 1); - } - else - { - previous_edge1 = *(temp2->pPolygon + counter); - previous_edge2 = *(temp2->pPolygon); - } - if ( ((*(temp2->walked+counter) == -1) && - (*(temp2->walked+counter+2) == -1))) - { - printf("There is an error in the walks!\n"); - printf("1Code %d %d \n",*(temp2->walked+counter),*(temp2->walked+counter+2)); - exit(0); - } - else - { - if ((*(temp2->walked+counter) == -1) && - (*(temp2->walked+counter-2) == -1)) - { - printf("There is an error in the walks!\n"); - printf("2Code %d %d \n",*(temp2->walked+counter),*(temp2->walked+counter-2)); - exit(0); - } - } - node = *(temp2->VertandId + counter); - y = counter; - if (node->edge[1] == nextvert) - nextvert = node->edge[2]; - else - nextvert = node->edge[1]; - } - } - - last_seen++; - - if (distance != 0) - { - if (((nextvert == -1) || (nextvert == lastvert)) && (distance != 1)) - return (original_distance - distance); - } - return original_distance; -} - - -int Test_Adj(PF_FACES temp2,int x,int north,int distance,int lastvert, int value) -{ - /* if first time, then just update the last seen field */ - if (x==1) - return(Update_and_Test(temp2,north,TRUE,distance,lastvert,value)); - /* else we have to check if we are adjacent to the last strip */ - else - return(Update_and_Test(temp2,north,FALSE,distance,lastvert,value)); -} - -void Get_Band_Walk(PF_FACES temp2,int face_id,int *dir1,int *dir2, - int orientation,int cutoff_length) -{ - int previous_edge1, previous_edge2; - F_EDGES *node; - ListHead *pListHead; - register int walk = 0, nextvert,numverts,counter; - BOOL flag; - - /* Get the largest band that will include this face, starting - from orientation. Save the values of the largest band - (either north and south together, or east and west together) - in the direction variables. - */ - /* Find the edge that we are currently on */ - if (orientation != 3) - { - previous_edge1 = *(temp2->pPolygon + orientation); - previous_edge2 = *(temp2->pPolygon + orientation + 1); - } - else - { - previous_edge1 = *(temp2->pPolygon + orientation ); - previous_edge2 = *(temp2->pPolygon); - } - - if (orientation == 0) - { - if (*dir1 > *(temp2->walked + 1)) - *dir1 = *(temp2->walked + 1); - if (*dir2 > *(temp2->walked + 3)) - *dir2 = *(temp2->walked + 3); - } - else if (orientation == 3) - { - if (*dir1 > *(temp2->walked + orientation - 3)) - *dir1 = *(temp2->walked + orientation - 3) ; - if (*dir2 > *(temp2->walked + orientation -1 )) - *dir2 = *(temp2->walked + orientation - 1); - } - else - { - if (*dir1 > *(temp2->walked + orientation - 1)) - *dir1 = *(temp2->walked + orientation -1) ; - if (*dir2 > *(temp2->walked+ orientation + 1)) - *dir2 = *(temp2->walked + orientation + 1); - } - - /* if we know already that we can't extend the - band from this face, we do not need to do the walk - */ - if ((*dir1 != 0) && (*dir2 != 0)) - { - /* Find the adjacent face to this edge */ - node = *(temp2->VertandId+orientation); - if (face_id == node->edge[1]) - nextvert = node->edge[2]; - else - nextvert = node->edge[1]; - } - else - nextvert = -1; /* leave w/o walking */ - - /* Keep walking in this direction until we cannot do so */ - while ((nextvert != face_id) && (nextvert != -1)) - { - walk++; - pListHead = PolFaces[nextvert]; - temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0); - numverts = temp2->nPolSize; - if ((numverts != 4) || (walk > cutoff_length)) - nextvert = -1; - else - { - /* Find edge that is not adjacent to the previous one */ - counter = 0; - flag = TRUE; - while ((counter < 3) && (flag)) - { - if ( ((*(temp2->pPolygon+counter) == previous_edge1) || - (*(temp2->pPolygon+counter+1) == previous_edge2)) || - ((*(temp2->pPolygon+counter) == previous_edge2) || - (*(temp2->pPolygon+counter+1) == previous_edge1)) ) - counter++; - else - flag = FALSE; - } - /* Get the IDs of the next edge */ - if (counter < 3) - { - previous_edge1 = *(temp2->pPolygon + counter); - previous_edge2 = *(temp2->pPolygon + counter + 1); - } - else - { - previous_edge1 = *(temp2->pPolygon + counter); - previous_edge2 = *(temp2->pPolygon); - } - - /* find out how far we can extend in the 2 directions - along this new face in the walk - */ - if (counter == 0) - { - if (*dir1 > *(temp2->walked + 1)) - *dir1 = *(temp2->walked + 1); - if (*dir2 > *(temp2->walked + 3)) - *dir2 = *(temp2->walked + 3); - } - else if (counter == 3) - { - if (*dir1 > *(temp2->walked + counter - 3)) - *dir1 = *(temp2->walked + counter - 3) ; - if (*dir2 > *(temp2->walked + counter -1 )) - *dir2 = *(temp2->walked + counter -1); - } - else - { - if (*dir1 > *(temp2->walked + counter - 1)) - *dir1 = *(temp2->walked + counter -1) ; - if (*dir2 > *(temp2->walked + counter + 1)) - *dir2 = *(temp2->walked + counter + 1); - } - - /* if we know already that we can't extend the - band from this face, we do not need to do the walk - */ - if ((*dir1 == 0) || (*dir2 == 0)) - nextvert = -1; - if (nextvert != -1) - { - node = *(temp2->VertandId + counter); - if (node->edge[1] == nextvert) - nextvert = node->edge[2]; - else - nextvert = node->edge[1]; - } - - } - } -} - - - - -int Find_Max(PF_FACES temp2,int lastvert,int north,int left, - int *lastminup,int *lastminleft) -{ - int temp,walk,counter,minup,x,band_value; - int previous_edge1, previous_edge2; - F_EDGES *node; - ListHead *pListHead; - BOOL flag; - static int last_seen = 0; - register int smallest_so_far,nextvert,max=-1; - - *lastminup = MAX_BAND; - *lastminleft = 1; - - if (left == 3) - { - previous_edge1 = *(temp2->pPolygon + left); - previous_edge2 = *(temp2->pPolygon); - } - - else - { - previous_edge1 = *(temp2->pPolygon + left + 1); - previous_edge2 = *(temp2->pPolygon + left); - } - - temp2->seen = last_seen; - walk = *(temp2->walked + left); - - for (x=1;x<=(walk+1); x++) - { - /* test to see if we have a true band - that is, are they adjacent to each other - */ - - minup = *(temp2->walked + north) + 1; - - /* if we are at the very first face, then we do not - have to check the adjacent faces going up - and our north distance is the distance of this face's - north direction. - */ - if (x == 1) - { - *lastminup = minup; - minup = Test_Adj(temp2,x,north,*lastminup,lastvert,last_seen); - *lastminup = minup; - smallest_so_far = minup; - } - - - /* find the largest band that we can have */ - if (minup < (*lastminup)) - { - /* see if we really can go up all the way - temp should by less than our equal to minup - if it is less, then one of the faces was not - adjacent to those next to it and the band height - will be smaller - */ - temp = Test_Adj(temp2,x,north,minup,lastvert,last_seen); - if (temp > minup) - { - printf("There is an error in the test adj\n"); - exit(0); - } - minup = temp; - band_value = x * minup; - if (minup < smallest_so_far) - { - if (band_value > max) - { - smallest_so_far = minup; - *lastminup = minup; - *lastminleft = x; - max = band_value; - } - else - smallest_so_far = minup; - } - else - { - band_value = x * smallest_so_far; - if (band_value > max) - { - *lastminup = smallest_so_far; - *lastminleft = x; - max = band_value; - } - } - } - else - { - if (x != 1) - { - temp = Test_Adj(temp2,x,north,smallest_so_far,lastvert,last_seen); - if (temp > smallest_so_far) - { - printf("There is an error in the test adj\n"); - exit(0); - } - smallest_so_far = temp; - } - band_value = x * smallest_so_far; - if (band_value > max) - { - *lastminup = smallest_so_far; - *lastminleft = x; - max = band_value; - } - } - if ( x != (walk + 1)) - { - node = *(temp2->VertandId+left); - if (lastvert == node->edge[1]) - nextvert = node->edge[2]; - else - nextvert = node->edge[1]; - - lastvert = nextvert; - - if (nextvert == -1) - return max; - - pListHead = PolFaces[nextvert]; - temp2 = (PF_FACES) PeekList(pListHead, LISTHEAD, 0); - - /* if we have visited this face before, then there is an error */ - if (((*(temp2->walked) == -1) && (*(temp2->walked+1) == -1) && - (*(temp2->walked+2) == -1) && (*(temp2->walked+3) == -1)) - || (temp2->nPolSize !=4) || (temp2->seen == last_seen)) - { - - if (lastvert == node->edge[1]) - nextvert = node->edge[2]; - else - nextvert = node->edge[1]; - if (nextvert == -1) - return max; - lastvert = nextvert; - /* Last attempt to get the face ... */ - pListHead = PolFaces[nextvert]; - temp2 = (PF_FACES) PeekList(pListHead, LISTHEAD, 0); - if (((*(temp2->walked) == -1) && (*(temp2->walked+1) == -1) && - (*(temp2->walked+2) == -1) && (*(temp2->walked+3) == -1)) - || (temp2->nPolSize !=4) || (temp2->seen == last_seen)) - return max; /* The polygon was not saved with the edge, not - enough room. We will get the walk when we come - to that polygon later. - */ - } - /*else - {*/ - counter = 0; - flag = TRUE; - temp2->seen = last_seen; - - while ((counter < 3) && (flag)) - { - - if ( ((*(temp2->pPolygon+counter) == previous_edge1) || - (*(temp2->pPolygon+counter+1) == previous_edge2)) || - ((*(temp2->pPolygon+counter) == previous_edge2) || - (*(temp2->pPolygon+counter+1) == previous_edge1)) ) - counter++; - else - flag = FALSE; - } - /*}*/ - - /* Get the IDs of the next edge */ - left = counter; - north = left+1; - if (left ==3) - north = 0; - if (counter < 3) - { - previous_edge1 = *(temp2->pPolygon + counter + 1); - previous_edge2 = *(temp2->pPolygon + counter); - } - else - { - previous_edge1 = *(temp2->pPolygon + counter); - previous_edge2 = *(temp2->pPolygon); - } - - } - -} -last_seen++; -return max; -} - -void Mark_Face(PF_FACES temp2, int color1, int color2, - int color3, FILE *output_file, BOOL end, int *edge1, int *edge2, - int *face_id, int norms, int texture) -{ - static int last_quad[4]; - int x,y,z=0; - int saved[2]; - static int output1, output2,last_id; - BOOL cptexture = FALSE; - - /* Are we done with the patch? If so return the last edge that - we will come out on, and that will be the edge that we will - start to extend upon. - */ - - if (end) - { - *edge1 = output1; - *edge2 = output2; - *face_id = last_id; - return; - } - - cptexture = texture; - last_id = *face_id; - *(temp2->walked) = -1; - *(temp2->walked+1) = -1; - *(temp2->walked+2) = -1; - *(temp2->walked+3) = -1; - added_quad++; - temp2->nPolSize = 1; - - if (patch == 0) - { - /* At the first quad in the strip -- save it */ - last_quad[0] = *(temp2->pPolygon); - last_quad[1] = *(temp2->pPolygon+1); - last_quad[2] = *(temp2->pPolygon+2); - last_quad[3] = *(temp2->pPolygon+3); - patch++; - } - else - { - /* Now we have a triangle to output, find the edge in common */ - for (x=0; x < 4 ;x++) - { - for (y=0; y< 4; y++) - { - if (last_quad[x] == *(temp2->pPolygon+y)) - { - saved[z++] = last_quad[x]; - if (z > 2) - { - /* This means that there was a non convex or - an overlapping polygon - */ - z--; - break; - } - } - } - } - - if (z != 2) - { - printf("Z is not 2 %d \n",patch); - printf("4 %d %d %d %d %d %d %d\n",*(temp2->pPolygon), - *(temp2->pPolygon+1),*(temp2->pPolygon+2),*(temp2->pPolygon+3), - color1,color2,color3); - printf("%d %d %d %d\n",last_quad[0],last_quad[1],last_quad[2],last_quad[3]); - exit(1); - } - - if (patch == 1) - { - /* First one to output, there was no output edge */ - patch++; - x = Adjacent(saved[0],saved[1],last_quad,4); - y = Adjacent(saved[1],saved[0],last_quad,4); - - /* Data might be mixed and we do not have textures for some of the vertices */ - if ((texture) && ( ((vt[x]) == 0) || ((vt[y])==0) || ((vt[saved[1]])==0))) - cptexture = FALSE; - - if ((!norms) && (!cptexture)) - { - fprintf(output_file,"\nt %d %d %d ",x+1,y+1,saved[1]+1); - fprintf(output_file,"%d ",saved[0]+1); - } - else if ((norms) && (!cptexture)) - { - fprintf(output_file,"\nt %d//%d %d//%d %d//%d ",x+1,vn[x] +1, - y+1,vn[y] +1, - saved[1]+1,vn[saved[1]]+1); - fprintf(output_file,"%d//%d ",saved[0]+1,vn[saved[0]]+1); - } - else if ((cptexture) && (!norms)) - { - fprintf(output_file,"\nt %d/%d %d/%d %d/%d ",x+1,vt[x] +1, - y+1,vt[y] +1, - saved[1]+1,vt[saved[1]]+1); - fprintf(output_file,"%d//%d ",saved[0]+1,vt[saved[0]]+1); - } - else - { - fprintf(output_file,"\nt %d/%d/%d %d/%d/%d %d/%d/%d ",x+1,vt[x]+1,vn[x] +1, - y+1,vt[y]+1,vn[y] +1, - saved[1]+1,vt[saved[1]]+1,vn[saved[1]]+1); - fprintf(output_file,"%d/%d/%d ",saved[0]+1,vt[saved[0]]+1,vn[saved[0]]+1); - } - - x = Adjacent(saved[0],saved[1],temp2->pPolygon,4); - y = Adjacent(saved[1],saved[0],temp2->pPolygon,4); - - /* Data might be mixed and we do not have textures for some of the vertices */ - if ((texture) && ( (vt[x] == 0) || (vt[y]==0))) - { - if (cptexture) - fprintf(output_file,"\nq "); - cptexture = FALSE; - } - if ((!norms) && (!cptexture)) - { - fprintf(output_file,"%d ",x+1); - fprintf(output_file,"%d ",y+1); - } - else if ((norms) && (!cptexture)) - { - fprintf(output_file,"%d//%d ",x+1,vn[x]+1); - fprintf(output_file,"%d//%d ",y+1,vn[y]+1); - } - else if ((cptexture) && (!norms)) - { - fprintf(output_file,"%d/%d ",x+1,vt[x]+1); - fprintf(output_file,"%d/%d ",y+1,vt[y]+1); - } - else - { - fprintf(output_file,"%d/%d/%d ",x+1,vt[x]+1,vn[x]+1); - fprintf(output_file,"%d/%d/%d ",y+1,vt[y]+1,vn[y]+1); - } - - output1 = x; - output2 = y; - } - - else - { - x = Adjacent(output2,output1,temp2->pPolygon,4); - y = Adjacent(output1,output2,temp2->pPolygon,4); - /* Data might be mixed and we do not have textures for some of the vertices */ - if ((texture) && ( ((vt[x]) == 0) || ((vt[y])==0) )) - texture = FALSE; - - if ((!norms) && (!texture)) - { - fprintf(output_file,"\nq %d ",x+1); - fprintf(output_file,"%d ",y+1); - } - else if ((norms) && (!texture)) - { - fprintf(output_file,"\nq %d//%d ",x+1,vn[x]+1); - fprintf(output_file,"%d//%d ",y+1,vn[y]+1); - } - else if ((texture) && (!norms)) - { - fprintf(output_file,"\nq %d/%d ",x+1,vt[x]+1); - fprintf(output_file,"%d/%d ",y+1,vt[y]+1); - } - else - { - fprintf(output_file,"\nq %d/%d/%d ",x+1,vt[x]+1,vn[x]+1); - fprintf(output_file,"%d/%d/%d ",y+1,vt[y]+1,vn[y]+1); - } - - output1 = x; - output2 = y; - } - - last_quad[0] = *(temp2->pPolygon); - last_quad[1] = *(temp2->pPolygon+1); - last_quad[2] = *(temp2->pPolygon+2); - last_quad[3] = *(temp2->pPolygon+3); - } -} - -void Fast_Reset(int x) -{ - register int y,numverts; - register int front_walk, back_walk; - ListHead *pListHead; - PF_FACES temp = NULL; - - pListHead = PolFaces[x]; - temp = (PF_FACES) PeekList(pListHead,LISTHEAD,0); - numverts = temp->nPolSize; - - front_walk = 0; - back_walk = 0; - resetting = TRUE; - - /* we are doing this only for quads */ - if (numverts == 4) - { - /* for each face not seen yet, do North and South together - and East and West together - */ - for (y=0;y<2;y++) - { - /* Check if the opposite sides were seen already */ - /* Find walk for the first edge */ - front_walk = Calculate_Walks(x,y,temp); - /* Find walk in the opposite direction */ - back_walk = Calculate_Walks(x,y+2,temp); - /* Now put into the data structure the numbers that - we have found - */ - Assign_Walk(x,temp,front_walk,y,back_walk); - Assign_Walk(x,temp,back_walk,y+2,front_walk); - } - } - resetting = FALSE; -} - - -void Reset_Max(PF_FACES temp2,int face_id,int north,int last_north, int orientation, - int last_left,FILE *output_file,int color1,int color2,int color3, - BOOL start) -{ - int previous_edge1,previous_edge2; - F_EDGES *node; - ListHead *pListHead; - int f,t,nextvert,counter; - BOOL flag; - - - /* Reset walks on faces, since we just found a patch */ - if (orientation !=3) - { - previous_edge1 = *(temp2->pPolygon + orientation+1); - previous_edge2 = *(temp2->pPolygon + orientation ); - } - else - { - previous_edge1 = *(temp2->pPolygon + orientation ); - previous_edge2 = *(temp2->pPolygon); - } - - /* only if we are going left, otherwise there will be -1 there */ - /*Find the adjacent face to this edge */ - - for (t = 0; t <=3 ; t++) - { - node = *(temp2->VertandId+t); - - if (face_id == node->edge[1]) - f = node->edge[2]; - else - f = node->edge[1]; - - if (f != -1) - Fast_Reset(f); - } - - node = *(temp2->VertandId+orientation); - if (face_id == node->edge[1]) - nextvert = node->edge[2]; - else - nextvert = node->edge[1]; - - while ((last_left--) > 1) - { - - if (start) - Reset_Max(temp2,face_id,orientation,last_left,north,last_north,output_file,color1,color2,color3,FALSE); - - face_id = nextvert; - pListHead = PolFaces[nextvert]; - temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0); - if ((temp2->nPolSize != 4) && (temp2->nPolSize != 1)) - { - /* There is more than 2 polygons on the edge, and we could have - gotten the wrong one - */ - if (nextvert != node->edge[1]) - nextvert = node->edge[1]; - else - nextvert = node->edge[2]; - pListHead = PolFaces[nextvert]; - temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0); - node = *(temp2->VertandId+orientation); - } - - - if (!start) - { - for (t = 0; t <=3 ; t++) - { - node = *(temp2->VertandId+t); - - if (face_id == node->edge[1]) - f = node->edge[2]; - else - f = node->edge[1]; - - if (f != -1) - Fast_Reset(f); - } - } - - - counter = 0; - flag = TRUE; - while ((counter < 3) && (flag)) - { - if ( ((*(temp2->pPolygon+counter) == previous_edge1) || - (*(temp2->pPolygon+counter+1) == previous_edge2)) || - ((*(temp2->pPolygon+counter) == previous_edge2) || - (*(temp2->pPolygon+counter+1) == previous_edge1)) ) - counter++; - else - flag = FALSE; - } - - /* Get the IDs of the next edge */ - if (counter < 3) - { - previous_edge1 = *(temp2->pPolygon + counter+1); - previous_edge2 = *(temp2->pPolygon + counter); - } - else - { - previous_edge1 = *(temp2->pPolygon + counter); - previous_edge2 = *(temp2->pPolygon); - } - orientation = counter; - - node = *(temp2->VertandId + counter); - if (node->edge[1] == nextvert) - nextvert = node->edge[2]; - else - nextvert = node->edge[1]; - - if (!reversed) - { - if (counter != 3) - north = counter +1; - else - north = 0; - } - else - { - if (counter != 0) - north = counter -1; - else - north = 3; - - } - } -if (start) - Reset_Max(temp2,face_id,orientation,last_left,north,last_north,output_file,color1,color2,color3,FALSE); -else if (nextvert != -1) - Fast_Reset(nextvert); - -} - - -int Peel_Max(PF_FACES temp2,int face_id,int north,int last_north, int orientation, - int last_left,FILE *output_file,int color1,int color2,int color3, - BOOL start, int *swaps_added, int norms, int texture) -{ - int end1,end2,last_id,s=0,walk = 0; - int previous_edge1,previous_edge2; - static int last_seen = 1000; - F_EDGES *node; - ListHead *pListHead; - int nextvert,numverts,counter,dummy,tris=0; - BOOL flag; - - /* Peel the patch from the model. - We will try and extend off the end of each strip in the patch. We will return the - number of triangles completed by this extension only, and the number of swaps - in the extension only. - */ - patch = 0; - - if (orientation !=3) - { - previous_edge1 = *(temp2->pPolygon + orientation+1); - previous_edge2 = *(temp2->pPolygon + orientation ); - } - else - { - previous_edge1 = *(temp2->pPolygon + orientation ); - previous_edge2 = *(temp2->pPolygon); - } - - - walk = *(temp2->walked + orientation); - - /* only if we are going left, otherwise there will be -1 there */ - if ((start) && ((walk+1) < last_left)) - { - printf("There is an error in the left %d %d\n",walk,last_left); - exit(0); - } - - /* Find the adjacent face to this edge */ - node = *(temp2->VertandId+orientation); - if (face_id == node->edge[1]) - nextvert = node->edge[2]; - else - nextvert = node->edge[1]; - temp2->seen = last_seen; - - - while ((last_left--) > 1) - { - if (start) - tris += Peel_Max(temp2,face_id,orientation,last_left,north,last_north,output_file, - color1,color2,color3,FALSE,swaps_added,norms,texture); - else - Mark_Face(temp2,color1,color2,color3,output_file,FALSE,&dummy,&dummy,&face_id,norms,texture); - - - pListHead = PolFaces[nextvert]; - temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0); - numverts = temp2->nPolSize; - - if ((numverts != 4) || (temp2->seen == last_seen) - || (nextvert == -1)) - { - - /* There is more than 2 polygons on the edge, and we could have - gotten the wrong one - */ - if (nextvert != node->edge[1]) - nextvert = node->edge[1]; - else - nextvert = node->edge[2]; - pListHead = PolFaces[nextvert]; - temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0); - numverts = temp2->nPolSize; - if ((numverts != 4) || (temp2->seen == last_seen) ) - { - printf("Peel 2 %d\n",numverts); - exit(1); - } - } - - face_id = nextvert; - temp2->seen = last_seen; - - counter = 0; - flag = TRUE; - while ((counter < 3) && (flag)) - { - if ( ((*(temp2->pPolygon+counter) == previous_edge1) || - (*(temp2->pPolygon+counter+1) == previous_edge2)) || - ((*(temp2->pPolygon+counter) == previous_edge2) || - (*(temp2->pPolygon+counter+1) == previous_edge1)) ) - counter++; - else - flag = FALSE; - } - /* Get the IDs of the next edge */ - if (counter < 3) - { - previous_edge1 = *(temp2->pPolygon + counter+1); - previous_edge2 = *(temp2->pPolygon + counter); - } - else - { - previous_edge1 = *(temp2->pPolygon + counter); - previous_edge2 = *(temp2->pPolygon); - } - orientation = counter; - - node = *(temp2->VertandId + counter); - if (node->edge[1] == nextvert) - nextvert = node->edge[2]; - else - nextvert = node->edge[1]; - - if (!reversed) - { - if (counter != 3) - north = counter +1; - else - north = 0; - } - else - { - if (counter != 0) - north = counter -1; - else - north = 3; - } -} - -if (start) - tris += Peel_Max(temp2,face_id,orientation,last_left,north,last_north,output_file, - color1,color2,color3,FALSE,swaps_added,norms,texture); -else - Mark_Face(temp2,color1,color2,color3,output_file,FALSE,&dummy,&dummy,&face_id,norms,texture);/* do the last face */ - -last_seen++; - -/* Get the edge that we came out on the last strip of the patch */ -Mark_Face(NULL,0,0,0,output_file,TRUE,&end1,&end2,&last_id,norms,texture); -tris += Extend_Face(last_id,end1,end2,&s,output_file,color1,color2,color3,vn,norms,vt,texture); -*swaps_added = *swaps_added + s; -return tris; -} - - - -void Find_Bands(int numfaces, FILE *output_file, int *swaps, int *bands, - int *cost, int *tri, int norms, int *vert_norms, int texture, int *vert_texture) -{ - - register int x,y,max1,max2,numverts,face_id,flag,maximum = 25; - ListHead *pListHead; - PF_FACES temp = NULL; - int color1 = 0, color2 = 100, color3 = 255; - int larger,smaller; - int north_length1,last_north,left_length1,last_left,north_length2,left_length2; - int total_tri = 0, total_swaps = 0,last_id; - int end1, end2,s=0; - register int cutoff = 20; - - /* Code that will find the patches. "Cutoff" will be - the cutoff of the area of the patches that we will be allowing. After - we reach this cutoff length, then we will run the local algorithm on the - remaining faces. - */ - - /* For each faces that is left find the largest possible band that we can - have with the remaining faces. Note that we will only be finding patches - consisting of quads. - */ - - vn = vert_norms; - vt = vert_texture; - y=1; - *bands = 0; - - while ((maximum >= cutoff)) - { - y++; - maximum = -1; - for (x=0; xnPolSize; - - /* we are doing this only for quads */ - if (numverts == 4) - { - /* We want a face that is has not been used yet, - since we know that that face must be part of - a band. Then we will find the largest band that - the face may be contained in - */ - - /* Doing the north and the left */ - if ((*(temp->walked) != -1) && (*(temp->walked+3) != -1)) - max1 = Find_Max(temp,x,0,3,&north_length1,&left_length1); - if ((*(temp->walked+1) != -1) && (*(temp->walked+2) != -1)) - max2 = Find_Max(temp,x,2,1,&north_length2,&left_length2); - if ((max1 != (north_length1 * left_length1)) || - (max2 != (north_length2 * left_length2))) - { - printf("Max1 %d, %d %d Max2 %d, %d %d\n",max1,north_length1,left_length1,max2,north_length2,left_length2); - exit(0); - } - - - if ((max1 > max2) && (max1 > maximum)) - { - maximum = max1; - face_id = x; - flag = 1; - last_north = north_length1; - last_left = left_length1; - /* so we know we saved max1 */ - } - else if ((max2 > maximum) ) - { - maximum = max2; - face_id = x; - flag = 2; - last_north = north_length2; - last_left = left_length2; - /* so we know we saved max2 */ - } - } - } - if ((maximum < cutoff) && (*bands == 0)) - return; - pListHead = PolFaces[face_id]; - temp = (PF_FACES) PeekList(pListHead,LISTHEAD,0); - /* There are no patches that we found in this pass */ - if (maximum == -1) - break; - printf("The maximum is face %d area %d: lengths %d %d\n",face_id,maximum,last_north,last_left); - if (maximum == 16) - printf("Fran"); - - if (last_north > last_left) - { - larger = last_north; - smaller = last_left; - } - else - { - larger = last_left; - smaller = last_north; - } - - length = larger; - - if (flag == 1) - { - if (last_north > last_left) /* go north sequentially */ - { - total_tri += Peel_Max(temp,face_id,0,last_north,3,last_left,output_file,color1,color2,color3,TRUE,&s,norms,texture); - Reset_Max(temp,face_id,0,last_north,3,last_left,output_file,color1,color2,color3,TRUE); - total_swaps += s; - } - else - { - reversed = TRUE; - total_tri += Peel_Max(temp,face_id,3,last_left,0,last_north,output_file,color1,color2,color3,TRUE,&s,norms,texture); - Reset_Max(temp,face_id,3,last_left,0,last_north,output_file,color1,color2,color3,TRUE); - reversed = FALSE; - total_swaps += s; - } - - - /* Get the edge that we came out on the last strip of the patch */ - Mark_Face(NULL,0,0,0,NULL,TRUE,&end1,&end2,&last_id,norms,texture); - total_tri += Extend_Face(last_id,end1,end2,&s,output_file,color1,color2,color3,vn,norms,vt,texture); - total_swaps += s; - - } - else - { - if (last_north > last_left) - { - total_tri += Peel_Max(temp,face_id,2,last_north,1,last_left,output_file,color1,color2,color3,TRUE,&s,norms,texture); - Reset_Max(temp,face_id,2,last_north,1,last_left,output_file,color1,color2,color3,TRUE); - total_swaps += s; - } - else - { - reversed = TRUE; - total_tri += Peel_Max(temp,face_id,1,last_left,2,last_north,output_file,color1,color2,color3,TRUE,&s,norms,texture); - Reset_Max(temp,face_id,1,last_left,2,last_north,output_file,color1,color2,color3,TRUE); - reversed = FALSE; - total_swaps += s; - } - - /* Get the edge that we came out on on the patch */ - Mark_Face(NULL,0,0,0,NULL,TRUE,&end1,&end2,&last_id,norms,texture); - total_tri += Extend_Face(last_id,end1,end2,&s,output_file,color1,color2,color3,vn,norms,vt,texture); - total_swaps += s; - } - - /* Now compute the cost of transmitting this band, is equal to - going across the larger portion sequentially, - and swapping 3 times per other dimension - */ - - total_tri += (maximum * 2); - *bands = *bands + smaller; - } - - printf("We transmitted %d triangles,using %d swaps and %d strips\n",total_tri,total_swaps, *bands); - printf("COST %d\n",total_tri + total_swaps + *bands + *bands); - - *cost = total_tri + total_swaps + *bands + *bands; - *tri = total_tri; - added_quad = added_quad * 4; - *swaps = total_swaps; -} - - -void Save_Rest(int *numfaces) -{ - /* Put the polygons that are left into a data structure so that we can run the - stripping code on it. - */ - register int x,y=0,numverts; - ListHead *pListHead; - PF_FACES temp=NULL; - - for (x=0; x<*numfaces; x++) - { - /* for each face, get the face */ - pListHead = PolFaces[x]; - temp = (PF_FACES) PeekList(pListHead,LISTHEAD,0); - numverts = temp->nPolSize; - /* If we did not do the face before add it to data structure with new - face id number - */ - if (numverts != 1) - { - CopyFace(temp->pPolygon,numverts,y+1,temp->pNorms); - y++; - } - /* Used it, so remove it */ - else - RemoveList(pListHead,(PLISTINFO) temp); - - } - *numfaces = y; -} - -void Assign_Walk(int lastvert,PF_FACES temp2, int front_walk,int y, - int back_walk) -{ -/* Go back and do the walk again, but this time save the lengths inside - the data structure. - y was the starting edge number for the front_walk length - back_walk is the length of the walk along the opposite edge - */ - int previous_edge1, previous_edge2; - register int walk = 0,nextvert,numverts,counter; - BOOL flag; - F_EDGES *node; - ListHead *pListHead; - static int seen = 0; - static BOOL first = TRUE; - BOOL wrap = FALSE, set = FALSE; - - /* In the "Fast_Reset" resetting will be true */ - if ((resetting) && (first)) - { - seen = 0; - first = FALSE; - } - - seen++; - /* Had a band who could be a cycle */ - if (front_walk == back_walk) - wrap = TRUE; - - /* Find the edge that we are currently on */ - if (y != 3) - { - previous_edge1 = *(temp2->pPolygon +y); - previous_edge2 = *(temp2->pPolygon + y + 1); - } - else - { - previous_edge1 = *(temp2->pPolygon +y); - previous_edge2 = *(temp2->pPolygon); - } - - /* Assign the lengths */ - if (y < 2) - { - *(temp2->walked+y) = front_walk--; - *(temp2->walked+y+2) = back_walk++; - } - else - { - *(temp2->walked+y) = front_walk--; - *(temp2->walked+y-2) = back_walk++; - } - - /*Find the adjacent face to this edge */ - node = *(temp2->VertandId+y); - - if (node->edge[2] != lastvert) - nextvert = node->edge[2]; - else - nextvert = node->edge[1]; - - temp2->seen3 = seen; - - /* Keep walking in this direction until we cannot do so */ - while ((nextvert != lastvert) && (nextvert != -1) && (front_walk >= 0)) - { - walk++; - pListHead = PolFaces[nextvert]; - - temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0); - numverts = temp2->nPolSize; - if ((numverts != 4)) - { - nextvert = -1; - /* Don't include this face in the walk */ - walk--; - } - else - { - /* Find edge that is not adjacent to the previous one */ - counter = 0; - flag = TRUE; - while ((counter < 3) && (flag)) - { - if ( ((*(temp2->pPolygon+counter) == previous_edge1) || - (*(temp2->pPolygon+counter+1) == previous_edge2)) || - ((*(temp2->pPolygon+counter) == previous_edge2) || - (*(temp2->pPolygon+counter+1) == previous_edge1)) ) - counter++; - else - flag = FALSE; - } - /* Get the IDs of the next edge */ - if (counter < 3) - { - previous_edge1 = *(temp2->pPolygon + counter); - previous_edge2 = *(temp2->pPolygon + counter + 1); - } - else - { - previous_edge1 = *(temp2->pPolygon + counter); - previous_edge2 = *(temp2->pPolygon); - } - - - /* Put in the walk lengths */ - if (counter < 2) - { - if (((*(temp2->walked + counter) >= 0) - || (*(temp2->walked +counter + 2) >= 0))) - { - if ((resetting == FALSE) && ((temp2->seen3) != (seen-1))) - { - /* If there are more than 2 polygons adjacent - to an edge then we can be trying to assign more than - once. We will save the smaller one - */ - temp2->seen3 = seen; - if ( (*(temp2->walked+counter) <= front_walk) && - (*(temp2->walked+counter+2) <= back_walk) ) - return; - if (*(temp2->walked+counter) > front_walk) - *(temp2->walked+counter) = front_walk--; - else - front_walk--; - if (*(temp2->walked+counter+2) > back_walk) - *(temp2->walked+counter+2) = back_walk++; - else - back_walk++; - } - else if (resetting == FALSE) - { - /* if there was a cycle then all lengths are the same */ - walk--; - back_walk--; - front_walk++; - temp2->seen3 = seen; - *(temp2->walked+counter) = front_walk--; - *(temp2->walked+counter+2) = back_walk++; - } - else if (((temp2->seen3 == (seen-1)) - && (wrap) && (walk == 1)) || (set)) - { - /* if there was a cycle then all lengths are the same */ - set = TRUE; - walk--; - back_walk--; - front_walk++; - temp2->seen3 = seen; - *(temp2->walked+counter) = front_walk--; - *(temp2->walked+counter+2) = back_walk++; - } - else - { - temp2->seen3 = seen; - *(temp2->walked+counter) = front_walk--; - *(temp2->walked+counter+2) = back_walk++; - } - } /* if was > 0 */ - else - { - temp2->seen3 = seen; - *(temp2->walked+counter) = front_walk--; - *(temp2->walked+counter+2) = back_walk++; - } - } - - else - { - if (((*(temp2->walked + counter) >= 0 ) - || (*(temp2->walked +counter - 2) >= 0)) ) - { - if ((temp2->seen3 != (seen-1)) && (resetting == FALSE)) - { - /* If there are more than 2 polygons adjacent - to an edge then we can be trying to assign more than - once. We will save the smaller one - */ - temp2->seen3 = seen; - if ( (*(temp2->walked+counter) <= front_walk) && - (*(temp2->walked+counter-2) <= back_walk) ) - return; - if (*(temp2->walked+counter) > front_walk) - *(temp2->walked+counter) = front_walk--; - else - front_walk--; - if (*(temp2->walked+counter-2) > back_walk) - *(temp2->walked+counter-2) = back_walk++; - else - back_walk++; - } - else if (resetting == FALSE) - { - walk--; - back_walk--; - front_walk++; - temp2->seen3 = seen; - *(temp2->walked+counter) = front_walk--; - *(temp2->walked+counter-2) = back_walk++; - } - else if (((temp2->seen3 == (seen-1)) && (walk == 1) && (wrap)) - || (set)) - { - /* if there was a cycle then all lengths are the same */ - set = TRUE; - walk--; - back_walk--; - front_walk++; - temp2->seen3 = seen; - *(temp2->walked+counter) = front_walk--; - *(temp2->walked+counter-2) = back_walk++; - } - else - { - temp2->seen3 = seen; - *(temp2->walked+counter) = front_walk--; - *(temp2->walked+counter-2) = back_walk++; - } - } - else - { - temp2->seen3 = seen; - *(temp2->walked+counter) = front_walk--; - *(temp2->walked+counter-2) = back_walk++; - } - - } - if (nextvert != -1) - { - node = *(temp2->VertandId + counter); - if (node->edge[1] == nextvert) - nextvert = node->edge[2]; - else - nextvert = node->edge[1]; - } - - } -} -if ((EVEN(seen)) ) - seen+=2; -} - -void Save_Walks(int numfaces) -{ - int x,y,numverts; - int front_walk, back_walk; - ListHead *pListHead; - PF_FACES temp = NULL; - - for (x=0; xnPolSize; - front_walk = 0; - back_walk = 0; - - /* we are finding patches only for quads */ - if (numverts == 4) - { - /* for each face not seen yet, do North and South together - and East and West together - */ - for (y=0;y<2;y++) - { - /* Check if the opposite sides were seen already from another - starting face, if they were then there is no need to do the walk again - */ - - if ( ((*(temp->walked+y) == -1) && - (*(temp->walked+y+2) == -1) )) - { - /* Find walk for the first edge */ - front_walk = Calculate_Walks(x,y,temp); - /* Find walk in the opposite direction */ - back_walk = Calculate_Walks(x,y+2,temp); - /* Now put into the data structure the numbers that - we have found - */ - Assign_Walk(x,temp,front_walk,y,back_walk); - Assign_Walk(x,temp,back_walk,y+2,front_walk); - } - } - } - } -} - - diff --git a/Tools/Stripe_w/options.c b/Tools/Stripe_w/options.c deleted file mode 100644 index 7e1243e24..000000000 --- a/Tools/Stripe_w/options.c +++ /dev/null @@ -1,181 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: options.c - This file contains routines that are used to determine the options - that were specified by the user -*/ -/*---------------------------------------------------------------------*/ - -#include -#include -#include "options.h" -#include "global.h" - -int power_10(int power) -{ - /* Raise 10 to the power */ - register int i,p; - - p = 1; - for (i = 1; i <= power; ++i) - p = p * 10; - return p; -} - -float power_negative(int power) -{ - /* Raise 10 to the negative power */ - - register int i; - float p; - - p = (float)1; - for (i = 1; i<=power; i++) - p = p * (float).1; - return p; -} - -float convert_array(int num[],int stack_size) -{ - /* Convert an array of characters to an integer */ - - register int counter,c; - float temp =(float)0.0; - - for (c=(stack_size-1), counter = 0; c>=0; c--, counter++) - { - if (num[c] == -1) - /* We are at the decimal point, convert to decimal - less than 1 - */ - { - counter = -1; - temp = power_negative(stack_size - c - 1) * temp; - } - else - temp += power_10(counter) * num[c]; - } - - return(temp); -} - -double get_options(int argc, char **argv, int *f, int *t, int *tr, int *group) -{ - char c; - int count = 0; - int buffer[STRIP_MAX]; - int next = 0; - /* tie variable */ - enum tie_options tie = SEQUENTIAL; - /* triangulation variable */ - enum triangulation_options triangulate = PARTIAL; - /* normal difference variable (in degrees) */ - float norm_difference = (float)360.0; - /* file-type variable */ - enum file_options file_type = ASCII; - - /* User has the wrong number of options */ - if ((argc > 5) || (argc < 2)) - { - printf("Usage: bands -[file_option][ties_option][triangulation_option][normal_difference] in_file_name out_file_name\n"); - exit(0); - } - - /* Interpret the options specified */ - while (--argc > 0 && (*++argv)[0] == '-') - { - /* At the next option that was specified */ - next = 1; - while (c = *++argv[0]) - switch (c) - { - case 'f': - /* Use the first polygon we see. */ - tie = FIRST; - break; - - case 'r': - /* Randomly choose the next polygon */ - tie = RANDOM; - break; - - case 'a': - /* Alternate direction in choosing the next polygon */ - tie = ALTERNATE; - break; - - case 'l': - /* Use lookahead to choose the next polygon */ - tie = LOOK; - break; - - case 'q': - /* Try to reduce swaps */ - tie = SEQUENTIAL; - break; - - case 'p': - /* Use partial triangulation of polygons */ - triangulate = PARTIAL; - break; - - case 'w': - /* Use whole triangulation of polygons */ - triangulate = WHOLE; - break; - - case 'b': - /* Input file is in binary */ - file_type = BINARY; - break; - - case 'g': - /* Strips will be grouped according to the groups in - the data file. We will have to restrict strips to be - in the grouping of the data file. - */ - *group = 1; - - /* Get each the value of the integer */ - /* We have an integer */ - default: - if ((c >= '0') && (c <= '9')) - { - /* More than one normal difference specified, use the last one */ - if (next == 1) - { - count = 0; - next = 0; - } - buffer[count++] = ATOI(c); - } - /* At the decimal point */ - else if (c == '.') - { - /* More than one normal difference specified, use the last one */ - if (next == 1) - { - count = 0; - next = 0; - } - buffer[count++] = -1; - } - else - break; - } - } - /* Convert the buffer of characters to a floating pt integer */ - if (count != 0) - norm_difference = convert_array(buffer,count); - *f = file_type; - *t = tie; - *tr = triangulate; - return norm_difference; -} diff --git a/Tools/Stripe_w/options.h b/Tools/Stripe_w/options.h deleted file mode 100644 index 34c10bcc1..000000000 --- a/Tools/Stripe_w/options.h +++ /dev/null @@ -1,17 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: options.h ------------------------------------------------------------------------*/ - -double get_options(int argc, char **argv, int *f, int *t, int *tr, int *group); -enum file_options {ASCII,BINARY}; -enum tie_options {FIRST, RANDOM, ALTERNATE, LOOK, SEQUENTIAL}; -enum triangulation_options {PARTIAL,WHOLE}; - diff --git a/Tools/Stripe_w/output.c b/Tools/Stripe_w/output.c deleted file mode 100644 index 16eb6abe6..000000000 --- a/Tools/Stripe_w/output.c +++ /dev/null @@ -1,579 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: output.c - This file contains routines that are finding and outputting the - strips from the local algorithm -*/ -/*---------------------------------------------------------------------*/ - -#include -#include -#include "global.h" -#include "polverts.h" -#include "triangulate.h" -#include "partial.h" -#include "sturcts.h" -#include "ties.h" -#include "options.h" -#include "common.h" -#include "util.h" -#include "free.h" - -int *vn; -int *vt; -int norm; -int text; - -int Finished(int *swap, FILE *output, BOOL global) -{ - /* We have finished all the triangles, now is time to output to - the data file. In the strips data structure, every three ids - is a triangle. Now we see whether we can swap, or make a new strip - or continue the strip, and output the data accordingly to the - data file. - */ - int num,x,vertex1,vertex2; - ListHead *pListHead; - int id[2],other1,other2,index = 0,a,b,c; - P_STRIPS temp1,temp2,temp3,temp4,temp5,temp6; - BOOL cptexture; - *swap =0; - - cptexture = text; - pListHead = strips[0]; - if (pListHead == NULL) - return 0; - - num = NumOnList(pListHead); - // WILBUR - // printf ("There are %d triangles in the extend\n",num/3); - - /* Go through the list triangle by triangle */ - temp1 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 0); - temp2 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 1); - temp3 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 2); - - /* Next triangle for lookahead */ - temp4 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 3); - - - /* There is only one polygon in the strip */ - if (temp4 == NULL) - { - /* Data might be mixed and we do not have textures for some of the vertices */ - if ((text) && (vt[temp3->face_id] == 0)) - cptexture = FALSE; - if ((norm) && (!cptexture)) - fprintf(output,"%d//%d %d//%d %d//%d",temp3->face_id+1,vn[temp3->face_id]+1, - temp2->face_id+1,vn[temp2->face_id]+1, - temp1->face_id+1,vn[temp1->face_id]+1); - else if ((cptexture) && (!norm)) - fprintf(output,"%d/%d %d/%d %d/%d",temp3->face_id+1,vt[temp3->face_id]+1, - temp2->face_id+1,vt[temp2->face_id]+1, - temp1->face_id+1,vt[temp1->face_id]+1); - else if ((cptexture)&& (norm)) - fprintf(output,"%d/%d/%d %d/%d/%d %d/%d/%d",temp3->face_id+1,vt[temp3->face_id]+1,vn[temp3->face_id]+1, - temp2->face_id+1,vt[temp2->face_id]+1,vn[temp2->face_id]+1, - temp1->face_id+1,vt[temp1->face_id]+1,vn[temp1->face_id]+1); - else - fprintf(output,"%d %d %d",temp3->face_id+1,temp2->face_id+1,temp1->face_id+1); - Free_Strips(); - return 1; - } - - /* We have a real strip */ - temp5 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 4); - temp6 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 5); - - if ((temp1 == NULL) || (temp2 == NULL) || (temp3 == NULL) || (temp5 == NULL) || (temp6 == NULL)) - { - printf("There is an error in the output of the triangles\n"); - exit(0); - } - - /* Find the vertex in the first triangle that is not in the second */ - vertex1 = Different(temp1->face_id,temp2->face_id,temp3->face_id,temp4->face_id,temp5->face_id,temp6->face_id,&other1,&other2); - /* Find the vertex in the second triangle that is not in the first */ - vertex2 = Different(temp4->face_id,temp5->face_id,temp6->face_id,temp1->face_id,temp2->face_id,temp3->face_id,&other1,&other2); - - /* Lookahead for the correct order of the 2nd and 3rd vertex of the first triangle */ - temp1 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 6); - temp2 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 7); - temp3 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 8); - - if (temp1 != NULL) - other1 = Different(temp3->face_id,temp4->face_id,temp5->face_id,temp1->face_id,temp2->face_id,temp3->face_id,&other1,&a); - - id[index] = vertex1; index = !index; - id[index] = other1; index = !index; - id[index] = other2; index = !index; - - a = temp4->face_id; - b = temp5->face_id; - c = temp6->face_id; - - /* If we need to rearrange the first sequence because otherwise - there would have been a swap. - */ - - if ((temp3 != NULL) && (text) && ( vt[temp3->face_id]==0)) - cptexture = FALSE; - if ((norm) && (!cptexture)) - fprintf(output,"%d//%d %d//%d %d//%d ",vertex1+1,vn[vertex1]+1, - other1+1,vn[other1]+1,other2+1,vn[other2]+1); - else if ((cptexture) && (!norm)) - fprintf(output,"%d/%d %d/%d %d/%d ",vertex1+1,vt[vertex1]+1, - other1+1,vt[other1]+1,other2+1,vt[other2]+1); - else if ((cptexture) && (norm)) - fprintf(output,"%d/%d/%d %d/%d/%d %d/%d/%d ",vertex1+1,vt[vertex1]+1,vn[vertex1]+1, - other1+1,vt[other1]+1,vn[other1]+1,other2+1,vt[other2]+1,vn[other2]+1); - else { - fprintf(output,"%d %d %d ",vertex1+1,other1+1,other2+1); - } - - // original line - // for (x = 6; x < num ; x = x+3) - // Wilbur modified line - for (x = 6; x < num ; x = x+3) - { - /* Get the next triangle */ - temp1 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, x); - temp2 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, x+1); - temp3 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, x+2); - - /* Error checking */ - if (!(member(id[0],a,b,c)) || !(member(id[1],a,b,c)) || !(member(vertex2,a,b,c))) - { - /* If we used partial we might have a break in the middle of a strip */ - fprintf(output,"\nt "); - /* Find the vertex in the first triangle that is not in the second */ - vertex1 = Different(a,b,c,temp1->face_id,temp2->face_id,temp3->face_id,&other1,&other2); - /* Find the vertex in the second triangle that is not in the first */ - vertex2 = Different(temp1->face_id,temp2->face_id,temp3->face_id,a,b,c,&other1,&other2); - - id[index] = vertex1; index = !index; - id[index] = other1; index = !index; - id[index] = other2; index = !index; - } - - if ((temp1 == NULL ) || (temp2 == NULL) || (temp3 == NULL)) - { - printf("There is an error in the triangle list \n"); - exit(0); - } - - if ((id[0] == id[1]) || (id[0] == vertex2)) - continue; - - if ( (member(id[index],temp1->face_id,temp2->face_id,temp3->face_id)) ) - { - if ((text) && ( vt[id[index]]==0)) { - cptexture = FALSE; - } - if ((!norm) && (!cptexture)) { - fprintf(output,"%d ",id[index]+1); - } else if ((norm) && (!cptexture)) { - fprintf(output,"%d//%d ",id[index]+1,vn[id[index]]+1); - } else if ((!norm) && (cptexture)) { - fprintf(output,"%d/%d ",id[index]+1,vt[id[index]]+1); - } else { - fprintf(output,"%d/%d/%d ",id[index]+1,vt[id[index]]+1,vn[id[index]]+1); - } - - index = !index; - *swap = *swap + 1; - } - - if ((text) && ( vt[vertex2]==0)) - cptexture = FALSE; - if ((!norm) && (!cptexture)) - fprintf(output,"\nq %d ",vertex2+1); - else if ((norm) && (!cptexture)) - fprintf(output,"\nq %d//%d ",vertex2+1,vn[vertex2]+1); - else if ((!norm) && (cptexture)) - fprintf(output,"\nq %d/%d ",vertex2+1,vt[vertex2]+1); - else - fprintf(output,"\nq %d/%d/%d ",vertex2+1,vt[vertex2]+1,vn[vertex2]+1); - - id[index] = vertex2; index = !index; - - /* Get the next vertex not in common */ - vertex2 = Different(temp1->face_id,temp2->face_id,temp3->face_id,a,b,c,&other1,&other2); - a = temp1->face_id; - b = temp2->face_id; - c = temp3->face_id; - } - - /* Do the last vertex */ - if ((!norm) && (!cptexture)) - fprintf(output,"\nq %d ",vertex2+1); - else if ((norm) && (!cptexture)) - fprintf(output,"\nq %d//%d ",vertex2+1,vn[vertex2]+1); - else if ((!norm) && (cptexture)) - fprintf(output,"\nq %d/%d ",vertex2+1,vt[vertex2]+1); - else - fprintf(output,"\nq %d/%d/%d ",vertex2+1,vt[vertex2]+1,vn[vertex2]+1); - - Free_Strips(); - return (num/3); -} - - - - - -void Output_Tri(int id1, int id2, int id3,FILE *bands, int color1, int color2, int color3,BOOL end) -{ - /* We will save everything into a list, rather than output at once, - as was done in the old routine. This way for future modifications - we can change the strips later on if we want to. - */ - - int temp1,temp2,temp3; - - /* Make sure we do not have an error */ - /* There are degeneracies in some of the files */ - if ( (id1 == id2) || (id1 == id3) || (id2 == id3)) - { - printf("Degenerate triangle %d %d %d\n",id1,id2,id3); - exit(0); - } - else - { - Last_Edge(&temp1,&temp2,&temp3,0); - Add_Id_Strips(id1,end); - Add_Id_Strips(id2,end); - Add_Id_Strips(id3,end); - Last_Edge(&id1,&id2,&id3,1); - } -} - - -int Polygon_Output(P_ADJACENCIES temp,int face_id,int bucket, - ListHead *pListHead, BOOL first, int *swaps, - FILE *bands,int color1,int color2,int color3,BOOL global, BOOL end) -{ - ListHead *pListFace; - PF_FACES face; - P_ADJACENCIES pfNode; - int next_face_id,next_bucket,e1,e2,e3,other1,other2,other3; - P_ADJACENCIES lpListInfo; - int ties=0; - - /* We have a polygon to output, the id is face id, and the number - of adjacent polygons to it is bucket. This routine extends the patches from - either end to make longer triangle strips. - */ - - - /* Now get the edge */ - Last_Edge(&e1,&e2,&e3,0); - - /* Get the polygon with id face_id */ - pListFace = PolFaces[face_id]; - face = (PF_FACES) PeekList(pListFace,LISTHEAD,0); - - /* We can't go any more */ - if ((face->nPolSize == 1) || ((face->nPolSize == 4) && (global))) /* if global, then we are still doing patches */ - { - /* Remove it from the list so we do not have to waste - time visiting it in the future, or winding up in an infinite loop - if it is the first on that we are looking at for a possible strip - */ - if (face->nPolSize == 1) - RemoveList(pListHead,(PLISTINFO) temp); - if (first) - return 0; - else - return (Finished(swaps,bands,global)); - } - - if (face->nPolSize == 3) - { - /* It is already a triangle */ - if (bucket == 0) - { - /* It is not adjacent to anything so we do not have to - worry about the order of the sides or updating adjacencies - */ - - next_face_id = Different(*(face->pPolygon),*(face->pPolygon+1),*(face->pPolygon+2), - e1,e2,e3,&other1,&other2); - face->nPolSize = 1; - - /* If this is the first triangle in the strip */ - if ((e2 == 0) && (e3 ==0)) - { - e2 = other1; - e3 = other2; - } - - Output_Tri(e2,e3,next_face_id,bands,color1,color2,color3,end); - RemoveList(pListHead,(PLISTINFO) temp); - return (Finished(swaps,bands,global)); - } - - - /* It is a triangle with adjacencies. This means that we - have to: - 1. Update the adjacencies in the list, because we are - using this polygon and it will be deleted. - 2. Get the next polygon. - */ - else - { - /* Return the face_id of the next polygon we will be using, - while updating the adjacency list by decrementing the - adjacencies of everything adjacent to the current triangle. - */ - - next_face_id = Update_Adjacencies(face_id, &next_bucket, &e1,&e2,&ties); - /* Maybe we deleted something in a patch and could not find an adj polygon */ - if (next_face_id == -1) - { - Output_Tri(*(face->pPolygon),*(face->pPolygon+1),*(face->pPolygon+2),bands,color1, - color2,color3,end); - face->nPolSize = 1; - RemoveList(pListHead,(PLISTINFO) temp); - return (Finished(swaps,bands,global)); - } - - /* Find the other vertex to transmit in the triangle */ - e3 = Return_Other(face->pPolygon,e1,e2); - Last_Edge(&other1,&other2,&other3,0); - - if ((other2 != 0) && (other3 != 0)) - { - /* See which vertex in the output edge is not in the input edge */ - if ((e1 != other2) && (e1 != other3)) - e3 = e1; - else if ((e2 != other2) && (e2 != other3)) - e3 = e2; - else - { - printf("There is an error in the tri with adj\n"); - exit(0); - } - - /* See which vertex of the input edge is not in the output edge */ - if ((other2 != e1) && (other2 != e2)) - { - other1 = other2; - other2 = other3; - } - else if ((other3 != e1) && (other3 != e2)) - other1 = other3; - else - { - printf("There is an error in getting the tri with adj\n"); - exit(0); - } - - } - else - { - /* We are the first triangle in the strip and the starting edge - has not been set yet - */ - /* Maybe we deleted something in a patch and could not find an adj polygon */ - if (next_face_id == -1) - { - Output_Tri(*(face->pPolygon),*(face->pPolygon+1),*(face->pPolygon+2),bands,color1, - color2,color3,end); - face->nPolSize = 1; - RemoveList(pListHead,(PLISTINFO) temp); - return (Finished(swaps,bands,global)); - } - - other1 = e3; - e3 = e2; - other2 = e1; - } - - /* At this point the adjacencies have been updated and we - have the next polygon id - */ - - Output_Tri(other1,other2,e3,bands,color1,color2,color3,end); - face->nPolSize = 1; - RemoveList(pListHead,(PLISTINFO) temp); - - /* Maybe we deleted something in a patch and could not find an adj polygon */ - if (next_face_id == -1) - return (Finished(swaps,bands,global)); - - if (Done(next_face_id,59,&next_bucket) == NULL) - { - printf("We deleted the next face 4%d\n",next_face_id); - exit(0); - } - - pListHead = array[next_bucket]; - pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) ); - if ( pfNode ) - pfNode->face_id = next_face_id; - lpListInfo = (P_ADJACENCIES) (SearchList(array[next_bucket], pfNode, - (int (*)(void *,void *)) (Compare))); - if (lpListInfo == NULL) - { - printf("There is an error finding the next polygon3 %d\n",next_face_id); - exit(0); - } - return (Polygon_Output(lpListInfo,next_face_id,next_bucket, - pListHead, FALSE, swaps,bands,color1,color2,color3,global,end)); - - } - } - - else - { - /* It is not a triangle, we have to triangulate it . - Since it is not adjacent to anything we can triangulate it - blindly - */ - if (bucket == 0) - { - /* It is the first polygon in the strip, therefore there is no - input edge to start with. - */ - if ((e2 == 0) && (e3 ==0)) - Blind_Triangulate(face->nPolSize,face->pPolygon,bands, - TRUE,1,color1,color2,color3); - - else - Blind_Triangulate(face->nPolSize,face->pPolygon,bands, - FALSE,1,color1,color2,color3); - - RemoveList(pListHead,(PLISTINFO) temp); - - /* We will be at the beginning of the next strip. */ - face->nPolSize = 1; - return (Finished(swaps,bands,global)); - } - - - else - { - - - /* WHOLE triangulation */ - /* It is not a triangle and has adjacencies. - This means that we have to: - 1. Triangulate this polygon, not blindly because - we have an edge that we want to come out on, that - is the edge that is adjacent to a polygon with the - least number of adjacencies. Also we must come in - on the last seen edge. - 2. Update the adjacencies in the list, because we are - using this polygon . - 3. Get the next polygon. - */ - /* Return the face_id of the next polygon we will be using, - while updating the adjacency list by decrementing the - adjacencies of everything adjacent to the current polygon. - */ - - next_face_id = Update_Adjacencies(face_id, &next_bucket, &e1,&e2,&ties); - - /* Maybe we deleted something in a patch and could not find an adj polygon */ - if (next_face_id == -1) - { - - /* If we are at the first polygon in the strip and there is no input - edge, then begin is TRUE - */ - if ((e2 == 0) && (e3 == 0)) - Blind_Triangulate(face->nPolSize,face->pPolygon, - bands,TRUE,1,color1,color2,color3); - - else - Blind_Triangulate(face->nPolSize,face->pPolygon, - bands,FALSE,1,color1,color2,color3); - - RemoveList(pListHead,(PLISTINFO) temp); - - /* We will be at the beginning of the next strip. */ - face->nPolSize = 1; - return (Finished(swaps,bands,global)); - } - - if (Done(next_face_id,59,&next_bucket) == NULL) - { - printf("We deleted the next face 6 %d %d\n",next_face_id,face_id); - exit(0); - } - - Non_Blind_Triangulate(face->nPolSize,face->pPolygon, - bands,next_face_id,face_id,1,color1,color2,color3); - - RemoveList(pListHead,(PLISTINFO) temp); - face->nPolSize = 1; - pListHead = array[next_bucket]; - pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) ); - if ( pfNode ) - pfNode->face_id = next_face_id; - lpListInfo = (P_ADJACENCIES) (SearchList(array[next_bucket], pfNode, - (int (*)(void *,void *)) (Compare))); - if (lpListInfo == NULL) - { - printf("There is an error finding the next polygon2 %d %d\n",next_face_id,next_bucket); - exit(0); - } - return (Polygon_Output(lpListInfo,next_face_id,next_bucket, - pListHead, FALSE, swaps,bands,color1,color2,color3,global,end)); - } - - } - Last_Edge(&e1,&e2,&e3,0); - -} - - -int Extend_Face(int face_id,int e1,int e2,int *swaps,FILE *bands, - int color1,int color2,int color3,int *vert_norm, int normals, - int *vert_texture, int texture) -{ - int dummy=0,next_bucket; - P_ADJACENCIES pfNode,lpListInfo; - ListHead *pListHead; - - /* Try to extend backwards off of the local strip that we just found */ - - vn = vert_norm; - vt = vert_texture; - norm = normals; - text = texture; - - *swaps = 0; - /* Find the face that is adjacent to the edge and is not the - current face. - */ - face_id = Find_Face(face_id, e1, e2,&next_bucket); - if (face_id == -1) - return 0; - - pListHead = array[next_bucket]; - pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) ); - if ( pfNode ) - pfNode->face_id = face_id; - lpListInfo = (P_ADJACENCIES) (SearchList(array[next_bucket], pfNode, - (int (*)(void *,void *)) (Compare))); - if (lpListInfo == NULL) - { - printf("There is an error finding the next polygon3 %d\n",face_id); - exit(0); - } - Last_Edge(&dummy,&e1,&e2,1); - - /* Find a strip extending from the patch and return the cost */ - return (Polygon_Output(lpListInfo,face_id,next_bucket,pListHead,TRUE,swaps,bands,color1,color2,color3,TRUE,TRUE)); -} - - diff --git a/Tools/Stripe_w/output.h b/Tools/Stripe_w/output.h deleted file mode 100644 index fd4b34c27..000000000 --- a/Tools/Stripe_w/output.h +++ /dev/null @@ -1,34 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: output.h ------------------------------------------------------------------------*/ - - -#include "polverts.h" - -#define TRIANGLE 3 -#define MAGNITUDE 1000000 - -void Output_Tri(int id1, int id2, int id3,FILE *bands, int color1, - int color2, int color3,BOOL end); -void Sgi_Test(); -int Polygon_Output(P_ADJACENCIES temp,int face_id,int bucket, - ListHead *pListHead, BOOL first, int *swaps, - FILE *bands,int color1,int color2,int color3, - BOOL global, BOOL end); -void Last_Edge(); -void Extend_Backwards(); -int Finished(int *swap, FILE *output, BOOL global); -int Extend_Face(int face_id,int e1,int e2,int *swaps,FILE *bands, - int color1,int color2,int color3,int *vert_norm, int normals, - int *vert_texture, int texture); -void Fast_Reset(); - - diff --git a/Tools/Stripe_w/outputex.c b/Tools/Stripe_w/outputex.c deleted file mode 100644 index 10bfb741f..000000000 --- a/Tools/Stripe_w/outputex.c +++ /dev/null @@ -1,514 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: outputex.c - This file contains routines that are used for various functions in - the local algorithm. -*/ -/*---------------------------------------------------------------------*/ - - -#include -#include -#include "global.h" -#include "outputex.h" -#include "triangulatex.h" -#include "polverts.h" -#include "ties.h" -#include "partial.h" -#include "sturctsex.h" -#include "options.h" -#include "output.h" -#include "common.h" -#include "util.h" - - -void Output_TriEx(int id1, int id2, int id3, FILE *output, int next_face, int flag, - int where) -{ - /* We will save everything into a list, rather than output at once, - as was done in the old routine. This way for future modifications - we can change the strips later on if we want to. - */ - - int swap,temp1,temp2,temp3; - static int total=0; - static int tri=0; - static int strips = 0; - static int cost = 0; - - if (flag == -20) - { - cost = cost + where+total+tri+strips+strips; - printf("We will need to send %d vertices to the renderer\n",cost); - total = 0; - tri = 0; - strips = 0; - return ; - } - - - if (flag == -10) /* We are finished, now is time to output the triangle list */ - { - fprintf(output,"\nt "); - tri = tri + Finished(&swap,output,FALSE); - total = total + swap; - strips++; - /*printf("There are %d swaps %d tri %d strips\n",total,tri,strips);*/ - } - - else - { - Last_Edge(&temp1,&temp2,&temp3,0); - Add_Id_Strips(id1,where); - Add_Id_Strips(id2,where); - Add_Id_Strips(id3,where); - Last_Edge(&id1,&id2,&id3,1); - } -} - - - - -void Extend_BackwardsEx(int face_id, FILE *output, FILE *strip, int *ties, - int tie, int triangulate, int swaps, int *next_id) -{ - /* We just made a strip, now we are going to see if we can extend - backwards from the starting face, which had 2 or more adjacencies - to start with. - */ - int bucket,next_face,num,x,y,z,c,max,f; - ListHead *pListFace; - PF_FACES face; - P_ADJACENCIES temp; - - /* Get the first triangle that we have saved the the strip data - structure, so we can see if there are any polygons adjacent - to this edge or a neighboring one - */ - First_Edge(&x,&y,&z); - - pListFace = PolFaces[face_id]; - face = (PF_FACES) PeekList(pListFace,LISTHEAD,0); - - num = face->nPolSize; - - /* Go through the edges to see if there is an adjacency - with a vertex in common to the first triangle that was - outputted in the strip. (maybe edge was deleted....) - */ - for (c=0; cpPolygon+c) == x) && (*(face->pPolygon+c+1) == y)) || - (*(face->pPolygon+c) == y) && (*(face->pPolygon+c+1) == x))) - { - /* Input edge is still there see if there is an adjacency */ - next_face = Find_Face(face_id, x, y, &bucket); - if (next_face == -1) - /* Could not find a face adjacent to the edge */ - break; - pListFace = array[bucket]; - max = NumOnList(pListFace); - for (f=0;;f++) - { - temp = (P_ADJACENCIES) PeekList(pListFace,LISTHEAD,f); - if (temp->face_id == next_face) - { - Last_Edge(&z,&y,&x,1); - Polygon_OutputEx(temp,temp->face_id,bucket,pListFace, - output,strip,ties,tie,triangulate,swaps,next_id,0); - return; - } - - if (temp == NULL) - { - printf("Error in the new buckets%d %d %d\n",bucket,max,0); - exit(0); - } - } - - } - else if ( (c == (num -1)) && - ( ((*(face->pPolygon) == x) && (*(face->pPolygon+num-1) == y)) || - (*(face->pPolygon) == y) && (*(face->pPolygon+num-1) == x))) - { - next_face = Find_Face(face_id,x,y,&bucket); - if (next_face == -1) - /* Could not find a face adjacent to the edge */ - break; - pListFace = array[bucket]; - max = NumOnList(pListFace); - for (f=0;;f++) - { - temp = (P_ADJACENCIES) PeekList(pListFace,LISTHEAD,f); - if (temp->face_id == next_face) - { - Last_Edge(&z,&y,&x,1); - Polygon_OutputEx(temp,temp->face_id,bucket,pListFace, - output,strip,ties,tie,triangulate,swaps,next_id,0); - return; - } - - if (temp == NULL) - { - printf("Error in the new buckets%d %d %d\n",bucket,max,0); - exit(0); - } - } - } - - } - -} - -void Polygon_OutputEx(P_ADJACENCIES temp,int face_id,int bucket, - ListHead *pListHead, FILE *output, FILE *strips, - int *ties, int tie, int triangulate, int swaps, - int *next_id, int where) -{ - ListHead *pListFace; - PF_FACES face; - P_ADJACENCIES pfNode; - static BOOL begin = TRUE; - int old_face,next_face_id,next_bucket,e1,e2,e3,other1,other2,other3; - P_ADJACENCIES lpListInfo; - - /* We have a polygon to output, the id is face id, and the number - of adjacent polygons to it is bucket. - */ - - Last_Edge(&e1,&e2,&e3,0); - - /* Get the polygon with id face_id */ - pListFace = PolFaces[face_id]; - face = (PF_FACES) PeekList(pListFace,LISTHEAD,0); - - if (face->nPolSize == 3) - { - /* It is already a triangle */ - if (bucket == 0) - { - /* It is not adjacent to anything so we do not have to - worry about the order of the sides or updating adjacencies - */ - - Last_Edge(&e1,&e2,&e3,0); - next_face_id = Different(*(face->pPolygon),*(face->pPolygon+1),*(face->pPolygon+2), - e1,e2,e3,&other1,&other2); - /* No input edge, at the start */ - if ((e2 ==0) && (e3 == 0)) - { - e2 = other1; - e3 = other2; - } - - Output_TriEx(e2,e3,next_face_id,strips,-1,begin,where); - RemoveList(pListHead,(PLISTINFO) temp); - /* We will be at the beginning of the next strip. */ - begin = TRUE; - } - /* It is a triangle with adjacencies. This means that we - have to: - 1. Update the adjacencies in the list, because we are - using this polygon and it will be deleted. - 2. Get the next polygon. - */ - else - { - /* Return the face_id of the next polygon we will be using, - while updating the adjacency list by decrementing the - adjacencies of everything adjacent to the current triangle. - */ - - next_face_id = Update_AdjacenciesEx(face_id, &next_bucket, &e1,&e2,ties); - old_face = next_face_id; - - /* Break the tie, if there was one */ - if (tie != FIRST) - old_face = Get_Next_Face(tie,face_id,triangulate); - - if (next_face_id == -1) - { - Polygon_OutputEx(temp,face_id,0,pListHead,output,strips,ties,tie, - triangulate,swaps,next_id,where); - return; - } - - - /* We are using a different face */ - if ((tie != FIRST) && (old_face != next_face_id) && (swaps == ON)) - { - next_face_id = old_face; - /* Get the new output edge, since e1 and e2 are for the - original next face that we got. - */ - e3 = Get_EdgeEx(&e1,&e2,face->pPolygon,next_face_id,face->nPolSize,0,0); - } - - /* Find the other vertex to transmit in the triangle */ - e3 = Return_Other(face->pPolygon,e1,e2); - Last_Edge(&other1,&other2,&other3,0); - - if ((other1 != 0) && (other2 != 0)) - { - /* See which vertex in the output edge is not in the input edge */ - if ((e1 != other2) && (e1 != other3)) - e3 = e1; - else if ((e2 != other2) && (e2 != other3)) - e3 = e2; - /* can happen with > 2 polys on an edge but won't form a good strip so stop - the strip here - */ - else - { - Polygon_OutputEx(temp,face_id,0,pListHead,output,strips,ties,tie, - triangulate,swaps,next_id,where); - return; - } - - /* See which vertex of the input edge is not in the output edge */ - if ((other2 != e1) && (other2 != e2)) - { - other1 = other2; - other2 = other3; - } - else if ((other3 != e1) && (other3 != e2)) - other1 = other3; - else - { - /* Degenerate triangle just return*/ - Output_TriEx(other1,other2,e3,strips,next_face_id,begin,where); - RemoveList(pListHead,(PLISTINFO) temp); - begin = FALSE; - return; - } - - } - - /* There was not an input edge, we are the first triangle in a strip */ - else - { - /* Find the correct order to transmit the triangle, what is - the output edge that we want ? - */ - other1 = e3; - e3 = e2; - other2 = e1; - } - - /* At this point the adjacencies have been updated and we - have the next polygon id - */ - Output_TriEx(other1,other2,e3,strips,next_face_id,begin,where); - RemoveList(pListHead,(PLISTINFO) temp); - begin = FALSE; - - if (Done(next_face_id,59,&next_bucket) == NULL) - return; - - pListHead = array[next_bucket]; - pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) ); - if ( pfNode ) - pfNode->face_id = next_face_id; - lpListInfo = (P_ADJACENCIES) (SearchList(array[next_bucket], pfNode, - (int (*)(void *,void *)) (Compare))); - if (lpListInfo == NULL) - { - printf("There is an error finding the next polygon3 %d\n",next_face_id); - exit(0); - } - Polygon_OutputEx(lpListInfo,next_face_id,next_bucket, - pListHead, output, strips,ties,tie,triangulate,swaps,next_id,where); - - } -} - - else - { - /* It is not a triangle, we have to triangulate it . - Since it is not adjacent to anything we can triangulate it - blindly - */ - if (bucket == 0) - { - /* Check to see if there is not an input edge */ - Last_Edge(&other1,&other2,&other3,0); - if ((other1 == 0) && (other2 ==0)) - Blind_TriangulateEx(face->nPolSize,face->pPolygon, strips, - output,TRUE,where); - else - Blind_TriangulateEx(face->nPolSize,face->pPolygon,strips, - output,FALSE,where); - - RemoveList(pListHead,(PLISTINFO) temp); - /* We will be at the beginning of the next strip. */ - begin = TRUE; - } - - /* If we have specified PARTIAL triangulation then - we will go to special routines that will break the - polygon and update the data structure. Else everything - below will simply triangulate the whole polygon - */ - else if (triangulate == PARTIAL) - { - - /* Return the face_id of the next polygon we will be using, - */ - next_face_id = Min_Face_AdjEx(face_id,&next_bucket,ties); - - - /* Don't do it partially, because we can go inside and get - less adjacencies, for a quad we can do the whole thing. - */ - if ((face_id == next_face_id) && (face->nPolSize == 4) && (swaps == ON)) - { - next_face_id = Update_AdjacenciesEx(face_id, &next_bucket, &e1,&e2,ties); - if (next_face_id == -1) - { - /* There is no sequential face to go to, end the strip */ - Polygon_OutputEx(temp,face_id,0,pListHead,output,strips,ties,tie, - triangulate,swaps,next_id,where); - return; - } - - /* Break the tie, if there was one */ - if (tie != FIRST) - next_face_id = Get_Next_Face(tie,face_id,triangulate); - Non_Blind_TriangulateEx(face->nPolSize,face->pPolygon, strips, - output,next_face_id,face_id,where); - RemoveList(pListHead,(PLISTINFO) temp); - } - - /* Was not a quad but we still do not want to do it partially for - now, since we want to only do one triangle at a time - */ - else if ((face_id == next_face_id) && (swaps == ON)) - Inside_Polygon(face->nPolSize,face->pPolygon,strips,output, - next_face_id,face_id,next_id,pListHead,temp,where); - - else - { - if ((tie != FIRST) && (swaps == ON)) - next_face_id = Get_Next_Face(tie,face_id,triangulate); - Partial_Triangulate(face->nPolSize,face->pPolygon,strips, - output,next_face_id,face_id,next_id,pListHead,temp,where); - /* Check the next bucket again ,maybe it changed - We calculated one less, but that might not be the case - */ - } - - if (Done(next_face_id,59,&next_bucket) == NULL) - { - /* Check to see if there is not an input edge */ - Last_Edge(&other1,&other2,&other3,0); - if ((other1 == 0) && (other2 ==0)) - Blind_TriangulateEx(face->nPolSize,face->pPolygon, strips, - output,TRUE,where); - else - Blind_TriangulateEx(face->nPolSize,face->pPolygon,strips, - output,FALSE,where); - - if (Done(face_id,59,&bucket) != NULL) - { - pListHead = array[bucket]; - pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) ); - if ( pfNode ) - pfNode->face_id = face_id; - lpListInfo = (P_ADJACENCIES) (SearchList(array[bucket], pfNode, - (int (*)(void *,void *)) (Compare))); - RemoveList(pListHead,(PLISTINFO)lpListInfo); - } - begin = TRUE; - return; - } - - begin = FALSE; - pListHead = array[next_bucket]; - pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) ); - if ( pfNode ) - pfNode->face_id = next_face_id; - lpListInfo = (P_ADJACENCIES) (SearchList(array[next_bucket], pfNode, - (int (*)(void *,void *)) (Compare))); - if (lpListInfo == NULL) - { - printf("There is an error finding the next polygon1 %d %d\n",next_face_id,next_bucket); - exit(0); - } - Polygon_OutputEx(lpListInfo,next_face_id,next_bucket, - pListHead, output, strips,ties,tie,triangulate,swaps,next_id,where); - } - - - else - { - /* WHOLE triangulation */ - /* It is not a triangle and has adjacencies. - This means that we have to: - 1. TriangulateEx this polygon, not blindly because - we have an edge that we want to come out on, that - is the edge that is adjacent to a polygon with the - least number of adjacencies. Also we must come in - on the last seen edge. - 2. Update the adjacencies in the list, because we are - using this polygon . - 3. Get the next polygon. - */ - /* Return the face_id of the next polygon we will be using, - while updating the adjacency list by decrementing the - adjacencies of everything adjacent to the current polygon. - */ - - next_face_id = Update_AdjacenciesEx(face_id, &next_bucket, &e1,&e2,ties); - - if (Done(next_face_id,59,&next_bucket) == NULL) - { - Polygon_OutputEx(temp,face_id,0,pListHead,output,strips,ties,tie, - triangulate,swaps,next_id,where); - /* Because maybe there was more than 2 polygons on the edge */ - return; - } - - /* Break the tie, if there was one */ - else if (tie != FIRST) - next_face_id = Get_Next_Face(tie,face_id,triangulate); - - Non_Blind_TriangulateEx(face->nPolSize,face->pPolygon, strips, - output,next_face_id,face_id,where); - RemoveList(pListHead,(PLISTINFO) temp); - begin = FALSE; - pListHead = array[next_bucket]; - pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) ); - if ( pfNode ) - pfNode->face_id = next_face_id; - lpListInfo = (P_ADJACENCIES) (SearchList(array[next_bucket], pfNode, - (int (*)(void *,void *)) (Compare))); - if (lpListInfo == NULL) - { - printf("There is an error finding the next polygon2 %d %d\n",next_face_id,next_bucket); - exit(0); - } - Polygon_OutputEx(lpListInfo,next_face_id,next_bucket, - pListHead, output, strips,ties,tie,triangulate,swaps,next_id,where); - } - - } - Last_Edge(&e1,&e2,&e3,0); - -} - - - - - - - - diff --git a/Tools/Stripe_w/outputex.h b/Tools/Stripe_w/outputex.h deleted file mode 100644 index f59f7e75c..000000000 --- a/Tools/Stripe_w/outputex.h +++ /dev/null @@ -1,31 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: outputex.h ------------------------------------------------------------------------*/ - - -#include "polverts.h" - - -#define TRIANGLE 3 -#define MAGNITUDE 1000000 - -void Output_TriEx(int id1, int id2, int id3, FILE *output, int next_face, - int flag, int where); -void Sgi_Test(); -void Polygon_OutputEx(P_ADJACENCIES temp,int face_id,int bucket, - ListHead *pListHead, FILE *output, FILE *strips, - int *ties, int tie, int triangulate, int swaps, - int *next_id, int where); -void Extend_BackwardsEx(int face_id, FILE *output, FILE *strip, int *ties, - int tie, int triangulate, int swaps,int *next_id); -void FinishedEx(); - - diff --git a/Tools/Stripe_w/partial.c b/Tools/Stripe_w/partial.c deleted file mode 100644 index 847b40501..000000000 --- a/Tools/Stripe_w/partial.c +++ /dev/null @@ -1,668 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: partial.c - This file contains routines that are used partial triangulation of polygons -*/ -/*---------------------------------------------------------------------*/ - -#include -#include -#include -#include "global.h" -#include "outputex.h" -#include "polyvertsex.h" -#include "triangulatex.h" -#include "sturctsex.h" -#include "polverts.h" -#include "common.h" -#include "util.h" - -void P_Triangulate_Quad(int out_edge1,int out_edge2,int in_edge1, - int in_edge2,int size,int *index, - FILE *output,FILE *fp,int reversed,int face_id, - int *next_id,ListHead *pListHead, - P_ADJACENCIES temp, - int where) -{ - int vertex4,vertex5,dummy=60; - - /* This routine will nonblindly triangulate a quad, meaning - that there is a definite input and a definite output - edge that we must adhere to. Reversed will tell the orientation - of the input edge. (Reversed is -1 is we do not have an input - edge, in other words we are at the beginning of a strip.) - Out_edge* is the output edge, and in_edge* is the input edge. - Index are the edges of the polygon - and size is the size of the polygon. Begin is whether we are - at the start of a new strip. - Note that we will not necessarily triangulate the whole quad; - maybe we will do half and leave the other half (a triangle) - for later. - */ - - - /* If we do not have an input edge, then we can make our input - edge whatever we like, therefore it will be easier to come - out on the output edge. In this case the whole quad is done. - */ - if (reversed == -1) - { - vertex4 = AdjacentEx(out_edge1,out_edge2,index,size); - vertex5 = Get_Other_Vertex(vertex4,out_edge1,out_edge2,index); - Output_TriEx(vertex5,vertex4,out_edge1,output,-1,-1,where); - Output_TriEx(vertex4,out_edge1,out_edge2,output,-1,-1,where); - dummy = Update_AdjacenciesEx(face_id, &dummy, &dummy,&dummy,&dummy); - RemoveList(pListHead,(PLISTINFO) temp); - return; - } - - /* These are the 5 cases that we can have for the output edge */ - - /* Are they consecutive so that we form a triangle to - peel off, but cannot use the whole quad? - */ - - if (in_edge2 == out_edge1) - { - /* Output the triangle that comes out the correct - edge. Save the other half for later. - */ - vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge2,index); - Output_TriEx(in_edge1,in_edge2,out_edge2,output,-1,-1,where); - /* Now we have a triangle used, and a triangle that is - left for later. - */ - - /* Now delete the adjacencies by one for all the faces - that are adjacent to the triangle that we just outputted. - */ - Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy, - face_id,&dummy,&dummy,&dummy); - Delete_AdjEx(out_edge2,in_edge2,&dummy,&dummy, - face_id,&dummy,&dummy,&dummy); - /* Put the new face in the proper bucket of adjacencies - There are 2 edges that need to be checked for the triangle - that was just outputted. For the output edge we definitely - will be decreasing the adjacency, but we must check for the - input edge. - */ - - dummy = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp,FALSE); - dummy = Change_FaceEx(face_id,in_edge2,out_edge2,pListHead,temp,TRUE); - - /* Update the face data structure, by deleting the old - face and putting in the triangle as the new face - */ - New_Face(face_id,in_edge1,out_edge2,vertex4); - return; - } - else if (in_edge1 == out_edge1) - { - /* We want to output the first triangle (whose output - edge is not the one that we want. - We have to find the vertex that we need, which is - the other vertex which we do not have. - */ - vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge2,index); - Output_TriEx(in_edge2,in_edge1,out_edge2,output,-1,-1,where); - /* Now we have a triangle used, and a triangle that is - left for later. - */ - - /* Now delete the adjacencies by one for all the faces - that are adjacent to the triangle that we just outputted. - */ - Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id, - &dummy,&dummy,&dummy); - Delete_AdjEx(out_edge2,out_edge1,&dummy,&dummy, - face_id,&dummy,&dummy,&dummy); - - /* Put the new face in the proper bucket of adjacencies */ - dummy = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp,FALSE); - dummy = Change_FaceEx(face_id,in_edge1,out_edge2,pListHead,temp,TRUE); - - /* Update the face data structure, by deleting the old - face and putting in the triangle as the new face - */ - New_Face(face_id,in_edge2,out_edge2,vertex4); - return; - } - - /* Consecutive cases again, but with the output edge reversed */ - else if (in_edge1 == out_edge2) - { - vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge1,index); - Output_TriEx(in_edge2,in_edge1,out_edge1,output,-1,-1,where); - /* Now we have a triangle used, and a triangle that is - left for later. - */ - - /* Now delete the adjacencies by one for all the faces - that are adjacent to the triangle that we just outputted. - */ - Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id, - &dummy,&dummy,&dummy); - Delete_AdjEx(out_edge2,out_edge1,&dummy,&dummy, - face_id,&dummy,&dummy,&dummy); - - /* Put the new face in the proper bucket of adjacencies */ - dummy = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp,FALSE); - dummy = Change_FaceEx(face_id,out_edge1,out_edge2,pListHead,temp,TRUE); - - /* Update the face data structure, by deleting the old - face and putting in the triangle as the new face - */ - New_Face(face_id,in_edge2,out_edge1,vertex4); - return; - } - else if (in_edge2 == out_edge2) - { - vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge1,index); - Output_TriEx(in_edge1,in_edge2,out_edge1,output,-1,-1,where); - /* Now we have a triangle used, and a triangle that is - left for later. - */ - /* Now delete the adjacencies by one for all the faces - that are adjacent to the triangle that we just outputted. - */ - Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id, - &dummy,&dummy,&dummy); - Delete_AdjEx(out_edge2,out_edge1,&dummy,&dummy, - face_id,&dummy,&dummy,&dummy); - - /* Put the new face in the proper bucket of adjacencies */ - dummy = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp,FALSE); - dummy = Change_FaceEx(face_id,out_edge1,out_edge2,pListHead,temp,TRUE); - - /* Update the face data structure, by deleting the old - face and putting in the triangle as the new face - */ - New_Face(face_id,in_edge1,out_edge1,vertex4); - return; - } - - /* The final case is where we want to come out the opposite - edge. - */ - else - { - if( ((!reversed) && (out_edge1 == (AdjacentEx(in_edge1,in_edge2,index,size)))) || - ((reversed) && (out_edge2 == (AdjacentEx(in_edge2,in_edge1,index,size))))) - { - /* We need to know the orientation of the input - edge, so we know which way to put the diagonal. - And also the output edge, so that we triangulate - correctly. Does not need partial. - */ - Output_TriEx(in_edge1,in_edge2,out_edge2,output,-1,-1,where); - Output_TriEx(in_edge2,out_edge2,out_edge1,output,-1,-1,where); - dummy = Update_AdjacenciesEx(face_id, &dummy, &dummy,&dummy,&dummy); - RemoveList(pListHead,(PLISTINFO) temp); - } - else - { - /* Input and output orientation was reversed, so diagonal will - be reversed from above. - */ - Output_TriEx(in_edge1,in_edge2,out_edge1,output,-1,-1,where); - Output_TriEx(in_edge2,out_edge1,out_edge2,output,-1,-1,where); - dummy = Update_AdjacenciesEx(face_id, &dummy, &dummy,&dummy,&dummy); - RemoveList(pListHead,(PLISTINFO) temp); - } - return; - } -} - -void P_Triangulate_Polygon(int out_edge1,int out_edge2,int in_edge1, - int in_edge2,int size, - int *index,FILE *output,FILE *fp, - int reversed,int face_id,int *next_id, - ListHead *pListHead, P_ADJACENCIES temp2, - int where) -{ - /* We have a polygon greater than 4 sides, which we wish - to partially triangulate - */ - int next_bucket,vertex4,dummy = 60; - int *temp; - P_ADJACENCIES pfNode; - - - /* Since we are calling this recursively, we have to check whether - we are down to the case of the quad. - */ - if (size == 4) - { - P_Triangulate_Quad(out_edge1,out_edge2,in_edge1,in_edge2,size, - index,output,fp,reversed,face_id,next_id, - pListHead,temp2,where); - return; - } - - /* We do not have a specified input edge, and therefore we - can make it anything we like, as long as we still come out - the output edge that we want. - */ - if (reversed == -1) - { - /* Get the vertex for the last triangle, which is - the one coming out the output edge, before we do - any deletions to the list. We will be doing this - bottom up. - */ - vertex4 = AdjacentEx(out_edge1,out_edge2,index,size); - temp = (int *) malloc(sizeof(int) * size); - memcpy(temp,index,sizeof(int)*size); - Delete_From_ListEx(out_edge2,index,size); - /* We do not have to partially triangulate, since - we will do the whole thing, so use the whole routine - */ - /* Triangulate_PolygonEx(vertex4,out_edge1,in_edge2, - vertex4,size-1,index,output,fp,reversed, - face_id,next_id,pListHead,temp2,where); */ - Triangulate_PolygonEx(vertex4,out_edge1,in_edge2, - vertex4,size-1,index,output,fp,reversed, - face_id,where); - memcpy(index,temp,sizeof(int)*size); - /* Lastly do the triangle that comes out the output - edge. - */ - Output_TriEx(vertex4,out_edge1,out_edge2,output,-1,-1,where); - /* We were able to do the whole polygon, now we - can delete the whole thing from our data structure. - */ - dummy = Update_AdjacenciesEx(face_id, &dummy, &dummy,&dummy,&dummy); - RemoveList(pListHead,(PLISTINFO) temp2); - return; - } - - /* These are the 5 cases that we can have for the output edge */ - - /* Are they consecutive so that we form a triangle to - peel off that comes out the correct output edge, - but we cannot use the whole polygon? - */ - if (in_edge2 == out_edge1) - { - Output_TriEx(in_edge1,out_edge1,out_edge2,output,-1,-1,where); - - /* Now delete the adjacencies by one for all the faces - that are adjacent to the triangle that we just outputted. - */ - Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id, - &dummy,&dummy,&dummy); - Delete_AdjEx(out_edge2,out_edge1,&dummy,&dummy, - face_id,&dummy,&dummy,&dummy); - - /* Put the new face in the proper bucket of adjacencies */ - next_bucket = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE); - next_bucket = Change_FaceEx(face_id,out_edge1,out_edge2,pListHead,temp2,TRUE); - - /* Create a new edgelist without the triangle that - was just outputted. - */ - Delete_From_ListEx(in_edge2,index,size); - /* Update the face data structure, by deleting the old - face and putting in the polygon minus the triangle - as the new face, here we will be decrementing the size - by one. - */ - New_Size_Face(face_id); - return; - } - - /* Next case is where it is again consecutive, but the triangle - formed by the consecutive edges do not come out of the - correct output edge. (the input edge will be reversed in - the next triangle) - */ - else if (in_edge1 == out_edge1) - { - /* Get vertex adjacent to in_edge2, but is not in_edge1 */ - Output_TriEx(in_edge2,in_edge1,out_edge2,output,-1,-1,where); - - /* Now delete the adjacencies by one for all the faces - that are adjacent to the triangle that we just outputted. - */ - Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id, - &dummy,&dummy,&dummy); - Delete_AdjEx(out_edge2,out_edge1,&dummy,&dummy, - face_id,&dummy,&dummy,&dummy); - - /* Put the new face in the proper bucket of adjacencies */ - next_bucket = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE); - next_bucket = Change_FaceEx(face_id,out_edge1,out_edge2,pListHead,temp2,TRUE); - - /* Create a new edgelist without the triangle that - was just outputted. - */ - Delete_From_ListEx(in_edge1,index,size); - /* Update the face data structure, by deleting the old - face and putting in the polygon minus the triangle - as the new face, here we will be decrementing the size - by one. - */ - New_Size_Face(face_id); - return; - } - - /* Consecutive cases again, but with the output edge reversed */ - else if (in_edge1 == out_edge2) - { - Output_TriEx(in_edge2,in_edge1,out_edge1,output,-1,-1,where); - - /* Now delete the adjacencies by one for all the faces - that are adjacent to the triangle that we just outputted. - */ - Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id, - &dummy,&dummy,&dummy); - Delete_AdjEx(out_edge1,out_edge2,&dummy,&dummy, - face_id,&dummy,&dummy,&dummy); - - /* Put the new face in the proper bucket of adjacencies */ - next_bucket = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE); - next_bucket = Change_FaceEx(face_id,out_edge1,out_edge2,pListHead,temp2,TRUE); - - /* Create a new edgelist without the triangle that - was just outputted. - */ - Delete_From_ListEx(in_edge1,index,size); - /* Update the face data structure, by deleting the old - face and putting in the polygon minus the triangle - as the new face, here we will be decrementing the size - by one. - */ - New_Size_Face(face_id); - return; - } - else if (in_edge2 == out_edge2) - { - Output_TriEx(in_edge1,in_edge2,out_edge1,output,-1,-1,where); - - /* Now delete the adjacencies by one for all the faces - that are adjacent to the triangle that we just outputted. - */ - Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id, - &dummy,&dummy,&dummy); - Delete_AdjEx(out_edge2,out_edge1,&dummy,&dummy, - face_id,&dummy,&dummy,&dummy); - - /* Put the new face in the proper bucket of adjacencies */ - next_bucket = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE); - next_bucket = Change_FaceEx(face_id,out_edge1,out_edge2,pListHead,temp2,TRUE); - - /* Create a new edgelist without the triangle that - was just outputted. - */ - Delete_From_ListEx(in_edge2,index,size); - /* Update the face data structure, by deleting the old - face and putting in the polygon minus the triangle - as the new face, here we will be decrementing the size - by one. - */ - New_Size_Face(face_id); - return; - } - - /* Else the edge is not consecutive, and it is sufficiently - far away, for us not to make a conclusion at this time. - So we can take off a triangle and recursively call this - function. - */ - else - { - if (!reversed) - { - vertex4 = AdjacentEx(in_edge2,in_edge1,index,size); - Output_TriEx(in_edge1,in_edge2,vertex4,output,-1,-1,where); - - /* Now delete the adjacencies by one for all the faces - that are adjacent to the triangle that we just outputted. - */ - Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id, - &dummy,&dummy,&dummy); - Delete_AdjEx(in_edge1,vertex4,&dummy,&dummy, - face_id,&dummy,&dummy,&dummy); - - /* Put the new face in the proper bucket of adjacencies */ - next_bucket = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE); - next_bucket = Change_FaceEx(face_id,in_edge1,vertex4,pListHead,temp2,FALSE); - - /* Create a new edgelist without the triangle that - was just outputted. - */ - Delete_From_ListEx(in_edge1,index,size); - /* Update the face data structure, by deleting the old - face and putting in the polygon minus the triangle - as the new face, here we will be decrementing the size - by one. - */ - New_Size_Face(face_id); - - /* Save the info for the new bucket, we will need it on - the next pass for the variables, pListHead and temp - */ - pListHead = array[next_bucket]; - pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) ); - if ( pfNode ) - pfNode->face_id = face_id; - temp2 = (P_ADJACENCIES) (SearchList(array[next_bucket], pfNode, - (int (*)(void *,void *)) (Compare))); - if (temp2 == NULL) - { - printf("There is an error finding the next polygon10 %d %d\n",next_bucket,face_id); - exit(0); - } - - P_Triangulate_Polygon(out_edge1,out_edge2,in_edge2, - vertex4,size-1,index,output,fp,!reversed, - face_id,next_id,pListHead,temp2,where); - } - else - { - vertex4 = AdjacentEx(in_edge1,in_edge2,index,size); - Output_TriEx(in_edge2,in_edge1,vertex4,output,-1,-1,where); - - /* Now delete the adjacencies by one for all the faces - that are adjacent to the triangle that we just outputted. - */ - Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id, - &dummy,&dummy,&dummy); - Delete_AdjEx(in_edge2,vertex4,&dummy,&dummy, - face_id,&dummy,&dummy,&dummy); - - /* Put the new face in the proper bucket of adjacencies */ - next_bucket = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE); - next_bucket = Change_FaceEx(face_id,in_edge2,vertex4,pListHead,temp2,FALSE); - - /* Create a new edgelist without the triangle that - was just outputted. - */ - Delete_From_ListEx(in_edge2,index,size); - - /* Update the face data structure, by deleting the old - face and putting in the polygon minus the triangle - as the new face, here we will be decrementing the size - by one. - */ - New_Size_Face(face_id); - - /* Save the info for the new bucket, we will need it on - the next pass for the variables, pListHead and temp - */ - pListHead = array[next_bucket]; - pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) ); - if ( pfNode ) - pfNode->face_id = face_id; - temp2 = (P_ADJACENCIES) (SearchList(array[next_bucket], pfNode, - (int (*)(void *,void *)) (Compare))); - if (temp2 == NULL) - { - printf("There is an error finding the next polygon11 %d %d\n",face_id,next_bucket); - exit(0); - } - - P_Triangulate_Polygon(out_edge1,out_edge2,vertex4, - in_edge1,size-1,index,output,fp,!reversed, - face_id,next_id,pListHead,temp2,where); - } - return; - } -} - -void P_Triangulate(int out_edge1,int out_edge2,int in_edge1, - int in_edge2,int size,int *index, - FILE *fp,FILE *output,int reversed,int face_id, - int *next_id,ListHead *pListHead, - P_ADJACENCIES temp,int where) -{ - - if (size == 4) - P_Triangulate_Quad(out_edge1,out_edge2,in_edge1,in_edge2,size, - index,fp,output,reversed,face_id,next_id,pListHead, temp,where); - else - P_Triangulate_Polygon(out_edge1,out_edge2,in_edge1,in_edge2,size, - index,fp,output,reversed,face_id,next_id,pListHead,temp,where); -} - - void Partial_Triangulate(int size,int *index, FILE *fp, - FILE *output,int next_face_id,int face_id, - int *next_id,ListHead *pListHead, - P_ADJACENCIES temp, int where) -{ - int id1,id2,id3; - int nedge1,nedge2; - int reversed; - - /* We have a polygon that has to be triangulated and we cannot - do it blindly, ie we will try to come out on the edge that - has the least number of adjacencies, But also we do not - want to triangulate the whole polygon now, so that means - we will output the least number of triangles that we can - and then update the data structures, with the polygon - that is left after we are done. - */ - Last_Edge(&id1,&id2,&id3,0); - - /* Find the edge that is adjacent to the new face , - also return whether the orientation is reversed in the - face of the input edge, which is id2 and id3. - */ - reversed = Get_EdgeEx(&nedge1,&nedge2,index,next_face_id,size,id2,id3); - - /* Input edge and output edge can be the same if there are more than - one polygon on an edge - */ - if ( ((nedge1 == id2) && (nedge2 == id3)) || - ((nedge1 == id3) && (nedge2 == id2)) ) - /* Set output edge arbitrarily but when come out of here the - next face will be on the old output edge (identical one) - */ - nedge2 = Return_Other(index,id2,id3); - - /* Do the triangulation */ - P_Triangulate(nedge1,nedge2,id2,id3,size,index,fp,output,reversed, - face_id,next_id,pListHead,temp,where); -} - - void Input_Edge(int face_id, int *index, int size, int in_edge1, int in_edge2, - FILE *fp, FILE *output,ListHead *pListHead, P_ADJACENCIES temp2, - int where) - { - /* The polygon had an input edge, specified by input1 and input2 */ - - int output1; - int vertex4, vertex5,dummy=60; - - output1 = Get_Output_Edge(face_id,size,index,in_edge1,in_edge2); - vertex5 = AdjacentEx(in_edge2,in_edge1,index,size); - vertex4 = AdjacentEx(in_edge1,in_edge2,index,size); - - if (vertex4 == output1) - { - Output_TriEx(in_edge2,in_edge1,output1,output,-1,-1,where); - /* Now delete the adjacencies by one for all the faces - that are adjacent to the triangle that we just outputted. - */ - Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id, - &dummy,&dummy,&dummy); - Delete_AdjEx(in_edge2,output1,&dummy,&dummy, - face_id,&dummy,&dummy,&dummy); - /* Put the new face in the proper bucket of adjacencies */ - Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE); - Change_FaceEx(face_id,in_edge2,output1,pListHead,temp2,FALSE); - - /* Create a new edgelist without the triangle that - was just outputted. - */ - Delete_From_ListEx(in_edge2,index,size); - - } - else if (vertex5 == output1) - { - Output_TriEx(in_edge1,in_edge2,vertex5,output,-1,-1,where); - /* Now delete the adjacencies by one for all the faces - that are adjacent to the triangle that we just outputted. - */ - Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id, - &dummy,&dummy,&dummy); - Delete_AdjEx(in_edge1,vertex5,&dummy,&dummy, - face_id,&dummy,&dummy,&dummy); - /* Put the new face in the proper bucket of adjacencies */ - Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE); - Change_FaceEx(face_id,in_edge1,vertex5,pListHead,temp2,FALSE); - - /* Create a new edgelist without the triangle that - was just outputted. - */ - Delete_From_ListEx(in_edge1,index,size); - } - - /* Update the face data structure, by deleting the old - face and putting in the polygon minus the triangle - as the new face, here we will be decrementing the size - by one. - */ - New_Size_Face(face_id); - return; - } - - void Inside_Polygon(int size,int *index,FILE *fp,FILE *output, - int next_face_id,int face_id,int *next_id, - ListHead *pListHead,P_ADJACENCIES temp, int where) - { - /* We know that we have a polygon that is greater than 4 sides, and - that it is better for us to go inside the polygon for the next - one, since inside will have less adjacencies than going outside. - So, we are not doing partial for a part of the polygon. - */ - int id1,id2,id3; - int new1,new2; - - Last_Edge(&id1,&id2,&id3,0); - - /* See if the input edge existed in the polygon, that will help us */ - if (Exist(face_id,id2,id3)) - Input_Edge(face_id,index,size,id2,id3,output,fp,pListHead,temp,where); - else - { - /* Make one of the input edges - We will choose it by trying to get an edge that has something - in common with the last triangle, or by getting the edge that - is adjacent to the least number of thigs, with preference given - to the first option - */ - - Get_Input_Edge(index,id1,id2,id3,&new1,&new2,size,face_id); - Input_Edge(face_id,index,size,new1,new2,output,fp,pListHead,temp,where); - } - } - - diff --git a/Tools/Stripe_w/partial.h b/Tools/Stripe_w/partial.h deleted file mode 100644 index 6a4e3a5b1..000000000 --- a/Tools/Stripe_w/partial.h +++ /dev/null @@ -1,20 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: partial.h ------------------------------------------------------------------------*/ - -void Partial_Triangulate(int size,int *index, FILE *fp, - FILE *output,int next_face_id,int face_id, - int *next_id,ListHead *pListHead, - P_ADJACENCIES temp, int where); -void Inside_Polygon(int size,int *index,FILE *fp,FILE *output, - int next_face_id,int face_id,int *next_id, - ListHead *pListHead,P_ADJACENCIES temp, int where); - diff --git a/Tools/Stripe_w/polverts.h b/Tools/Stripe_w/polverts.h deleted file mode 100644 index b3979eb4b..000000000 --- a/Tools/Stripe_w/polverts.h +++ /dev/null @@ -1,108 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: polverts.h ------------------------------------------------------------------------*/ - - -#ifndef _POLVERTS_H -#define _POLVERTS_H - - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include "queue.h" - -#ifdef HAVE_STDLIB_H -# include -#else -# include -#endif - - -typedef struct adjacencies -{ - Node ListNode; - int face_id; -} ADJACENCIES,*P_ADJACENCIES; - -typedef struct FVerts -{ - Node ListNode; - int *pPolygon; - int nPolSize; - int nId; -} F_VERTS, *PF_VERTS; - -/*Every time we need to use this, cast it ( ListInfo*)*/ - -typedef struct FEdges -{ - Node ListNode; - int edge[3]; -}F_EDGES,*PF_EDGES; - -typedef struct FFaces -{ - Node ListNode; - int *pPolygon; - int *pNorms; - int seen; - int seen2; - int seen3; - int nPolSize; - F_EDGES **VertandId; - int *marked; - int *walked; -} F_FACES,*PF_FACES; - - -typedef struct Strips -{ - Node ListNode; - int face_id; -} Strips,*P_STRIPS; - - - struct vert_added - { - int num; - int *normal; - }; - - -/* external functions */ -void Find_Adjacencies(int num_faces); -void Test_Adj_Struct(); -void Test_SGI_Struct(); -void Write_Edges(); -void Build_SGI_Table(int num_verts,int num_faces); -void Save_Walks(int numfaces); -void Find_Bands(int numfaces, FILE *output_file, int *swaps, int *bands, - int *cost, int *tri, int norms, int *vert_norms, int texture, - int *vert_texture); -void Save_Rest(int *numfaces); -void Assign_Walk(int lastvert, PF_FACES temp2, int front_walk,int y, - int back_walk); -void Save_Walks(int numfaces); - - -/* Globals */ -extern ListHead **PolVerts; -extern ListHead **PolFaces; -extern ListHead **PolEdges; -extern ListHead *array[60]; -extern int id_array[60]; -extern ListHead *strips[1]; -extern ListHead *all_strips[100000]; /* Assume max 100000 strips */ - - -#endif _POLVERTS_H diff --git a/Tools/Stripe_w/polyvertsex.h b/Tools/Stripe_w/polyvertsex.h deleted file mode 100644 index 4c541f7bc..000000000 --- a/Tools/Stripe_w/polyvertsex.h +++ /dev/null @@ -1,42 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: polvertsex.h ------------------------------------------------------------------------*/ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#ifdef HAVE_STDLIB_H -# include -#else -# include -#endif - -#include "queue.h" - -/* external functions */ -void Start_Vert_Struct(); -void Start_Face_StructEx(); -void Start_Edge_StructEx(); -void AddNewNode(); -void AddNewFaceEx(); -void Find_AdjacenciesEx(); -void Test_Adj_Struct(); -void Test_SGI_Struct(); -void Write_Edges(); -void End_Verts_Struct(); -void End_Face_StructEx(); -void End_Edge_StructEx(); -void Build_SGI_TableEx(); -void Add_AdjEdgeEx(); - - - diff --git a/Tools/Stripe_w/queue.c b/Tools/Stripe_w/queue.c deleted file mode 100644 index 966f20379..000000000 --- a/Tools/Stripe_w/queue.c +++ /dev/null @@ -1,226 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: queue.c - This file contains the routines used in the data structures lists, which - are queues. -*/ -/*---------------------------------------------------------------------*/ - - #include "queue.h" - - - -/*---------------------------------------------------------------------------- - * InitList: - */ -BOOL InitList (PLISTHEAD LHead) - -{ - if (LHead == NULL) return(FALSE); - - LHead->LHeaders[LISTHEAD] = LHead->LHeaders[LISTTAIL] = NULL; - LHead->NumList = 0; - return(TRUE); -} - -/*---------------------------------------------------------------------------- - * AddHead: - */ -BOOL AddHead(PLISTHEAD LHead, PLISTINFO LInfo) -{ - if (LHead == NULL || LInfo == NULL) - return(FALSE); - if (EMPTYLIST(LHead)) - LHead->LHeaders[LISTTAIL] = LInfo; - else LHead->LHeaders[LISTHEAD]->ListNode.Previous = (void *) LInfo; - - LInfo->ListNode.Next = (void *) LHead->LHeaders[LISTHEAD]; - LHead->LHeaders[LISTHEAD] = LInfo; - LInfo->ListNode.Previous = NULL; - LHead->NumList++; - return(TRUE); -} - -/*---------------------------------------------------------------------------- - * AddTail - */ -BOOL AddTail(PLISTHEAD LHead, PLISTINFO LInfo) -{ - if (LHead == NULL || LInfo == NULL) - return(FALSE); - if (EMPTYLIST(LHead)) - LHead->LHeaders[LISTHEAD] = LInfo; - else LHead->LHeaders[LISTTAIL]->ListNode.Next = (void *) LInfo; - - LInfo->ListNode.Previous = (void *) LHead->LHeaders[LISTTAIL]; - LHead->LHeaders[LISTTAIL] = LInfo; - LInfo->ListNode.Next = NULL; - LHead->NumList++; - return(TRUE); -} - - -BOOL InsertNode( PLISTHEAD LHead, int nPos, PLISTINFO LInfo ) -{ -PLISTINFO LAddNode; - - if ( LHead == NULL || LInfo == NULL || nPos > NumOnList( LHead ) ) - return( FALSE ); - - if ( nPos == 0 ) - AddHead( LHead, LInfo ); - else if ( nPos == NumOnList( LHead ) ) - AddTail( LHead, LInfo ); - else - { - if ( (LAddNode = PeekList( LHead, LISTHEAD, nPos - 1 )) == NULL ) - return( FALSE ); - - ((PLISTINFO)LAddNode->ListNode.Next)->ListNode.Previous = LInfo; - LInfo->ListNode.Next = LAddNode->ListNode.Next; - LInfo->ListNode.Previous = LAddNode; - LAddNode->ListNode.Next = LInfo; - - LHead->NumList++; - } - - return( TRUE ); -} - - - - -/*---------------------------------------------------------------------------- - * RemHead: - */ -PLISTINFO RemHead(PLISTHEAD LHead) -{ - PLISTINFO t, t1; - - if ( LHead == NULL || EMPTYLIST(LHead) ) - return(NULL); - - t = LHead->LHeaders[LISTHEAD]; - LHead->LHeaders[LISTHEAD] = (PLISTINFO) t->ListNode.Next; - - if (LHead->LHeaders[LISTHEAD] != NULL) - { - t1 = (PLISTINFO) t->ListNode.Next; - t1->ListNode.Previous = NULL; - } - else - LHead->LHeaders[LISTTAIL] = NULL; - - LHead->NumList--; - - return(t); -} - -/*---------------------------------------------------------------------------- - * RemTail: - */ -PLISTINFO RemTail(PLISTHEAD LHead) -{ - PLISTINFO t, t1; - - if ( LHead == NULL || EMPTYLIST(LHead) ) - return(NULL); - - t = LHead->LHeaders[LISTTAIL]; - LHead->LHeaders[LISTTAIL] = (PLISTINFO) t->ListNode.Previous; - if (LHead->LHeaders[LISTTAIL] != NULL) - { - t1 = (PLISTINFO) t->ListNode.Previous; - t1->ListNode.Next = NULL; - } - else - LHead->LHeaders[LISTHEAD] = NULL; - - LHead->NumList--; - return(t); -} - -/*---------------------------------------------------------------------------- - * PeekList: - */ -PLISTINFO PeekList(PLISTHEAD LHead, int wch, int index ) -{ - PLISTINFO t; - - if (LHead == NULL) - return(NULL); - if ( (t = LHead->LHeaders[wch]) == NULL ) - return(NULL); - - for (; t != NULL && index > 0; index-- ) - t = (wch == LISTHEAD) ? (PLISTINFO) t->ListNode.Next : - (PLISTINFO) t->ListNode.Previous; - return(t); -} - - -/*---------------------------------------------------------------------------- - * RemoveList: - */ -PLISTINFO RemoveList( PLISTHEAD LHead, PLISTINFO LInfo ) -{ - PLISTINFO t, t1; - - t = LInfo; - if (LHead == NULL) - return(NULL); - if (LHead->LHeaders[LISTHEAD] == t) - t = (PLISTINFO) RemHead(LHead); - else if (LHead->LHeaders[LISTTAIL] == t) - t = (PLISTINFO) RemTail(LHead); - else - { - t1 = (PLISTINFO) t->ListNode.Previous; - t1->ListNode.Next = t->ListNode.Next; - t1 = (PLISTINFO) t->ListNode.Next; - t1->ListNode.Previous = t->ListNode.Previous; - LHead->NumList--; - } - - return(t); -} - -/*---------------------------------------------------------------------------- - * SearchList: - * Try to find a specific node in the queue whose key matches with - * searching key. Return the pointer to that node if found, return NULL - * otherwise - * - * Input: - * lpHashTbl => a far pointer to the hash table - * lpKey => a far poniter to searching key - * CompareCallBack => comparision function - * - * Output: a far pointer to the node to be found - * - */ -PLISTINFO SearchList( - PLISTHEAD lpListHead, - PVOID lpSKey, - int (* CompareCallBack) ( PVOID, PVOID ) ) -{ -PLISTINFO lpListInfo; - - lpListInfo = PeekList( lpListHead, LISTHEAD, 0); - while ( lpListInfo != NULL ) - { - if ( CompareCallBack( lpListInfo, lpSKey ) ) - break; - lpListInfo = GetNextNode( lpListInfo ); - } - - return( lpListInfo ); -} - diff --git a/Tools/Stripe_w/queue.h b/Tools/Stripe_w/queue.h deleted file mode 100644 index 0bf926e0f..000000000 --- a/Tools/Stripe_w/queue.h +++ /dev/null @@ -1,283 +0,0 @@ - -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE:queue.h ------------------------------------------------------------------------*/ - -#ifndef QUEUE_INCLUDED -#define QUEUE_INCLUDED - -/* %%s Node */ -/***************************************************************** - This structure is used to store the List linkage information of a -ListInfo structure. It contains all the necessary information for the -List functions to function properly. This structure must be the first -one defined in any block of memory to be linked with the List functions. -for an example of the used of The Node structure look in the files -ipd2dms.c and ipd2man.h -******************************************************************/ -#include -#define FALSE 0 -#define TRUE 1 -typedef struct -{ - void *Next; - void *Previous; -} - Node, * PNODE; - -/***************************************************************** - Next : is a pointer to the next structure in this List. - Previous : is a pointer to the previous structure in this List. - priority : this is the priority of this structure in the List. The - highest priority is 0. This field is only used by the - functions EnQue and DeQue. -******************************************************************/ -/* %%e */ - - -/* %%s ListInfo */ - -/***************************************************************** - This is the general means of linking application defined information into -Lists and queues. All structures must begin with the Node Structure. All -other data in the structure is user definable. -******************************************************************/ - -typedef struct List -{ - Node ListNode; /* link to the next Listinfo Structure */ - /* user definable data */ -} ListInfo, *PLISTINFO; - -/***************************************************************** - ListNode : this is the required node structure for the List - mainpulation functions. This must be the first - element of a user definable structure. - - In order for an application to use the List routines, it must define -a structure with all the needed information. The first element in the -user definable structure must be a Node structure. The Node structure -contains all the necessary information for the List routines to do their -magic. For an example of a user defined List structure see the file -ipd2i.h. The User definable structure can be passed to any List function -that excepts a pointer to a ListInfo structure. - -example: - -typedef mstruct -{ - Node ListNode; - int a,b,c,d,e,f,g; -} - mystruct; - - the user definable portion of the above structure is represented by -the integers a,b,c,d,e,f,g. When passing this structure to a List -function a cast of (ListInfo *) must be made to satisify the "C" complier. -******************************************************************/ -/* %%e */ - - -/* %%s ListHead */ -/***************************************************************** - ListHead is used as a header to a List. LHeaders[0] points to the -head of the List. LHeaders[1] points the tail of the list. When -accessing these variables use the defines LISTHEAD, LISTTAIL. -******************************************************************/ - -typedef struct LHead -{ - PLISTINFO LHeaders[2]; - int NumList; -} -ListHead, *PLISTHEAD; - -/***************************************************************** - LHeaders : this is an array of two pointers to ListInfo structures. - This information is used to point to the head and tail of - a list. - NumList : this integer hold the number of structures linked into this - list. - -ListHead #define: - - LISTHEAD : when Peeking down a list this specifies you should - start at the Head of the list and search downward. - - LISTTAIL : when Peeking down a list this specifies you should - start at the tail of the list and search foward. - ******************************************************************/ - -#define LISTHEAD 0 - -#define LISTTAIL 1 -/* %%e */ - -typedef int BOOL; -typedef void * PVOID; - -#define PEEKFROMHEAD( lh, ind ) ( PeekList( (lh), LISTHEAD, (ind) ) ) -#define PEEKFROMTAIL( lh, ind ) ( PeekList( (lh), LISTTAIL, (ind) ) ) -#define EMPTYLIST( lh ) ( ( (lh)->LHeaders[LISTHEAD] == NULL ) ) - -/* General utility routines */ -/* %%s QueRoutines */ -BOOL InitList ( PLISTHEAD ); - -/***************************************************************** - InitList : Initialize a new list structure for use with the List - routines - - INPUTS : LHead : a pointer to a ListHead structure. - OUTPUT : a boolean value TRUE if no errors occured FALSE - otherwise -******************************************************************/ - - -PLISTINFO PeekList ( PLISTHEAD, int, int ); - -/***************************************************************** - PeekList : This funciton peeks down a list for the N'th element - from the HEAD or TAIL of the list - - INPUTS : LHead : a pointer to a List head structure. - from : can either search from the HEAD or TAIL - of the list - where : how many nodes from the begining should the - List routines look. - OUTPUT : a pointer to a ListInfo structure identified by - from/where or NULL if an error occurred. -******************************************************************/ - - -PLISTINFO RemoveList( PLISTHEAD LHead, PLISTINFO LInfo ); - - -/***************************************************************** - RemoveList: Remove a ListInfo structure from a List. - - INPUTS : LHead : a pointer to a ListHead structure. - LInfo : a pointer to the ListInfo structure to remove - from the list. - OUTPUT : a pointer to the ListInfo structure that was removed or - NULL if an error occurred. -******************************************************************/ - -BOOL InsertNode( PLISTHEAD LHead, int nPos, PLISTINFO LInfo ); - -/***************************************************************** - InsertNode: add a node to a list after a given node - - INPUTS : LHead : a pointer to a ListHead structure. - nPos : the position to insert the node into - LInfo : a pointer to the new node to add to the list. - OUTPUT: a boolean value TRUE if all goes well false otherwise -*****************************************************************/ - -BOOL AddHead ( PLISTHEAD, PLISTINFO ); - -/***************************************************************** - AddHead : add a ListInfo structure to the HEAD of a list. - - INPUTS : LHead : a pointer to a ListHead structure of the list - to add to. - LInfo : a pointer to the ListInfo structure to add to - the list. - OUTPUT : A boolean value TRUE if no errors occurred FALSE - otherwise. -******************************************************************/ - - -BOOL AddTail ( PLISTHEAD, PLISTINFO ); - -/***************************************************************** - AddTail : Add a ListInfo structure to the TAIL of a list. - - INPUTS : LHead : a pointer to a ListHead structure of the List - to add to. - LInfo : a pointer to the ListInfo structure to add to - the List. - OUTPUT : a boolean value TRUE if no errors occurred FALSE - otherwise. -******************************************************************/ - - -PLISTINFO RemTail ( PLISTHEAD ); - -/***************************************************************** - RemTail : Remove a ListInfo structure from the TAIL of a List. - - INPUTS : LHead : a pointer to a ListHead structure of the List - to remove from. - OUTPUT : a pointer to the ListInfo structure that was removed - or NULL if an error occurred. -******************************************************************/ - - -PLISTINFO RemHead ( PLISTHEAD ); - -/***************************************************************** - RemHead : Remove a ListInfo structure from the Head of a List. - - INPUTS : LHead : a pointer to a ListHead structure of the List - to remove from. - OUTPUT : a pointer to the ListInfo structure that was removed or - NULL if an error occurred. -******************************************************************/ - -PLISTINFO SearchList( - PLISTHEAD lpListHead, - PVOID lpSKey, - int ( * CompareCallBack) ( PVOID, PVOID ) ); - -/***************************************************************** - SearchList: - Try to find a specific node in the queue whose key matches with - searching key. Return the pointer to that node if found, return NULL - otherwise - - Input: - lpHashTbl => a far pointer to the hash table - lpKey => a far poniter to searching key - CompareCallBack => comparision function - - Output: a far pointer to the node to be found - - ******************************************************************/ - -#define NumOnList(lh) ( ((lh)->NumList) ) - -/***************************************************************** - NumOnList: Returns the number of Nodes linked to a ListHead - structure. This number is maintained by the List - routines. -******************************************************************/ - -#define GetNextNode(pli) ( ((pli)->ListNode.Next) ) - -/******************************************************** - GetNextNode: This macro returns the Next Structure in this list. - This macro will return NULL if no more structures are - in the List. -*********************************************************/ - -#define GetPrevNode(pli) ( ((pli)->ListNode.Previous) ) - -/******************************************************** - GetPrevNode: This macro returns the Previous Structure in this list. - This macro will reutrn NULL if no more structures are - in the List. -********************************************************/ -/* %%e */ - -#endif - - diff --git a/Tools/Stripe_w/sgi_triang.c b/Tools/Stripe_w/sgi_triang.c deleted file mode 100644 index 1a130906e..000000000 --- a/Tools/Stripe_w/sgi_triang.c +++ /dev/null @@ -1,628 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: sgi_triang.c - File contains the routines that do the whole triangulation - of polygons. -*/ -/*---------------------------------------------------------------------*/ - -#include -#include -#include -#include "global.h" -#include "output.h" -#include "polverts.h" -#include "sturcts.h" -#include "common.h" -#include "util.h" -#include "init.h" - -int Adjacent(int id2,int id1, int *list, int size) -{ - /* Return the vertex that is adjacent to id1, - but is not id2, in the list of integers. - */ - - register int x=0; - - while (x < size) - { - if (*(list+x) == id1) - { - if ((x != (size -1)) && (x != 0)) - { - if ( *(list+x+1) != id2) - return *(list+x+1); - else - return *(list+x-1); - } - else if (x == (size -1)) - { - if (*(list) != id2) - return *(list); - else - return *(list+x-1); - } - else - { - if (*(list+size-1) != id2) - return *(list+size-1); - else - return *(list+x+1); - } - } - x++; - } - /* if there are degeneracies */ - return id1; -} - - -void Rearrange_Index(int *index, int size) -{ - /* If we are in the middle of a strip we must find the - edge to start on, which is the last edge that we had - transmitted. - */ - int x,f,y,e1,e2,e3; - register int increment = 1; - int *temp; - - /* Find where the input edge is in the input list */ - Last_Edge(&e1,&e2,&e3,0); - for (y = 0; y < size; y++) - { - if (*(index+y) == e2) - { - if ((y != (size - 1)) && (*(index+y+1) == e3)) - break; - else if ((y == (size - 1)) && (*(index) == e3)) - break; - else if ((y != 0) && (*(index+y-1) == e3)) - { - increment = -1; - break; - } - else if ((y==0) && (*(index+size-1) == e3)) - { - increment = -1; - break; - } - } - if (*(index+y) == e3) - { - if ((y != (size - 1)) && (*(index+y+1) == e2)) - break; - else if ((y == (size - 1)) && (*(index) == e2)) - break; - else if ((y != 0) && (*(index+y-1) == e2)) - { - increment = -1; - break; - } - else if ((y==0) && (*(index+size-1) == e2)) - { - increment = -1; - break; - } - } - /* Edge is not here, we are at the beginning */ - if ((y == (size-1)) && (increment != -1)) - return; - } - - /* Now put the list into a new list, starting with the - input edge. Increment tells us whether we have to go - forward or backward. - */ - /* Was in good position already */ - if ((y == 0) && (increment == 1)) - return; - - temp = (int *) malloc(sizeof(int) * size); - memcpy(temp,index,sizeof(int)*size); - - if (increment == 1) - { - x=0; - for (f = y ; f< size; f++) - { - *(index+x) = *(temp+f); - x++; - } - /* Finish the rest of the list */ - for(f = 0; f < y ; f++) - { - *(index+x) = *(temp+f); - x++; - } - } - else - { - x=0; - for (f = y ; f >= 0; f--) - { - *(index+x) = *(temp+f); - x++; - } - /* Finish the rest of the list */ - for(f = (size - 1); f > y ; f--) - { - *(index+x) = *(temp+f); - x++; - } - } -} - -void Delete_From_List(int id,int *list, int *size) -{ - /* Delete the occurence of id in the list. - (list has size size) - */ - - int *temp; - register int x,y=0; - - temp = (int *) malloc(sizeof(int) * (*size)); - for (x=0; x<(*size); x++) - { - if (*(list+x) != id) - { - *(temp+y) = *(list+x); - y++; - } - } - *(temp+y) = -1; - *size = *size - (*size - y - 1); - memcpy(list,temp,sizeof(int)*(*size)); -} - - -void Build_SGI_Table(int num_verts,int num_faces) -{ - /* Build a table that has the polygons sorted by the - number of adjacent polygons. - */ - int x,y,size,tally=0; - ListHead *pListHead; - PF_FACES temp = NULL; - - /* For each face....*/ - for (x=0;x < num_faces;x++) - { - pListHead = PolFaces[x]; - temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); - /* Check each edge of the face and tally the number of adjacent - polygons to this face. - */ - if ( temp != NULL ) - { - /* Size of the polygon */ - size = temp->nPolSize; - if (size != 1) - { - for (y = 0; y< size; y++) - { - if (y != (size-1)) - tally += Num_Adj(*(temp->pPolygon+y),*(temp->pPolygon+y+1)); - else - tally += Num_Adj(*(temp->pPolygon),*(temp->pPolygon+(size-1))); - } - - /* Tally is the number of polygons that is adjacent to - the current polygon. - */ - /* Now put the face in the proper bucket depending on tally. */ - Add_Sgi_Adj(tally,x); - temp = NULL; - tally=0; - } - } - } -} - - -void Triangulate_Quad(int out_edge1,int out_edge2,int in_edge1, - int in_edge2,int size,int *index, - FILE *output,int reversed,int face_id, - int where,int color1,int color2,int color3) -{ - int vertex4,vertex5; - - /* This routine will nonblindly triangulate a quad, meaning - that there is a definite input and a definite output - edge that we must adhere to. Reversed will tell the orientation - of the input edge. (Reversed is -1 is we do not have an input - edge, in other words we are at the beginning of a strip.) - Out_edge* is the output edge, and in_edge* is the input edge. - Index are the edges of the polygon - and size is the size of the polygon. Begin is whether we are - at the start of a new strip. - */ - - /* If we do not have an input edge, then we can make our input - edge whatever we like, therefore it will be easier to come - out on the output edge. - */ - if (reversed == -1) - { - vertex4 = Adjacent(out_edge1,out_edge2,index,size); - vertex5 = Get_Other_Vertex(vertex4,out_edge1,out_edge2,index); - Output_Tri(vertex5,vertex4,out_edge1,output,color1,color2,color3,where); - Output_Tri(vertex4,out_edge1,out_edge2,output,color1,color2,color3,where); - return; - } - - /* These are the 5 cases that we can have for the output edge */ - - /* Are they consecutive so that we form a triangle to - peel off, but cannot use the whole quad? - */ - - if (in_edge2 == out_edge1) - { - /* Output the triangle that comes out the correct - edge last. First output the triangle that comes out - the wrong edge. - */ - vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge2,index); - Output_Tri(in_edge1,in_edge2,vertex4,output,color1,color2,color3,where); - Output_Tri(vertex4,in_edge2,out_edge2,output,color1,color2,color3,where); - return; - } - /* The next case is where it is impossible to come out the - edge that we want. So we will have to start a new strip to - come out on that edge. We will output the one triangle - that we can, and then start the new strip with the triangle - that comes out on the edge that we want to come out on. - */ - else if (in_edge1 == out_edge1) - { - /* We want to output the first triangle (whose output - edge is not the one that we want. - We have to find the vertex that we need, which is - the other vertex which we do not have. - */ - vertex4 = Get_Other_Vertex(in_edge2,in_edge1,out_edge2,index); - Output_Tri(in_edge2,in_edge1,vertex4,output,color1,color2,color3,where); - Output_Tri(vertex4,in_edge1,out_edge2,output,color1,color2,color3,where); - return; - } - - /* Consecutive cases again, but with the output edge reversed */ - else if (in_edge1 == out_edge2) - { - vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge1,index); - Output_Tri(in_edge2,in_edge1,vertex4,output,color1,color2,color3,where); - Output_Tri(vertex4,in_edge1,out_edge1,output,color1,color2,color3,where); - return; - } - else if (in_edge2 == out_edge2) - { - vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge1,index); - Output_Tri(in_edge1,in_edge2,vertex4,output,color1,color2,color3,where); - Output_Tri(vertex4,in_edge2,out_edge1,output,color1,color2,color3,where); - return; - } - - /* The final case is where we want to come out the opposite - edge. - */ - else - { - if( ((!reversed) && (out_edge1 == (Adjacent(in_edge1,in_edge2,index,size)))) || - ((reversed) && (out_edge2 == (Adjacent(in_edge2,in_edge1,index,size))))) - { - /* We need to know the orientation of the input - edge, so we know which way to put the diagonal. - And also the output edge, so that we triangulate - correctly. - */ - Output_Tri(in_edge1,in_edge2,out_edge2,output,color1,color2,color3,where); - Output_Tri(in_edge2,out_edge2,out_edge1,output,color1,color2,color3,where); - } - else - { - /* Input and output orientation was reversed, so diagonal will - be reversed from above. - */ - Output_Tri(in_edge1,in_edge2,out_edge1,output,color1,color2,color3,where); - Output_Tri(in_edge2,out_edge1,out_edge2,output,color1,color2,color3,where); - } - return; - } -} - -void Triangulate_Polygon(int out_edge1, int out_edge2, int in_edge1, - int in_edge2, int size, int *index, - FILE *output, int reversed, int face_id, - int where, int color1, int color2, int color3) -{ - /* We have a polygon that we need to nonblindly triangulate. - We will recursively try to triangulate it, until we are left - with a polygon of size 4, which can use the quad routine - from above. We will be taking off a triangle at a time - and outputting it. We will have 3 cases similar to the - cases for the quad above. The inputs to this routine - are the same as for the quad routine. - */ - - int vertex4; - int *temp; - - /* Since we are calling this recursively, we have to check whether - we are down to the case of the quad. - */ - - if (size == 4) - { - Triangulate_Quad(out_edge1,out_edge2,in_edge1,in_edge2,size, - index,output,reversed,face_id,where,color1,color2,color3); - return; - } - - - - /* We do not have a specified input edge, and therefore we - can make it anything we like, as long as we still come out - the output edge that we want. - */ - if (reversed == -1) - { - /* Get the vertex for the last triangle, which is - the one coming out the output edge, before we do - any deletions to the list. We will be doing this - bottom up. - */ - vertex4 = Adjacent(out_edge1,out_edge2,index,size); - temp = (int *) malloc(sizeof(int) * size); - memcpy(temp,index,sizeof(int)*size); - Delete_From_List(out_edge2,index,&size); - Triangulate_Polygon(out_edge1,vertex4,in_edge2, - vertex4,size-1,index,output,reversed,face_id,where,color1,color2,color3); - memcpy(index,temp,sizeof(int)*size); - /* Lastly do the triangle that comes out the output - edge. - */ - Output_Tri(vertex4,out_edge1,out_edge2,output,color1,color2,color3,where); - return; - } - - /* These are the 5 cases that we can have for the output edge */ - - /* Are they consecutive so that we form a triangle to - peel off that comes out the correct output edge, - but we cannot use the whole polygon? - */ - if (in_edge2 == out_edge1) - { - /* Output the triangle that comes out the correct - edge last. First recursively do the rest of the - polygon. - */ - /* Do the rest of the polygon without the triangle. - We will be doing a fan triangulation. - */ - /* Get the vertex adjacent to in_edge1, but is not - in_edge2. - */ - vertex4 = Adjacent(in_edge2,in_edge1,index,size); - Output_Tri(in_edge1,in_edge2,vertex4,output,color1,color2,color3,where); - /* Create a new edgelist without the triangle that - was just outputted. - */ - temp = (int *) malloc(sizeof(int) * size); - memcpy(temp,index,sizeof(int)*size); - Delete_From_List(in_edge1,index,&size); - Triangulate_Polygon(out_edge1,out_edge2,in_edge2, - vertex4,size-1,index,output,!reversed,face_id,where,color1,color2,color3); - memcpy(index,temp,sizeof(int)*size); - return; - } - - /* Next case is where it is again consecutive, but the triangle - formed by the consecutive edges do not come out of the - correct output edge. For this case, we can not do much to - keep it sequential. Try and do the fan. - */ - else if (in_edge1 == out_edge1) - { - /* Get vertex adjacent to in_edge2, but is not in_edge1 */ - vertex4 = Adjacent(in_edge1,in_edge2,index,size); - Output_Tri(in_edge1,in_edge2,vertex4,output,color1,color2,color3,where); - /* Since that triangle goes out of the polygon (the - output edge of it), we can make our new input edge - anything we like, so we will try to make it good for - the strip. (This will be like starting a new strip, - all so that we can go out the correct output edge.) - */ - temp = (int *) malloc(sizeof(int) * size); - memcpy(temp,index,sizeof(int)*size); - Delete_From_List(in_edge2,index,&size); - Triangulate_Polygon(out_edge1,out_edge2,in_edge1, - vertex4,size-1,index,output,reversed,face_id,where,color1,color2,color3); - memcpy(index,temp,sizeof(int)*size); - return; - } - /* Consecutive cases again, but with the output edge reversed */ - else if (in_edge1 == out_edge2) - { - /* Get vertex adjacent to in_edge2, but is not in_edge1 */ - vertex4 = Adjacent(in_edge1,in_edge2,index,size); - Output_Tri(in_edge2,in_edge1,vertex4,output,color1,color2,color3,where); - temp = (int *) malloc(sizeof(int) * size); - memcpy(temp,index,sizeof(int)*size); - Delete_From_List(in_edge2,index,&size); - Triangulate_Polygon(out_edge1,out_edge2,in_edge1, - vertex4,size-1,index,output,reversed,face_id,where,color1,color2,color3); - memcpy(index,temp,sizeof(int)*size); - return; - } - else if (in_edge2 == out_edge2) - { - /* Get vertex adjacent to in_edge2, but is not in_edge1 */ - vertex4 = Adjacent(in_edge2,in_edge1,index,size); - Output_Tri(in_edge1,in_edge2,vertex4,output,color1,color2,color3,where); - temp = (int *) malloc(sizeof(int) * size); - memcpy(temp,index,sizeof(int)*size); - Delete_From_List(in_edge1,index,&size); - Triangulate_Polygon(out_edge1,out_edge2,vertex4, - in_edge2,size-1,index,output,reversed,face_id,where,color1,color2,color3); - memcpy(index,temp,sizeof(int)*size); - return; - } - - /* Else the edge is not consecutive, and it is sufficiently - far away, for us not to make a conclusion at this time. - So we can take off a triangle and recursively call this - function. - */ - else - { - vertex4 = Adjacent(in_edge2,in_edge1,index,size); - Output_Tri(in_edge1,in_edge2,vertex4,output,color1,color2,color3,where); - temp = (int *) malloc(sizeof(int) * size); - memcpy(temp,index,sizeof(int)*size); - Delete_From_List(in_edge1,index,&size); - Triangulate_Polygon(out_edge1,out_edge2,in_edge2, - vertex4,size-1,index,output,!reversed,face_id,where,color1,color2,color3); - memcpy(index,temp,sizeof(int)*size); - return; - } -} - -void Triangulate(int out_edge1,int out_edge2,int in_edge1, - int in_edge2,int size,int *index, - FILE *output,int reversed,int face_id, int where, - int color1, int color2,int color3) -{ - /* We have the info we need to triangulate a polygon */ - - if (size == 4) - Triangulate_Quad(out_edge1,out_edge2,in_edge1,in_edge2,size, - index,output,reversed,face_id,where,color1,color2,color3); - else - Triangulate_Polygon(out_edge1,out_edge2,in_edge1,in_edge2,size, - index,output,reversed,face_id,where,color1,color2,color3); -} - -void Non_Blind_Triangulate(int size,int *index, - FILE *output,int next_face_id,int face_id,int where, - int color1,int color2,int color3) -{ - int id1,id2,id3; - int nedge1,nedge2; - int reversed; - /* We have a polygon that has to be triangulated and we cannot - do it blindly, ie we will try to come out on the edge that - has the least number of adjacencies - */ - - Last_Edge(&id1,&id2,&id3,0); - /* Find the edge that is adjacent to the new face , - also return whether the orientation is reversed in the - face of the input edge, which is id2 and id3. - */ - if (next_face_id == -1) - { - printf("The face is -1 and the size is %d\n",size); - exit(0); - } - - reversed = Get_Edge(&nedge1,&nedge2,index,next_face_id,size,id2,id3); - /* Do the triangulation */ - - /* If reversed is -1, the input edge is not in the polygon, therefore we can have the - input edge to be anything we like, since we are at the beginning - of a strip - */ - Triangulate(nedge1,nedge2,id2,id3,size,index,output,reversed, - face_id, where,color1,color2,color3); -} - - - -void Blind_Triangulate(int size, int *index, FILE *output, - BOOL begin, int where ,int color1,int color2, - int color3) -{ - /* save sides in temp array, we need it so we know - about swaps. - */ - int mode, decreasing,increasing,e1,e2,e3; - - /* Rearrange the index list so that the input edge is first - */ - if (!begin) - Rearrange_Index(index,size); - - /* We are given a polygon of more than 3 sides - and want to triangulate it. We will output the - triangles to the output file. - */ - - /* Find where the input edge is in the input list */ - Last_Edge(&e1,&e2,&e3,0); - if (( (!begin) && (*(index) == e2) ) || (begin)) - { - Output_Tri(*(index+0),*(index+1),*(index+size-1),output,color1,color2,color3,where); - /* If we have a quad, (chances are yes), then we know that - we can just add one diagonal and be done. (divide the - quad into 2 triangles. - */ - if (size == 4) - { - Output_Tri(*(index+1),*(index+size-1),*(index+2),output,color1,color2,color3,where); - return; - } - increasing = 1; - mode = 1; - - } - else if (!begin) - { - Output_Tri(*(index+1),*(index+0),*(index+size-1),output,color1,color2,color3,where); - if (size == 4) - { - Output_Tri(*(index+0),*(index+size-1),*(index+2),output,color1,color2,color3,where); - return; - } - Output_Tri(*(index+0),*(index+size-1),*(index+2),output,color1,color2,color3,where); - increasing = 2; - mode = 0; - } - if (size != 4) - { - /* We do not have a quad, we have something bigger. */ - decreasing = size - 1; - do - { - /* Will be alternating diagonals, so we will be increasing - and decreasing around the polygon. - */ - if (mode) - { - Output_Tri(*(index+increasing),*(index+decreasing),*(index+increasing+1),output,color1,color2,color3,where); - increasing++; - } - else - { - Output_Tri(*(index+decreasing),*(index+increasing),*(index+decreasing-1),output,color1,color2,color3,where); - decreasing--; - } - mode = !mode; - } while ((decreasing - increasing) >= 2); - - } -} - - - - diff --git a/Tools/Stripe_w/sgi_triangex.c b/Tools/Stripe_w/sgi_triangex.c deleted file mode 100644 index 9f153a1e8..000000000 --- a/Tools/Stripe_w/sgi_triangex.c +++ /dev/null @@ -1,582 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: sgi_triangex.c - This file contains routines that are used for various functions in - the local algorithm. -*/ -/*---------------------------------------------------------------------*/ - -#include -#include -#include -#include "global.h" -#include "outputex.h" -#include "polverts.h" -#include "sturctsex.h" -#include "common.h" -#include "util.h" - - -int AdjacentEx(int id2,int id1, int *list, int size) -{ - /* Return the vertex that is adjacent to id1, - but is not id2, in the list of integers. - */ - - register int x=0; - - while (x < size) - { - if (*(list+x) == id1) - { - if ((x != (size -1)) && (x != 0)) - { - if ( *(list+x+1) != id2) - return *(list+x+1); - else - return *(list+x-1); - } - else if (x == (size -1)) - { - if (*(list) != id2) - return *(list); - else - return *(list+x-1); - } - else - { - if (*(list+size-1) != id2) - return *(list+size-1); - else - return *(list+x+1); - } - } - x++; - } - printf("Error in the list\n"); - exit(0); -} - - -void Delete_From_ListEx(int id,int *list, int size) -{ - /* Delete the occurence of id in the list. - (list has size size) - */ - - int *temp; - register int x,y=0; - - temp = (int *) malloc(sizeof(int) * size); - for (x=0; x= 0; f--) - { - *(index+x) = *(temp+f); - x++; - } - /* Finish the rest of the list */ - for(f = (size - 1); f > y ; f--) - { - *(index+x) = *(temp+f); - x++; - } - } -} - -void Blind_TriangulateEx(int size, int *index, FILE *fp, - FILE *output, BOOL begin, int where ) -{ - /* save sides in temp array, we need it so we know - about swaps. - */ - int mode, decreasing,increasing,e1,e2,e3; - - /* Rearrange the index list so that the input edge is first - */ - if (!begin) - Rearrange_IndexEx(index,size); - - /* We are given a polygon of more than 3 sides - and want to triangulate it. We will output the - triangles to the output file. - */ - - /* Find where the input edge is in the input list */ - Last_Edge(&e1,&e2,&e3,0); - if (( (!begin) && (*(index) == e2) ) || (begin)) - { - Output_TriEx(*(index+0),*(index+1),*(index+size-1),fp,-1,-1,where); - /* If we have a quad, (chances are yes), then we know that - we can just add one diagonal and be done. (divide the - quad into 2 triangles. - */ - if (size == 4) - { - Output_TriEx(*(index+1),*(index+size-1),*(index+2),fp,-1,-1,where); - return; - } - increasing = 1; - mode = 1; - - } - else if (!begin) - { - Output_TriEx(*(index+1),*(index+0),*(index+size-1),fp,-1,-1,where); - if (size == 4) - { - Output_TriEx(*(index+0),*(index+size-1),*(index+2),fp,-1,-1,where); - return; - } - Output_TriEx(*(index+0),*(index+size-1),*(index+2),fp,-1,-1,where); - increasing = 2; - mode = 0; - } - if (size != 4) - { - /* We do not have a quad, we have something bigger. */ - decreasing = size - 1; - - do - { - /* Will be alternating diagonals, so we will be increasing - and decreasing around the polygon. - */ - if (mode) - { - Output_TriEx(*(index+increasing),*(index+decreasing),*(index+increasing+1),fp,-1,-1,where); - increasing++; - } - else - { - Output_TriEx(*(index+decreasing),*(index+increasing),*(index+decreasing-1),fp,-1,-1,where); - decreasing--; - } - mode = !mode; - } while ((decreasing - increasing) >= 2); - - } -} - - diff --git a/Tools/Stripe_w/struct.c b/Tools/Stripe_w/struct.c deleted file mode 100644 index 7010012b7..000000000 --- a/Tools/Stripe_w/struct.c +++ /dev/null @@ -1,549 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: struct.c - Contains routines that update structures, and micellaneous routines. -*/ -/*---------------------------------------------------------------------*/ - -#include -#include -#include "polverts.h" -#include "ties.h" -#include "output.h" -#include "triangulate.h" -#include "sturcts.h" -#include "options.h" -#include "common.h" -#include "util.h" - -int out1 = -1; -int out2 = -1; - -int Get_Edge(int *edge1,int *edge2,int *index,int face_id, - int size, int id1, int id2) -{ - /* Put the edge that is adjacent to face_id into edge1 - and edge2. For each edge see if it is adjacent to - face_id. Id1 and id2 is the input edge, so see if - the orientation is reversed, and save it in reversed. - */ - register int x; - int reversed = -1; - BOOL set = FALSE; - - for (x=0; x< size; x++) - { - if (x == (size-1)) - { - if ((*(index) == id1) && (*(index+size-1)==id2)) - { - if (set) - return 1; - reversed = 1; - } - else if ((*(index) == id2) && (*(index+size-1)==id1)) - { - if (set) - return 0; - reversed = 0; - } - - if (Look_Up(*(index),*(index+size-1),face_id)) - { - if ( (out1 != -1) && ( (out1 == *(index)) || (out1 == *(index+size-1)) ) && - ( (out2 == *(index)) || (out2 == *(index+size-1)) )) - { - set = TRUE; - *edge1 = *(index); - *edge2 = *(index+size-1); - } - else if (out1 == -1) - { - set = TRUE; - *edge1 = *(index); - *edge2 = *(index+size-1); - } - if ((reversed != -1) && (set)) - return reversed; - } - } - else - { - if ((*(index+x) == id1) && (*(index+x+1)==id2)) - { - if (set) - return 0; - reversed = 0; - } - else if ((*(index+x) == id2) && (*(index+x+1)==id1)) - { - if (set) - return 1; - reversed = 1; - } - - if (Look_Up(*(index+x),*(index+x+1),face_id)) - { - if ( (out1 != -1) && ( (out1 == *(index+x)) || (out1 == *(index+x+1)) ) && - ((out2 == *(index+x)) || (out2 == *(index+x+1)))) - { - set = TRUE; - *edge1 = *(index+x); - *edge2 = *(index+x+1); - } - else if (out1 == -1) - { - set = TRUE; - *edge1 = *(index+x); - *edge2 = *(index+x + 1); - } - if ((reversed != -1) && (set)) - return reversed; - } - } - } - if ((x == size) && (reversed != -1)) - { - /* Could not find the output edge */ - printf("Error in the Lookup %d %d %d %d %d %d %d %d\n",face_id,id1,id2,reversed,*edge1,*edge2,out1,out2); - exit(0); - } - return reversed; -} - - -void Update_Face(int *next_bucket, int *min_face, int face_id, int *e1, - int *e2,int temp1,int temp2,int *ties) -{ - /* We have a face id that needs to be decremented. - We have to determine where it is in the structure, - so that we can decrement it. - */ - /* The number of adjacencies may have changed, so to locate - it may be a little tricky. However we know that the number - of adjacencies is less than or equal to the original number - of adjacencies, - */ - int y,size; - ListHead *pListHead; - PF_FACES temp = NULL; - PLISTINFO lpListInfo; - static int each_poly = 0; - BOOL there = FALSE; - - pListHead = PolFaces[face_id]; - temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); - /* Check each edge of the face and tally the number of adjacent - polygons to this face. - */ - if ( temp != NULL ) - { - /* Size of the polygon */ - size = temp->nPolSize; - /* We did it already */ - if (size == 1) - return; - for (y = 0; y< size; y++) - { - /* If we are doing partial triangulation, we must check - to see whether the edge is still there in the polygon, - since we might have done a portion of the polygon - and saved the rest for later. - */ - if (y != (size-1)) - { - if( ((temp1 == *(temp->pPolygon+y)) && (temp2 ==*(temp->pPolygon+y+1))) - || ((temp2 == *(temp->pPolygon+y)) && (temp1 ==*(temp->pPolygon+y+1)))) - /* edge is still there we are ok */ - there = TRUE; - } - else - { - if( ((temp1 == *(temp->pPolygon)) && (temp2 == *(temp->pPolygon+size-1))) - || ((temp2 == *(temp->pPolygon)) && (temp1 ==*(temp->pPolygon+size-1)))) - /* edge is still there we are ok */ - there = TRUE; - } - } - - if (!there) - /* Original edge was already used, we cannot use this polygon */ - return; - - /* We have a starting point to start our search to locate - this polygon. - */ - - /* Check to see if this polygon was done */ - lpListInfo = Done(face_id,59,&y); - - if (lpListInfo == NULL) - return; - - /* Was not done, but there is an error in the adjacency calculations */ - if (y == 0) - { - printf("There is an error in finding the adjacencies\n"); - exit(0); - } - - /* Now put the face in the proper bucket depending on tally. */ - /* First add it to the new bucket, then remove it from the old */ - Add_Sgi_Adj(y-1,face_id); - RemoveList(array[y],lpListInfo); - - /* Save it if it was the smallest seen so far since then - it will be the next face - Here we will have different options depending on - what we want for resolving ties: - 1) First one we see we will use - 2) Random resolving - 3) Look ahead - 4) Alternating direction - */ - /* At a new strip */ - if (*next_bucket == 60) - *ties = *ties + each_poly; - /* Have a tie */ - if (*next_bucket == (y-1)) - { - Add_Ties(face_id); - each_poly++; - } - /* At a new minimum */ - if (*next_bucket > (y-1)) - { - *next_bucket = y-1; - *min_face = face_id; - *e1 = temp1; - *e2 = temp2; - each_poly = 0; - Clear_Ties(); - Add_Ties(face_id); - } - } -} - - -void Delete_Adj(int id1, int id2,int *next_bucket,int *min_face, - int current_face,int *e1,int *e2,int *ties) -{ - /* Find the face that is adjacent to the edge and is not the - current face. Delete one adjacency from it. Save the min - adjacency seen so far. - */ - register int count=0; - PF_EDGES temp = NULL; - ListHead *pListHead; - int next_face; - - /* Always want smaller id first */ - switch_lower(&id1,&id2); - - pListHead = PolEdges[id1]; - temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count); - if (temp == NULL) - /* It could be a new edge that we created. So we can - exit, since there is not a face adjacent to it. - */ - return; - while (temp->edge[0] != id2) - { - count++; - temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count); - if (temp == NULL) - /* Was a new edge that was created and therefore - does not have anything adjacent to it - */ - return; - } - /* Was not adjacent to anything else except itself */ - if (temp->edge[2] == -1) - return; - - /* Was adjacent to something */ - else - { - if (temp->edge[2] == current_face) - next_face = temp->edge[1]; - else - next_face = temp->edge[2]; - } - /* We have the other face adjacent to this edge, it is - next_face. Now we need to decrement this faces' adjacencies. - */ - Update_Face(next_bucket, min_face, next_face,e1,e2,id1,id2,ties); -} - - -int Change_Face(int face_id,int in1,int in2, - ListHead *pListHead, P_ADJACENCIES temp, BOOL no_check) -{ - /* We are doing a partial triangulation and we need to - put the new face of triangle into the correct bucket - */ - int input_adj,y; - - /* Find the old number of adjacencies to this face, - so we know where to delete it from - */ - y = Old_Adj(face_id); - - /* Do we need to change the adjacency? Maybe the edge on the triangle - that was outputted was not adjacent to anything. We know if we - have to check by "check". We came out on the output edge - that we needed, then we know that the adjacencies will decrease - by exactly one. - */ - if (!no_check) - { - input_adj = Number_Adj(in1,in2,face_id); - /* If there weren't any then don't do anything */ - if (input_adj == 0) - return y; - } - - RemoveList(pListHead,(PLISTINFO)temp); - /* Before we had a quad with y adjacencies. The in edge - did not have an adjacency, since it was just deleted, - since we came in on it. The outedge must have an adjacency - otherwise we would have a bucket 0, and would not be in this - routine. Therefore the new adjacency must be y-1 - */ - - Add_Sgi_Adj(y-1,face_id); - return (y-1); -} - -int Update_Adjacencies(int face_id, int *next_bucket, int *e1, int *e2, - int *ties) -{ - /* Give the face with id face_id, we want to decrement - all the faces that are adjacent to it, since we will - be deleting face_id from the data structure. - We will return the face that has the least number - of adjacencies. - */ - PF_FACES temp = NULL; - ListHead *pListHead; - int size,y,min_face = -1; - - *next_bucket = 60; - pListHead = PolFaces[face_id]; - temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); - - if ( temp == NULL ) - { - printf("The face was already deleted, there is an error\n"); - exit(0); - } - - /* Size of the polygon */ - size = temp->nPolSize; - for (y = 0; y< size; y++) - { - if (y != (size-1)) - Delete_Adj(*(temp->pPolygon+y),*(temp->pPolygon+y+1), - next_bucket,&min_face,face_id,e1,e2,ties); - else - Delete_Adj(*(temp->pPolygon),*(temp->pPolygon+(size-1)), - next_bucket,&min_face,face_id,e1,e2,ties); - } - return (min_face); -} - - -void Find_Adj_Tally(int id1, int id2,int *next_bucket,int *min_face, - int current_face,int *ties) -{ - /* Find the face that is adjacent to the edge and is not the - current face. Save the min adjacency seen so far. - */ - int size,each_poly=0,y,count=0; - PF_EDGES temp = NULL; - PF_FACES temp2 = NULL; - ListHead *pListHead; - int next_face; - BOOL there = FALSE; - - - /* Always want smaller id first */ - switch_lower(&id1,&id2); - - pListHead = PolEdges[id1]; - temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count); - if (temp == NULL) - /* This was a new edge that was created, so it is - adjacent to nothing. - */ - return; - - while (temp->edge[0] != id2) - { - count++; - temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count); - if (temp == NULL) - /* This was a new edge that we created */ - return; - } - /* Was not adjacent to anything else except itself */ - if (temp->edge[2] == -1) - return; - else - { - if (temp->edge[2] == current_face) - next_face = temp->edge[1]; - else - next_face = temp->edge[2]; - } - /* We have the other face adjacent to this edge, it is - next_face. Find how many faces it is adjacent to. - */ - pListHead = PolFaces[next_face]; - temp2 = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); - /* Check each edge of the face and tally the number of adjacent - polygons to this face. This will be the original number of - polygons adjacent to this polygon, we must then see if this - number has been decremented - */ - if ( temp2 != NULL ) - { - /* Size of the polygon */ - size = temp2->nPolSize; - /* We did it already */ - if (size == 1) - return; - for (y = 0; y< size; y++) - { - /* Make sure that the edge is still in the - polygon and was not deleted, because if the edge was - deleted, then we used it already. - */ - if (y != (size-1)) - { - if( ((id1 == *(temp2->pPolygon+y)) && (id2 ==*(temp2->pPolygon+y+1))) - || ((id2 == *(temp2->pPolygon+y)) && (id1 ==*(temp2->pPolygon+y+1)))) - /* edge is still there we are ok */ - there = TRUE; - } - else - { - if( ((id1 == *(temp2->pPolygon)) && (id2 ==*(temp2->pPolygon+size-1))) - || ((id2 == *(temp2->pPolygon)) && (id1 ==*(temp2->pPolygon+size-1)))) - /* edge is still there we are ok */ - there = TRUE; - } - } - - if (!there) - /* Edge already used and deleted from the polygon*/ - return; - - /* See if the face was already deleted, and where - it is if it was not - */ - if (Done(next_face,size,&y) == NULL) - return; - - /* Save it if it was the smallest seen so far since then - it will be the next face - Here we will have different options depending on - what we want for resolving ties: - 1) First one we see we will use - 2) Random resolving - 3) Look ahead - 4) Alternating direction - */ - - /* At a new strip */ - if (*next_bucket == 60) - *ties = *ties + each_poly; - /* Have a tie */ - if (*next_bucket == (y-1)) - { - Add_Ties(next_face); - each_poly++; - } - /* At a new minimum */ - if (*next_bucket > (y-1)) - { - *next_bucket = y-1; - *min_face = next_face; - each_poly = 0; - Clear_Ties(); - Add_Ties(next_face); - } - } -} - - -int Min_Face_Adj(int face_id, int *next_bucket, int *ties) -{ - /* Used for the Partial triangulation to find the next - face. It will return the minimum adjacency face id - found at this face. - */ - PF_FACES temp = NULL; - ListHead *pListHead; - int size,y,min_face,test_face; - - *next_bucket = 60; - pListHead = PolFaces[face_id]; - temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); - - if ( temp == NULL ) - { - printf("The face was already deleted, there is an error\n"); - exit(0); - } - - /* Size of the polygon */ - size = temp->nPolSize; - for (y = 0; y< size; y++) - { - if (y != (size-1)) - Find_Adj_Tally(*(temp->pPolygon+y),*(temp->pPolygon+y+1), - next_bucket,&min_face,face_id,ties); - else - Find_Adj_Tally(*(temp->pPolygon),*(temp->pPolygon+(size-1)), - next_bucket,&min_face,face_id,ties); - } - /* Maybe we can do better by triangulating the face, because - by triangulating the face we will go to a polygon of lesser - adjacencies - */ - if (size == 4) - { - /* Checking for a quad whether to do the whole polygon will - result in better performance because the triangles in the polygon - have less adjacencies - */ - Check_In_Quad(face_id,&test_face); - if (*next_bucket > test_face) - /* We can do better by going through the polygon */ - min_face = face_id; - } - - /* We have a polygon with greater than 4 sides, check to see if going - inside is better than going outside the polygon for the output edge. - */ - else - { - Check_In_Polygon(face_id,&test_face,size); - if (*next_bucket > test_face) - /* We can do better by going through the polygon */ - min_face = face_id; - } - - return (min_face); -} - - - diff --git a/Tools/Stripe_w/structex.c b/Tools/Stripe_w/structex.c deleted file mode 100644 index 70359ddc0..000000000 --- a/Tools/Stripe_w/structex.c +++ /dev/null @@ -1,553 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: structex.c - This file contains routines that are used for various functions in - the local algorithm. -*/ -/*---------------------------------------------------------------------*/ - -#include -#include -#include "polverts.h" -#include "ties.h" -#include "outputex.h" -#include "triangulatex.h" -#include "sturctsex.h" -#include "options.h" -#include "common.h" -#include "util.h" - -int out1Ex = -1; -int out2Ex = -1; - -int Get_EdgeEx(int *edge1,int *edge2,int *index,int face_id, - int size, int id1, int id2) -{ - /* Put the edge that is adjacent to face_id into edge1 - and edge2. For each edge see if it is adjacent to - face_id. Id1 and id2 is the input edge, so see if - the orientation is reversed, and save it in reversed. - */ - int x; - int reversed = -1; - BOOL set = FALSE; - - for (x=0; x< size; x++) - { - if (x == (size-1)) - { - if ((*(index) == id1) && (*(index+size-1)==id2)) - { - if (set) - return 1; - reversed = 1; - } - else if ((*(index) == id2) && (*(index+size-1)==id1)) - { - if (set) - return 0; - reversed = 0; - } - - if (Look_Up(*(index),*(index+size-1),face_id)) - { - if ( (out1Ex != -1) && ( (out1Ex == *(index)) || (out1Ex == *(index+size-1)) ) && - ( (out2Ex == *(index)) || (out2Ex == *(index+size-1)) )) - { - set = TRUE; - *edge1 = *(index); - *edge2 = *(index+size-1); - } - else if (out1Ex == -1) - { - set = TRUE; - *edge1 = *(index); - *edge2 = *(index+size-1); - } - if ((reversed != -1) && (set)) - return reversed; - } - } - else - { - if ((*(index+x) == id1) && (*(index+x+1)==id2)) - { - if (set) - return 0; - reversed = 0; - } - else if ((*(index+x) == id2) && (*(index+x+1)==id1)) - { - if (set) - return 1; - reversed = 1; - } - - if (Look_Up(*(index+x),*(index+x+1),face_id)) - { - if ( (out1Ex != -1) && ( (out1Ex == *(index+x)) || (out1Ex == *(index+x+1)) ) && - ((out2Ex == *(index+x)) || (out2Ex == *(index+x+1)))) - { - set = TRUE; - *edge1 = *(index+x); - *edge2 = *(index+x+1); - } - else if (out1Ex == -1) - { - set = TRUE; - *edge1 = *(index+x); - *edge2 = *(index+x + 1); - } - if ((reversed != -1) && (set)) - return reversed; - } - } - } - if ((x == size) && (reversed != -1)) - { - /* Could not find the output edge */ - printf("Error in the Lookup %d %d %d %d %d %d %d %d\n",face_id,id1,id2,reversed,*edge1,*edge2,out1Ex,out2Ex); - exit(0); - } - return reversed; -} - - -void Update_FaceEx(int *next_bucket, int *min_face, int face_id, int *e1, - int *e2,int temp1,int temp2,int *ties) -{ - /* We have a face id that needs to be decremented. - We have to determine where it is in the structure, - so that we can decrement it. - */ - /* The number of adjacencies may have changed, so to locate - it may be a little tricky. However we know that the number - of adjacencies is less than or equal to the original number - of adjacencies, - */ - int y,size; - ListHead *pListHead; - PF_FACES temp = NULL; - PLISTINFO lpListInfo; - static int each_poly = 0; - BOOL there = FALSE; - - pListHead = PolFaces[face_id]; - temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); - /* Check each edge of the face and tally the number of adjacent - polygons to this face. - */ - if ( temp != NULL ) - { - /* Size of the polygon */ - size = temp->nPolSize; - for (y = 0; y< size; y++) - { - /* If we are doing partial triangulation, we must check - to see whether the edge is still there in the polygon, - since we might have done a portion of the polygon - and saved the rest for later. - */ - if (y != (size-1)) - { - if( ((temp1 == *(temp->pPolygon+y)) && (temp2 ==*(temp->pPolygon+y+1))) - || ((temp2 == *(temp->pPolygon+y)) && (temp1 ==*(temp->pPolygon+y+1)))) - /* edge is still there we are ok */ - there = TRUE; - } - else - { - if( ((temp1 == *(temp->pPolygon)) && (temp2 == *(temp->pPolygon+size-1))) - || ((temp2 == *(temp->pPolygon)) && (temp1 ==*(temp->pPolygon+size-1)))) - /* edge is still there we are ok */ - there = TRUE; - } - } - - if (!there) - /* Original edge was already used, we cannot use this polygon */ - return; - - /* We have a starting point to start our search to locate - this polygon. - */ - - /* Check to see if this polygon was done */ - lpListInfo = Done(face_id,59,&y); - - if (lpListInfo == NULL) - return; - - /* Was not done, but there is an error in the adjacency calculations */ - /* If more than one edge is adj to it then maybe it was not updated */ - if (y == 0) - return; - - /* Now put the face in the proper bucket depending on tally. */ - /* First add it to the new bucket, then remove it from the old */ - Add_Sgi_Adj(y-1,face_id); - RemoveList(array[y],lpListInfo); - - /* Save it if it was the smallest seen so far since then - it will be the next face - Here we will have different options depending on - what we want for resolving ties: - 1) First one we see we will use - 2) Random resolving - 3) Look ahead - 4) Alternating direction - */ - /* At a new strip */ - if (*next_bucket == 60) - *ties = *ties + each_poly; - /* Have a tie */ - if (*next_bucket == (y-1)) - { - Add_Ties(face_id); - each_poly++; - } - /* At a new minimum */ - if (*next_bucket > (y-1)) - { - *next_bucket = y-1; - *min_face = face_id; - *e1 = temp1; - *e2 = temp2; - each_poly = 0; - Clear_Ties(); - Add_Ties(face_id); - } - } -} - - -void Delete_AdjEx(int id1, int id2,int *next_bucket,int *min_face, - int current_face,int *e1,int *e2,int *ties) -{ - /* Find the face that is adjacent to the edge and is not the - current face. Delete one adjacency from it. Save the min - adjacency seen so far. - */ - register int count=0; - PF_EDGES temp = NULL; - ListHead *pListHead; - int next_face; - - /* Always want smaller id first */ - switch_lower(&id1,&id2); - - pListHead = PolEdges[id1]; - temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count); - if (temp == NULL) - /* It could be a new edge that we created. So we can - exit, since there is not a face adjacent to it. - */ - return; - while (temp->edge[0] != id2) - { - count++; - temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count); - if (temp == NULL) - /* Was a new edge that was created and therefore - does not have anything adjacent to it - */ - return; - } - /* Was not adjacent to anything else except itself */ - if (temp->edge[2] == -1) - return; - - /* Was adjacent to something */ - else - { - if (temp->edge[2] == current_face) - next_face = temp->edge[1]; - else - next_face = temp->edge[2]; - } - /* We have the other face adjacent to this edge, it is - next_face. Now we need to decrement this faces' adjacencies. - */ - Update_FaceEx(next_bucket, min_face, next_face,e1,e2,id1,id2,ties); -} - -int Change_FaceEx(int face_id,int in1,int in2, - ListHead *pListHead, P_ADJACENCIES temp, BOOL no_check) -{ - /* We are doing a partial triangulation and we need to - put the new face of triangle into the correct bucket - */ - int input_adj,y; - P_ADJACENCIES pfNode,lpListInfo; - - /* Find the old number of adjacencies to this face, - so we know where to delete it from - */ - y = Old_Adj(face_id); - pListHead = array[y]; - - pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) ); - if ( pfNode ) - pfNode->face_id = face_id; - lpListInfo = (P_ADJACENCIES) (SearchList(array[y], pfNode, - (int (*)(void *,void *)) (Compare))); - if (lpListInfo == NULL) - { - printf("There is an error finding the next polygon3 %d\n",face_id); - exit(0); - } - - /* Do we need to change the adjacency? Maybe the edge on the triangle - that was outputted was not adjacent to anything. We know if we - have to check by "check". We came out on the output edge - that we needed, then we know that the adjacencies will decrease - by exactly one. - */ - if (!no_check) - { - input_adj = Number_Adj(in1,in2,face_id); - /* If there weren't any then don't do anything */ - if (input_adj == 0) - return y; - } - - RemoveList(pListHead,(PLISTINFO)/*(temp*/lpListInfo); - /* Before we had a quad with y adjacencies. The in edge - did not have an adjacency, since it was just deleted, - since we came in on it. The outedge must have an adjacency - otherwise we would have a bucket 0, and would not be in this - routine. Therefore the new adjacency must be y-1 - */ - - Add_Sgi_Adj(y-1,face_id); - return (y-1); -} - -int Update_AdjacenciesEx(int face_id, int *next_bucket, int *e1, int *e2, - int *ties) -{ - /* Give the face with id face_id, we want to decrement - all the faces that are adjacent to it, since we will - be deleting face_id from the data structure. - We will return the face that has the least number - of adjacencies. - */ - PF_FACES temp = NULL; - ListHead *pListHead; - int size,y,min_face = -1; - - *next_bucket = 60; - pListHead = PolFaces[face_id]; - temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); - - if ( temp == NULL ) - { - printf("The face was already deleted, there is an error\n"); - exit(0); - } - - /* Size of the polygon */ - size = temp->nPolSize; - for (y = 0; y< size; y++) - { - if (y != (size-1)) - Delete_AdjEx(*(temp->pPolygon+y),*(temp->pPolygon+y+1), - next_bucket,&min_face,face_id,e1,e2,ties); - else - Delete_AdjEx(*(temp->pPolygon),*(temp->pPolygon+(size-1)), - next_bucket,&min_face,face_id,e1,e2,ties); - } - return (min_face); -} - - - -void Find_Adj_TallyEx(int id1, int id2,int *next_bucket,int *min_face, - int current_face,int *ties) -{ - /* Find the face that is adjacent to the edge and is not the - current face. Save the min adjacency seen so far. - */ - int size,each_poly=0,y,tally=0,count=0; - PF_EDGES temp = NULL; - PF_FACES temp2 = NULL; - ListHead *pListHead; - int next_face; - BOOL there = FALSE; - - - /* Always want smaller id first */ - switch_lower(&id1,&id2); - - pListHead = PolEdges[id1]; - temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count); - if (temp == NULL) - /* This was a new edge that was created, so it is - adjacent to nothing. - */ - return; - while (temp->edge[0] != id2) - { - count++; - temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count); - if (temp == NULL) - /* This was a new edge that we created */ - return; - } - /* Was not adjacent to anything else except itself */ - if (temp->edge[2] == -1) - return; - else - { - if (temp->edge[2] == current_face) - next_face = temp->edge[1]; - else - next_face = temp->edge[2]; - } - /* We have the other face adjacent to this edge, it is - next_face. Find how many faces it is adjacent to. - */ - pListHead = PolFaces[next_face]; - temp2 = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); - /* Check each edge of the face and tally the number of adjacent - polygons to this face. This will be the original number of - polygons adjacent to this polygon, we must then see if this - number has been decremented - */ - if ( temp2 != NULL ) - { - /* Size of the polygon */ - size = temp2->nPolSize; - for (y = 0; y< size; y++) - { - /* Make sure that the edge is still in the - polygon and was not deleted, because if the edge was - deleted, then we used it already. - */ - if (y != (size-1)) - { - if( ((id1 == *(temp2->pPolygon+y)) && (id2 ==*(temp2->pPolygon+y+1))) - || ((id2 == *(temp2->pPolygon+y)) && (id1 ==*(temp2->pPolygon+y+1)))) - /* edge is still there we are ok */ - there = TRUE; - } - else - { - if( ((id1 == *(temp2->pPolygon)) && (id2 ==*(temp2->pPolygon+size-1))) - || ((id2 == *(temp2->pPolygon)) && (id1 ==*(temp2->pPolygon+size-1)))) - /* edge is still there we are ok */ - there = TRUE; - } - } - - if (!there) - /* Edge already used and deleted from the polygon*/ - return; - - /* See if the face was already deleted, and where - it is if it was not - */ - if (Done(next_face,size,&y) == NULL) - return; - - /* Save it if it was the smallest seen so far since then - it will be the next face - Here we will have different options depending on - what we want for resolving ties: - 1) First one we see we will use - 2) Random resolving - 3) Look ahead - 4) Alternating direction - */ - - /* At a new strip */ - if (*next_bucket == 60) - *ties = *ties + each_poly; - /* Have a tie */ - if (*next_bucket == (y-1)) - { - Add_Ties(next_face); - each_poly++; - } - /* At a new minimum */ - if (*next_bucket > (y-1)) - { - *next_bucket = y-1; - *min_face = next_face; - each_poly = 0; - Clear_Ties(); - Add_Ties(next_face); - } - } -} - - -int Min_Face_AdjEx(int face_id, int *next_bucket, int *ties) -{ - /* Used for the Partial triangulation to find the next - face. It will return the minimum adjacency face id - found at this face. - */ - PF_FACES temp = NULL; - ListHead *pListHead; - int size,y,min_face,test_face; - - *next_bucket = 60; - pListHead = PolFaces[face_id]; - temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); - - if ( temp == NULL ) - { - printf("The face was already deleted, there is an error\n"); - exit(0); - } - - /* Size of the polygon */ - size = temp->nPolSize; - for (y = 0; y< size; y++) - { - if (y != (size-1)) - Find_Adj_TallyEx(*(temp->pPolygon+y),*(temp->pPolygon+y+1), - next_bucket,&min_face,face_id,ties); - else - Find_Adj_TallyEx(*(temp->pPolygon),*(temp->pPolygon+(size-1)), - next_bucket,&min_face,face_id,ties); - } - /* Maybe we can do better by triangulating the face, because - by triangulating the face we will go to a polygon of lesser - adjacencies - */ - if (size == 4) - { - /* Checking for a quad whether to do the whole polygon will - result in better performance because the triangles in the polygon - have less adjacencies - */ - Check_In_Quad(face_id,&test_face); - if (*next_bucket > test_face) - /* We can do better by going through the polygon */ - min_face = face_id; - } - - /* We have a polygon with greater than 4 sides, check to see if going - inside is better than going outside the polygon for the output edge. - */ - else - { - Check_In_Polygon(face_id,&test_face,size); - if (*next_bucket > test_face) - /* We can do better by going through the polygon */ - min_face = face_id; - } - - return (min_face); -} - - diff --git a/Tools/Stripe_w/sturcts.h b/Tools/Stripe_w/sturcts.h deleted file mode 100644 index 57490a695..000000000 --- a/Tools/Stripe_w/sturcts.h +++ /dev/null @@ -1,36 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: sturcts.h ------------------------------------------------------------------------*/ - -#define EVEN(x) (((x) & 1) == 0) - -int Get_Edge(int *edge1,int *edge2,int *index,int face_id, - int size, int id1, int id2); -void add_vert_id(); -void Update_Face(int *next_bucket, int *min_face, int face_id, int *e1, - int *e2,int temp1,int temp2,int *ties); -int Min_Adj(); -int Min_Face_Adj(int face_id, int *next_bucket, int *ties); -int Change_Face(int face_id,int in1,int in2, ListHead *pListHead, - P_ADJACENCIES temp, BOOL no_check); -void Delete_Adj(int id1, int id2,int *next_bucket,int *min_face, - int current_face,int *e1,int *e2,int *ties); -int Update_Adjacencies(int face_id, int *next_bucket, int *e1, int *e2, - int *ties); -int Get_Output_Edge(); -int Find_Face(); - - - - - - - diff --git a/Tools/Stripe_w/sturctsex.h b/Tools/Stripe_w/sturctsex.h deleted file mode 100644 index 6a4a76dbe..000000000 --- a/Tools/Stripe_w/sturctsex.h +++ /dev/null @@ -1,33 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE:sturctsex.h ------------------------------------------------------------------------*/ - -#define EVEN(x) (((x) & 1) == 0) - -int Get_EdgeEx(int *edge1,int *edge2,int *index,int face_id, - int size, int id1, int id2); -void add_vert_idEx(); -void Update_FaceEx(int *next_bucket, int *min_face, int face_id, int *e1, - int *e2,int temp1,int temp2,int *ties); -int Min_Face_AdjEx(int face_id, int *next_bucket, int *ties); -int Change_FaceEx(int face_id,int in1,int in2, - ListHead *pListHead, P_ADJACENCIES temp, BOOL no_check); -void Delete_AdjEx(int id1, int id2,int *next_bucket,int *min_face, - int current_face,int *e1,int *e2,int *ties); -int Number_AdjEx(); -int Update_AdjacenciesEx(int face_id, int *next_bucket, int *e1, int *e2, - int *ties); - - - - - - diff --git a/Tools/Stripe_w/ties.c b/Tools/Stripe_w/ties.c deleted file mode 100644 index e3fd31f78..000000000 --- a/Tools/Stripe_w/ties.c +++ /dev/null @@ -1,304 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: ties.c - This file will contain all the routines used to determine the next face if there - is a tie -*/ -/*---------------------------------------------------------------------*/ - -#include -#include "polverts.h" -#include "ties.h" -#include "sturctsex.h" -#include "triangulatex.h" -#include "options.h" -#include "common.h" -#include "util.h" - -#define MAX_TIE 60 -int ties_array[60]; -int last = 0; - -void Clear_Ties() -{ - /* Clear the buffer, because we do not have the tie - any more that we had before */ - last = 0; -} - -void Add_Ties(int id) -{ - /* We have a tie to add to the buffer */ - ties_array[last++] = id; -} - -int Alternate_Tie() -{ - /* Alternate in what we choose to break the tie - We are just alternating between the first and - second thing that we found - */ - static int x = 0; - register int t; - - t = ties_array[x]; - x++; - if (x == 2) - x = 0; - return t; -} - -int Random_Tie() -{ - /* Randomly choose the next face with which - to break the tie - */ - register int num; - - num = rand(); - while (num >= last) - num = num/20; - return (ties_array[num]); -} - -int Look_Ahead(int id) -{ - /* Look ahead at this face and save the minimum - adjacency of all the faces that are adjacent to - this face. - */ - return Min_Adj(id); -} - -int Random_Look(int id[],int count) -{ - /* We had a tie within a tie in the lookahead, - break it randomly - */ - register int num; - - num = rand(); - while (num >= count) - num = num/20; - return (id[num]); -} - - -int Look_Ahead_Tie() -{ - /* Look ahead and find the face to go to that - will give the least number of adjacencies - */ - int id[60],t,x,f=0,min = 60; - - for (x = 0; x < last; x++) - { - t = Look_Ahead(ties_array[x]); - /* We have a tie */ - if (t == min) - id[f++] = ties_array[x]; - if (t < min) - { - f = 0; - min = t; - id[f++] = ties_array[x]; - } - } - /* No tie within the tie */ - if ( f == 1) - return id[0]; - /* Or ties, but we are at the end of strips */ - if (min == 0) - return id[0]; - return (Random_Look(id,f)); -} - - -int Sequential_Tri(int *index) -{ - /* We have a triangle and need to break the ties at it. - We will choose the edge that is sequential. There - is definitely one since we know we have a triangle - and that there is a tie and there are only 2 edges - for the tie. - */ - int e1,e2,e3,output1,output2,output3,output4; - - /* e2 and e3 are the input edge to the triangle */ - Last_Edge(&e1,&e2,&e3,0); - - if ((e2 == 0) && (e3 == 0)) - /* Starting the strip, don't need to do this */ - return ties_array[0]; - - /* For the 2 ties find the edge adjacent to face id */ - Get_EdgeEx(&output1,&output2,index,ties_array[0],3,0,0); - Get_EdgeEx(&output3,&output4,index,ties_array[1],3,0,0); - - if ((output1 == e3) || (output2 == e3)) - return ties_array[0]; - if ((output3 == e3) || (output4 == e3)) - return ties_array[1]; - printf("There is an error trying to break sequential triangle \n"); -} - -int Sequential_Quad(int *index, int triangulate) -{ - /* We have a quad that need to break its ties, we will try - and choose a side that is sequential, otherwise use lookahead - */ - int output1,output2,x,e1,e2,e3; - - /* e2 and e3 are the input edge to the quad */ - Last_Edge(&e1,&e2,&e3,0); - - /* No input edge */ - if ((e2 == 0) && (e3 == 0)) - return ties_array[0]; - - /* Go through the ties and see if there is a sequential one */ - for (x = 0; x < last; x++) - { - Get_EdgeEx(&output1,&output2,index,ties_array[x],4,0,0); - /* Partial and whole triangulation will have different requirements */ - if (((output1 == e3) || (output2 == e3)) && (triangulate == PARTIAL)) - return ties_array[x]; - if (((output1 != e3) && (output1 != e2) && - (output2 != e3) && (output2 != e2))) - return ties_array[x]; - } - /* There was not a tie that was sequential */ - return Look_Ahead_Tie(); -} - -void Whole_Output(int in1,int in2, int *index, int size, int *out1, int *out2) -{ - /* Used to sequentially break ties in the whole triangulation for polygons - greater than 4 sides. We will find the output edge that is good - for sequential triangulation. - */ - - int half; - - /* Put the input edge first in the list */ - Rearrange_IndexEx(index,size); - - if (!(EVEN(size))) - { - if (*(index) == in1) - half = size/2 ; - else - half = size/2 +1; - } - else - half = size/2; - - *out1 = *(index+half); - *out2 = *(index+half+1); -} - -int Sequential_Poly(int size, int *index, int triangulate) -{ - /* We have a polygon of greater than 4 sides and wish to break the - tie in the most sequential manner. - */ - - int x,output1,output2,e1,e2,e3,saved1=-1,saved2=-1,output3,output4; - - /* e2 and e3 are the input edge to the quad */ - Last_Edge(&e1,&e2,&e3,0); - - /* If we are using whole, find the output edge that is sequential */ - if (triangulate == WHOLE) - Whole_Output(e2,e3,index,size,&output3,&output4); - - /* No input edge */ - if ((e2 == 0) && (e3 == 0)) - return ties_array[0]; - - for (x = 0; x < last ; x++) - { - Get_EdgeEx(&output1,&output2,index,ties_array[x],size,0,0); - /* Partial that can be removed in just one triangle */ - if (((output1 == e3) || (output2 == e3)) && (triangulate == PARTIAL)) - saved1 = ties_array[x]; - /* Partial removed in more than one triangle */ - if ((output1 != e3) && (output1 != e2) && (output2 != e3) && (output2 != e2) && - (triangulate == PARTIAL) && (saved2 != -1)) - saved2 = ties_array[x]; - /* Whole is not so easy, since the whole polygon must be done. Given - an input edge there is only one way to come out, approximately half - way around the polygon. - */ - if (((output1 == output3) && (output2 == output4)) || - ((output1 == output4) && (output2 == output3)) && - (triangulate == WHOLE)) - return ties_array[x]; - } - - if (saved1 != -1) - return saved1; - if (saved2 != -1) - return saved2; - - /* There was not a tie that was sequential */ - return Look_Ahead_Tie(); -} - -int Sequential_Tie(int face_id, int triangulate) -{ - /* Break the tie by choosing the face that will - not give us a swap and is sequential. If there - is not one, then do the lookahead to break the - tie. - */ - /* Separate into 3 cases for simplicity, if the current - polygon has 3 sides, 4 sides or if the sides were - greater. We can do the smaller cases faster, so that - is why I separated the cases. - */ - - ListHead *pListFace; - PF_FACES face; - - /* Get the polygon with id face_id */ - pListFace = PolFaces[face_id]; - face = (PF_FACES) PeekList(pListFace,LISTHEAD,0); - - if (face->nPolSize == 3) - return(Sequential_Tri(face->pPolygon)); - if (face->nPolSize == 4) - return(Sequential_Quad(face->pPolygon,triangulate)); - else - return(Sequential_Poly(face->nPolSize,face->pPolygon,triangulate)); - -} - -int Get_Next_Face(int t, int face_id, int triangulate) -{ - /* Get the next face depending on what - the user specified - */ - - /* Did not have a tie, don't do anything */ - if (last == 1) - return(ties_array[0]); - if (t == RANDOM) - return Random_Tie(); - if (t == ALTERNATE) - return Alternate_Tie(); - if (t == LOOK) - return Look_Ahead_Tie(); - if (t == SEQUENTIAL) - return Sequential_Tie(face_id,triangulate); - - printf("Illegal option specified for ties, using first \n"); - return (ties_array[0]); -} diff --git a/Tools/Stripe_w/ties.h b/Tools/Stripe_w/ties.h deleted file mode 100644 index 502aabf4d..000000000 --- a/Tools/Stripe_w/ties.h +++ /dev/null @@ -1,15 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: ties.h ------------------------------------------------------------------------*/ - -void Clear_Ties(); -void Add_Ties(int id); -int Get_Next_Face(int t, int face_id, int triangulate); diff --git a/Tools/Stripe_w/triangulate.h b/Tools/Stripe_w/triangulate.h deleted file mode 100644 index 1f677430a..000000000 --- a/Tools/Stripe_w/triangulate.h +++ /dev/null @@ -1,27 +0,0 @@ - -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: triangulate.h ------------------------------------------------------------------------*/ - -void Blind_Triangulate(int size, int *index, FILE *output, - BOOL begin, int where ,int color1,int color2, - int color3); -void Non_Blind_Triangulate(int size,int *index, FILE *output, - int next_face_id,int face_id,int where, - int color1,int color2,int color3); -int Adjacent(int id2,int id1, int *list, int size); -void Delete_From_List(int id,int *list, int *size); -void Triangulate_Polygon(int out_edge1, int out_edge2, int in_edge1, - int in_edge2, int size, int *index, - FILE *output, int reversed, int face_id, - int where, int color1, int color2, int color3); -void Rearrange_Index(int *index, int size); -void Find_Local_Strips(); diff --git a/Tools/Stripe_w/triangulatex.h b/Tools/Stripe_w/triangulatex.h deleted file mode 100644 index 3b2d8fb5c..000000000 --- a/Tools/Stripe_w/triangulatex.h +++ /dev/null @@ -1,28 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: triangulatex.h ------------------------------------------------------------------------*/ - -enum swap_type -{ ON, OFF}; - -void SGI_StripEx(); -void Blind_TriangulateEx(int size, int *index, FILE *fp, FILE *output, - BOOL begin, int where ); -void Non_Blind_TriangulateEx(int size,int *index, FILE *fp, FILE *output, - int next_face_id,int face_id,int where); -int AdjacentEx(int id2,int id1, int *list, int size); -void Delete_From_ListEx(int id,int *list, int size); -void Triangulate_PolygonEx(int out_edge1,int out_edge2,int in_edge1, - int in_edge2,int size,int *index, - FILE *output,FILE *fp,int reversed,int face_id, - int where); -void Rearrange_IndexEx(int *index, int size); -void Find_StripsEx(); diff --git a/Tools/Stripe_w/util.c b/Tools/Stripe_w/util.c deleted file mode 100644 index f17fe5f7c..000000000 --- a/Tools/Stripe_w/util.c +++ /dev/null @@ -1,272 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: util.c - This file contains routines that are used for various functions -*/ -/*---------------------------------------------------------------------*/ - - -#include -#include "polverts.h" - -void switch_lower (int *x, int *y) -{ - register int temp; - - /* Put lower value in x */ - if (*y < *x) - { - temp = *x; - *x = *y; - *y = temp; - } -} - -BOOL member(int x , int id1, int id2, int id3) -{ - /* Is x in the triangle specified by id1,id2,id3 */ - if ((x != id1) && (x != id2) && (x != id3)) - return FALSE; - return TRUE; -} - - -int Compare (P_ADJACENCIES node1, P_ADJACENCIES node2) -{ - /* This will only return whether 2 adjacency nodes - are equivalent. - */ - if (node1->face_id == node2->face_id) - return TRUE; - else - return FALSE; -} - - -BOOL Exist(int face_id, int id1, int id2) -{ - /* Does the edge specified by id1 and id2 exist in this - face currently? Maybe we deleted in partial triangulation - */ - ListHead *pListHead; - PF_FACES temp; - register int x,size; - BOOL a=FALSE,b =FALSE; - - pListHead = PolFaces[face_id]; - temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); - size = temp->nPolSize; - for (x=0; xpPolygon+x) == id1) - a = TRUE; - if (*(temp->pPolygon+x) == id2) - b = TRUE; - if (a && b) - return TRUE; - } - return FALSE; -} - -int Get_Next_Id(int *index,int e3, int size) -{ - /* Return the id following e3 in the list of vertices */ - - register int x; - - for (x = 0; x< size; x++) - { - if ((*(index+x) == e3) && (x != (size-1))) - return *(index+x+1); - else if (*(index+x) == e3) - return *(index); - } - printf("There is an error in the next id\n"); - exit(0); -} - -int Different (int id1,int id2,int id3,int id4,int id5, int id6, int *x, int *y) -{ - /* Find the vertex in the first 3 numbers that does not exist in - the last three numbers - */ - if ((id1 != id4) && (id1 != id5) && (id1 != id6)) - { - *x = id2; - *y = id3; - return id1; - } - if ((id2 != id4) && (id2 != id5) && (id2 != id6)) - { - *x = id1; - *y = id3; - return id2; - } - if ((id3 != id4) && (id3 != id5) && (id3 != id6)) - { - *x = id1; - *y = id2; - return id3; - } - - /* Because there are degeneracies in the data, this might occur */ - *x = id5; - *y = id6; - return id4; -} - -int Return_Other(int *index,int e1,int e2) -{ - /* We have a triangle and want to know the third vertex of it */ - register int x; - - for (x=0;x<3;x++) - { - if ((*(index+x) != e1) && (*(index+x) != e2)) - return *(index+x); - } - /* If there is a degenerate triangle return arbitrary */ - return e1; -} - -int Get_Other_Vertex(int id1,int id2,int id3,int *index) -{ - /* We have a list index of 4 numbers and we wish to - return the number that is not id1,id2 or id3 - */ - register int x; - - for (x=0; x<4; x++) - { - if ((*(index+x) != id1) && (*(index+x) != id2) && - (*(index+x) != id3)) - return *(index+x); - } - /* If there is some sort of degeneracy this might occur, - return arbitrary - */ - if (x==4) - return id1; -} - - -PLISTINFO Done(int face_id, int size, int *bucket) -{ - /* Check to see whether the polygon with face_id was used - already, return NULL if it was, otherwise return a pointer to the face. - */ - P_ADJACENCIES pfNode; - register int y; - PLISTINFO lpListInfo; - - pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) ); - if ( pfNode ) - pfNode->face_id = face_id; - - for (y=size; ; y--) - { - lpListInfo = SearchList(array[y], pfNode, - (int (*)(void *,void *)) (Compare)); - if (lpListInfo != NULL) - { - *bucket = y; - return lpListInfo; - } - if (y == 0) - /* This adjacent face was done already */ - return lpListInfo; - } - free (pfNode); -} - -void Output_Edge(int *index,int e2,int e3,int *output1,int *output2) -{ - /* Given a quad and an input edge return the other 2 vertices of the - quad. - */ - - *output1 = -1; - *output2 = -1; - - if ((*(index) != e2) && (*(index) != e3)) - *output1 = *(index); - - if ((*(index+1) != e2) && (*(index+1) != e3)) - { - if (*output1 == -1) - *output1 = *(index+1); - else - { - *output2 = *(index+1); - return; - } - } - - if ((*(index+2) != e2) && (*(index+2) != e3)) - { - if (*output1 == -1) - *output1 = *(index+2); - else - { - *output2 = *(index+2); - return; - } - } - - *output2 = *(index+3); -} - - -void First_Edge(int *id1,int *id2, int *id3) -{ - /* Get the first triangle in the strip we just found, we will use this to - try to extend backwards in the strip - */ - - ListHead *pListHead; - register int num; - P_STRIPS temp1,temp2,temp3; - - pListHead = strips[0]; - num = NumOnList(pListHead); - - /* Did not have a strip */ - if (num < 3) - return; - - temp1 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 0); - temp2 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 1); - temp3 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 2); - *id1 = temp1->face_id; - *id2 = temp2->face_id; - *id3 = temp3->face_id; - -} - -void Last_Edge(int *id1, int *id2, int *id3, BOOL save) -{ - /* We need the last edge that we had */ - static int v1, v2, v3; - - if (save) - { - v1 = *id1; - v2 = *id2; - v3 = *id3; - } - else - { - *id1 = v1; - *id2 = v2; - *id3 = v3; - } -} - - diff --git a/Tools/Stripe_w/util.h b/Tools/Stripe_w/util.h deleted file mode 100644 index 64c2f2334..000000000 --- a/Tools/Stripe_w/util.h +++ /dev/null @@ -1,24 +0,0 @@ -/********************************************************************/ -/* STRIPE: converting a polygonal model to triangle strips - Francine Evans, 1996. - SUNY @ Stony Brook - Advisors: Steven Skiena and Amitabh Varshney -*/ -/********************************************************************/ - -/*---------------------------------------------------------------------*/ -/* STRIPE: util.h ------------------------------------------------------------------------*/ - -void switch_lower (int *x, int *y); -int Compare (P_ADJACENCIES node1, P_ADJACENCIES node2); -BOOL Exist(int face_id, int id1, int id2); -int Get_Next_Id(int *index,int e3, int size); -int Different(int id1,int id2,int id3,int id4,int id5, int id6, int *x, int *y); -int Return_Other(int *index,int e1,int e2); -int Get_Other_Vertex(int id1,int id2,int id3,int *index); -PLISTINFO Done(int face_id, int size, int *bucket); -void Output_Edge(int *index,int e2,int e3,int *output1,int *output2); -void Last_Edge(int *id1, int *id2, int *id3, BOOL save); -void First_Edge(int *id1,int *id2, int *id3); -BOOL member(int x , int id1, int id2, int id3); diff --git a/Tools/Tools/Todo b/Tools/Todo similarity index 100% rename from Tools/Tools/Todo rename to Tools/Todo diff --git a/Tools/Tri2obj/Makefile.am b/Tools/Tri2obj/Makefile.am deleted file mode 100644 index c27fc320f..000000000 --- a/Tools/Tri2obj/Makefile.am +++ /dev/null @@ -1,71 +0,0 @@ -#--------------------------------------------------------------------------- -# Makefile -# -# Written by Curtis Olson, started January 1998. -# -# Copyright (C) 1998 Curtis L. Olson - curt@me.umn.edu -# -# 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. -# -# $Id$ -# (Log is kept at end of this file) -#--------------------------------------------------------------------------- - - -bin_PROGRAMS = tri2obj - -tri2obj_SOURCES = tri2obj.cxx tri2obj.hxx - -tri2obj_LDADD = \ - $(top_builddir)/Lib/Bucket/libBucket.a \ - $(top_builddir)/Lib/Math/libMath.a \ - $(top_builddir)/Lib/Debug/libDebug.a \ - $(top_builddir)/Lib/zlib/libz.a \ - $(base_LIBS) - -INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib - - -#--------------------------------------------------------------------------- -# $Log$ -# Revision 1.7 1998/11/04 23:02:02 curt -# Changes to the automake/autoconf system to reduce the number of libraries -# that are unnecessarily linked into the various executables. -# -# Revision 1.6 1998/07/30 23:49:26 curt -# Removed libtool support. -# -# Revision 1.5 1998/07/08 14:49:14 curt -# tweaks. -# -# Revision 1.4 1998/04/24 00:44:07 curt -# Added zlib support. -# -# Revision 1.3 1998/04/18 04:01:29 curt -# Now use libMath rather than having local copies of math routines. -# -# Revision 1.2 1998/04/14 02:26:09 curt -# Code reorganizations. Added a Lib/ directory for more general libraries. -# -# Revision 1.1 1998/04/08 23:22:13 curt -# Adopted Gnu automake/autoconf system. -# -# Revision 1.2 1998/01/21 02:55:46 curt -# Incorporated new make system from Bob Kuehne . -# -# Revision 1.1 1998/01/15 02:45:25 curt -# Initial revision. -# - diff --git a/Tools/Tri2obj/tri2obj.cxx b/Tools/Tri2obj/tri2obj.cxx deleted file mode 100644 index a3401052c..000000000 --- a/Tools/Tri2obj/tri2obj.cxx +++ /dev/null @@ -1,695 +0,0 @@ -// tri2obj.cxx -- read in a .ele/.node file pair generated by the triangle -// program and output a simple Wavefront .obj file. -// -// Written by Curtis Olson, started October 1997. -// -// Copyright (C) 1997 Curtis L. Olson - curt@infoplane.com -// -// 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. -// -// $Id$ -// (Log is kept at end of this file) - - -#include -#include // for atoi() -#include -#include // for stat() -#include // for stat() - -#include "tri2obj.hxx" - -#include -#include - -#include -#include -#include - - -int nodecount, tricount; -int normalcount = 0; -static Point3D nodes[MAX_NODES]; -static int tris[MAX_TRIS][3]; - -static double normals[MAX_NODES][3]; - -fgBUCKET my_index; -fgBUCKET ne_index, nw_index, sw_index, se_index; -fgBUCKET north_index, south_index, east_index, west_index; - - -// given three points defining a triangle, calculate the normal -void calc_normal(const Point3D& p1, const Point3D& p2, - const Point3D& p3, double normal[3]) -{ - double v1[3], v2[3]; - double temp; - - v1[0] = p2.x() - p1.x(); v1[1] = p2.y() - p1.y(); v1[2] = p2.z() - p1.z(); - v2[0] = p3.x() - p1.x(); v2[1] = p3.y() - p1.y(); v2[2] = p3.z() - p1.z(); - - MAT3cross_product(normal, v1, v2); - MAT3_NORMALIZE_VEC(normal, temp); - -// printf(" Normal = %.2f %.2f %.2f\n", normal[0], normal[1], normal[2]); -} - - -// return the index of all triangles containing the specified node -void find_tris(int n, int *t1, int *t2, int *t3, int *t4, int *t5) { - int i; - - *t1 = *t2 = *t3 = *t4 = *t5 = 0; - - i = 1; - while ( i <= tricount ) { - if ( (n == tris[i][0]) || (n == tris[i][1]) || (n == tris[i][2]) ) { - if ( *t1 == 0 ) { - *t1 = i; - } else if ( *t2 == 0 ) { - *t2 = i; - } else if ( *t3 == 0 ) { - *t3 = i; - } else if ( *t4 == 0 ) { - *t4 = i; - } else { - *t5 = i; - } - } - i++; - } -} - - -// return the file base name ( foo/bar/file.ext = file.ext ) -void extract_file(char *in, char *base) { - int len, i; - - len = strlen(in); - - i = len - 1; - while ( (i >= 0) && (in[i] != '/') ) { - i--; - } - - in += (i + 1); - strcpy(base, in); -} - - -// return the file path name ( foo/bar/file.ext = foo/bar ) -void extract_path(char *in, char *base) { - int len, i; - - len = strlen(in); - strcpy(base, in); - - i = len - 1; - while ( (i >= 0) && (in[i] != '/') ) { - i--; - } - - base[i] = '\0'; -} - - -// check if a file exists -int file_exists(char *file) { - struct stat stat_buf; - int result; - - printf("checking %s ... ", file); - - result = stat(file, &stat_buf); - - if ( result != 0 ) { - // stat failed, no file - printf("not found.\n"); - return(0); - } else { - // stat succeeded, file exists - printf("exists.\n"); - return(1); - } -} - - -// check to see if a shared object exists -int shared_object_exists(char *basepath, char *ext, char *file) { - char scene_path[256]; - long int index; - - if ( strcmp(ext, ".sw") == 0 ) { - fgBucketGenBasePath(&my_index, scene_path); - index = fgBucketGenIndex(&my_index); - sprintf(file, "%s/%s/%ld.1.sw", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - fgBucketGenBasePath(&west_index, scene_path); - index = fgBucketGenIndex(&west_index); - sprintf(file, "%s/%s/%ld.1.se", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - fgBucketGenBasePath(&sw_index, scene_path); - index = fgBucketGenIndex(&sw_index); - sprintf(file, "%s/%s/%ld.1.ne", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - fgBucketGenBasePath(&south_index, scene_path); - index = fgBucketGenIndex(&south_index); - sprintf(file, "%s/%s/%ld.1.nw", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - } - - if ( strcmp(ext, ".se") == 0 ) { - fgBucketGenBasePath(&my_index, scene_path); - index = fgBucketGenIndex(&my_index); - sprintf(file, "%s/%s/%ld.1.se", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - fgBucketGenBasePath(&east_index, scene_path); - index = fgBucketGenIndex(&east_index); - sprintf(file, "%s/%s/%ld.1.sw", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - fgBucketGenBasePath(&se_index, scene_path); - index = fgBucketGenIndex(&se_index); - sprintf(file, "%s/%s/%ld.1.nw", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - fgBucketGenBasePath(&south_index, scene_path); - index = fgBucketGenIndex(&south_index); - sprintf(file, "%s/%s/%ld.1.ne", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - } - - if ( strcmp(ext, ".ne") == 0 ) { - fgBucketGenBasePath(&my_index, scene_path); - index = fgBucketGenIndex(&my_index); - sprintf(file, "%s/%s/%ld.1.ne", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - fgBucketGenBasePath(&east_index, scene_path); - index = fgBucketGenIndex(&east_index); - sprintf(file, "%s/%s/%ld.1.nw", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - fgBucketGenBasePath(&ne_index, scene_path); - index = fgBucketGenIndex(&ne_index); - sprintf(file, "%s/%s/%ld.1.sw", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - fgBucketGenBasePath(&north_index, scene_path); - index = fgBucketGenIndex(&north_index); - sprintf(file, "%s/%s/%ld.1.se", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - } - - if ( strcmp(ext, ".nw") == 0 ) { - fgBucketGenBasePath(&my_index, scene_path); - index = fgBucketGenIndex(&my_index); - sprintf(file, "%s/%s/%ld.1.nw", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - fgBucketGenBasePath(&west_index, scene_path); - index = fgBucketGenIndex(&west_index); - sprintf(file, "%s/%s/%ld.1.ne", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - fgBucketGenBasePath(&nw_index, scene_path); - index = fgBucketGenIndex(&nw_index); - sprintf(file, "%s/%s/%ld.1.se", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - fgBucketGenBasePath(&north_index, scene_path); - index = fgBucketGenIndex(&north_index); - sprintf(file, "%s/%s/%ld.1.sw", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - } - - if ( strcmp(ext, ".south") == 0 ) { - fgBucketGenBasePath(&my_index, scene_path); - index = fgBucketGenIndex(&my_index); - sprintf(file, "%s/%s/%ld.1.south", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - fgBucketGenBasePath(&south_index, scene_path); - index = fgBucketGenIndex(&south_index); - sprintf(file, "%s/%s/%ld.1.north", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - } - - if ( strcmp(ext, ".north") == 0 ) { - fgBucketGenBasePath(&my_index, scene_path); - index = fgBucketGenIndex(&my_index); - sprintf(file, "%s/%s/%ld.1.north", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - fgBucketGenBasePath(&north_index, scene_path); - index = fgBucketGenIndex(&north_index); - sprintf(file, "%s/%s/%ld.1.south", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - } - - if ( strcmp(ext, ".west") == 0 ) { - fgBucketGenBasePath(&my_index, scene_path); - index = fgBucketGenIndex(&my_index); - sprintf(file, "%s/%s/%ld.1.west", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - fgBucketGenBasePath(&west_index, scene_path); - index = fgBucketGenIndex(&west_index); - sprintf(file, "%s/%s/%ld.1.east", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - } - - if ( strcmp(ext, ".east") == 0 ) { - fgBucketGenBasePath(&my_index, scene_path); - index = fgBucketGenIndex(&my_index); - sprintf(file, "%s/%s/%ld.1.east", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - fgBucketGenBasePath(&east_index, scene_path); - index = fgBucketGenIndex(&east_index); - sprintf(file, "%s/%s/%ld.1.west", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - } - - if ( strcmp(ext, ".body") == 0 ) { - fgBucketGenBasePath(&my_index, scene_path); - index = fgBucketGenIndex(&my_index); - sprintf(file, "%s/%s/%ld.1.body", basepath, scene_path, index); - if ( file_exists(file) ) { - return(1); - } - } - - return(0); -} - - -// given a file pointer, read all the vn (normals from it) -void read_normals(FILE *fp) { - char line[256]; - - while ( fgets(line, 250, fp) != NULL ) { - if ( strncmp(line, "vn ", 3) == 0 ) { - sscanf( line, "vn %lf %lf %lf\n", - &normals[normalcount][0], - &normals[normalcount][1], - &normals[normalcount][2] ); - /* - printf("read_normals(%d) %.2f %.2f %.2f %s", normalcount, - normals[normalcount][0], normals[normalcount][1], - normals[normalcount][2], line); - */ - normalcount++; - } - } -} - - -// my custom file opening routine ... don't open if a shared edge or -// vertex alread exists -FILE *my_open(char *basename, char *basepath, char *ext) { - FILE *fp; - char filename[256]; - - // check if a shared object already exists - if ( shared_object_exists(basepath, ext, filename) ) { - // not an actual file open error, but we've already got the - // shared edge, so we don't want to create another one - fp = fopen(filename, "r"); - printf("Opening %s\n", filename); - return(fp); - } else { - // open the file - printf("not opening\n"); - return(NULL); - } -} - - -// Initialize a new mesh structure -void triload(char *basename, char *basepath) { - char nodename[256], elename[256]; - double n[3]; - Point3D p; - FILE *ne, *nw, *se, *sw, *north, *south, *east, *west; - FILE *node, *ele; - int dim, junk1, junk2; - int i; - - ne = my_open(basename, basepath, ".ne"); - read_normals(ne); - fclose(ne); - - nw = my_open(basename, basepath, ".nw"); - read_normals(nw); - fclose(nw); - - se = my_open(basename, basepath, ".se"); - read_normals(se); - fclose(se); - - sw = my_open(basename, basepath, ".sw"); - read_normals(sw); - fclose(sw); - - north = my_open(basename, basepath, ".north"); - read_normals(north); - fclose(north); - - south = my_open(basename, basepath, ".south"); - read_normals(south); - fclose(south); - - east = my_open(basename, basepath, ".east"); - read_normals(east); - fclose(east); - - west = my_open(basename, basepath, ".west"); - read_normals(west); - fclose(west); - - strcpy(nodename, basename); - strcat(nodename, ".node"); - strcpy(elename, basename); - strcat(elename, ".ele"); - - printf("Loading node file: %s ...\n", nodename); - if ( (node = fopen(nodename, "r")) == NULL ) { - printf("Cannot open file '%s'\n", nodename); - exit(-1); - } - - fscanf(node, "%d %d %d %d", &nodecount, &dim, &junk1, &junk2); - - if ( nodecount > MAX_NODES - 1 ) { - printf("Error, too many nodes, need to increase array size\n"); - exit(-1); - } else { - printf(" Expecting %d nodes\n", nodecount); - } - - for ( i = 1; i <= nodecount; i++ ) { - fscanf(node, "%d %lf %lf %lf %d\n", &junk1, - &n[0], &n[1], &n[2], &junk2); - // printf("%d %.2f %.2f %.2f\n", junk1, n[0], n[1], n[2]); - p = Point3D( n[0] * ARCSEC_TO_RAD, - n[1] * ARCSEC_TO_RAD, - n[2] ); - nodes[i] = fgGeodToCart(p); - // printf("%d %.2f %.2f %.2f\n", - // junk1, nodes[i].x, nodes[i].y, nodes[i].z); - } - - fclose(node); - - printf("Loading element file: %s ...\n", elename); - if ( (ele = fopen(elename, "r")) == NULL ) { - printf("Cannot open file '%s'\n", elename); - exit(-1); - } - - fscanf(ele, "%d %d %d", &tricount, &junk1, &junk2); - - if ( tricount > MAX_TRIS - 1 ) { - printf("Error, too many elements, need to increase array size\n"); - exit(-1); - } else { - printf(" Expecting %d elements\n", tricount); - } - - for ( i = 1; i <= tricount; i++ ) { - fscanf(ele, "%d %d %d %d\n", &junk1, - &tris[i][0], &tris[i][1], &tris[i][2]); - // printf("%d %d %d %d\n", junk1, tris[i][0], tris[i][1], tris[i][2]);*/ - } - - fclose(ele); -} - - -// dump in WaveFront .obj format -void dump_obj(char *basename) { - char objname[256]; - double n1[3], n2[3], n3[3], n4[3], n5[3], norm[3], temp; - FILE *obj; - int i, t1, t2, t3, t4, t5, count; - double x, y, z; - - strcpy(objname, basename); - strcat(objname, ".obj"); - - printf("Dumping to file: %s ...\n", objname); - - obj = fopen(objname, "w"); - - // dump vertices - printf(" writing vertices\n"); - for ( i = 1; i <= nodecount; i++ ) { - x = nodes[i].x(); - y = nodes[i].y(); - z = nodes[i].z(); - fprintf(obj, "v %.6f %.6f %.6f\n", x, y, z); - } - - printf(" calculating and writing normals\n"); - printf(" First %d normals taken from shared files.\n", normalcount); - - // calculate and generate normals - for ( i = 1; i <= nodecount; i++ ) { - - if ( i <= normalcount ) { - // use precalculated (shared) normal - norm[0] = normals[i-1][0]; - norm[1] = normals[i-1][1]; - norm[2] = normals[i-1][2]; - } else { - // printf("Finding normal\n"); - - find_tris(i, &t1, &t2, &t3, &t4, &t5); - - n1[0] = n1[1] = n1[2] = 0.0; - n2[0] = n2[1] = n2[2] = 0.0; - n3[0] = n3[1] = n3[2] = 0.0; - n4[0] = n4[1] = n4[2] = 0.0; - n5[0] = n5[1] = n5[2] = 0.0; - - count = 1; - calc_normal(nodes[tris[t1][0]], nodes[tris[t1][1]], - nodes[tris[t1][2]], n1); - - if ( t2 > 0 ) { - calc_normal(nodes[tris[t2][0]], nodes[tris[t2][1]], - nodes[tris[t2][2]], n2); - count = 2; - } - - if ( t3 > 0 ) { - calc_normal(nodes[tris[t3][0]], nodes[tris[t3][1]], - nodes[tris[t3][2]], n3); - count = 3; - } - - if ( t4 > 0 ) { - calc_normal(nodes[tris[t4][0]], nodes[tris[t4][1]], - nodes[tris[t4][2]], n4); - count = 4; - } - - if ( t5 > 0 ) { - calc_normal(nodes[tris[t5][0]], nodes[tris[t5][1]], - nodes[tris[t5][2]], n5); - count = 5; - } - - // printf(" norm[2] = %.2f %.2f %.2f\n", n1[2], n2[2], n3[2]); - - norm[0] = ( n1[0] + n2[0] + n3[0] + n4[0] + n5[0] ) / (double)count; - norm[1] = ( n1[1] + n2[1] + n3[1] + n4[1] + n5[1] ) / (double)count; - norm[2] = ( n1[2] + n2[2] + n3[2] + n4[2] + n5[2] ) / (double)count; - - // printf(" count = %d\n", count); - // printf(" Ave. normal = %.4f %.4f %.4f\n", - // norm[0], norm[1], norm[2]);*/ - MAT3_NORMALIZE_VEC(norm, temp); - // printf(" Normalized ave. normal = %.4f %.4f %.4f\n", - // norm[0], norm[1], norm[2]); - } - // printf("%d vn %.4f %.4f %.4f\n", i, norm[0], norm[1], norm[2]); - fprintf(obj, "vn %.4f %.4f %.4f\n", norm[0], norm[1], norm[2]); - } - - // dump faces - printf(" writing faces\n"); - for ( i = 1; i <= tricount; i++ ) { - fprintf(obj, "f %d %d %d\n", tris[i][0], tris[i][1], tris[i][2]); - } - - fclose(obj); -} - -int main(int argc, char **argv) { - char basename[256], basepath[256], temp[256]; - long int tmp_index; - int len; - - strcpy(basename, argv[1]); - - // find the base path of the file - extract_path(basename, basepath); - extract_path(basepath, basepath); - extract_path(basepath, basepath); - printf("%s\n", basepath); - - // find the index of the current file - extract_file(basename, temp); - len = strlen(temp); - if ( len >= 2 ) { - temp[len-2] = '\0'; - } - tmp_index = atoi(temp); - printf("%ld\n", tmp_index); - fgBucketParseIndex(tmp_index, &my_index); - - printf("bucket = %d %d %d %d\n", - my_index.lon, my_index.lat, my_index.x, my_index.y); - // generate the indexes of the neighbors - fgBucketOffset(&my_index, &ne_index, 1, 1); - fgBucketOffset(&my_index, &nw_index, -1, 1); - fgBucketOffset(&my_index, &se_index, 1, -1); - fgBucketOffset(&my_index, &sw_index, -1, -1); - - fgBucketOffset(&my_index, &north_index, 0, 1); - fgBucketOffset(&my_index, &south_index, 0, -1); - fgBucketOffset(&my_index, &east_index, 1, 0); - fgBucketOffset(&my_index, &west_index, -1, 0); - - // load the input data files - triload(basename, basepath); - - // dump in WaveFront .obj format - dump_obj(basename); - - return(0); -} - - -// $Log$ -// Revision 1.5 1998/10/21 14:56:50 curt -// Minor parameter passing tweak. -// -// Revision 1.4 1998/10/20 15:52:46 curt -// Fixed a units conversion bug introduced when converting to Point3D class. -// -// Revision 1.3 1998/10/19 19:33:31 curt -// C++-ification. -// -// Revision 1.2 1998/10/18 01:17:29 curt -// Point3D tweaks. -// -// Revision 1.1 1998/07/08 14:54:53 curt -// renamed *.[ch] to *.[ch]xx -// -// Revision 1.17 1998/07/04 00:56:40 curt -// typedef'd struct fgBUCKET. -// -// Revision 1.16 1998/05/23 15:20:41 curt -// Output more digits after the decimal place. -// -// Revision 1.15 1998/05/02 01:54:39 curt -// Converting to polar3d.h routines. -// -// Revision 1.14 1998/04/18 04:01:32 curt -// Now use libMath rather than having local copies of math routines. -// -// Revision 1.13 1998/04/14 02:26:11 curt -// Code reorganizations. Added a Lib/ directory for more general libraries. -// -// Revision 1.12 1998/04/08 23:22:18 curt -// Adopted Gnu automake/autoconf system. -// -// Revision 1.11 1998/03/03 16:01:00 curt -// More c++ compile tweaks. -// -// Revision 1.10 1998/01/31 00:41:27 curt -// Made a few changes converting floats to doubles. -// -// Revision 1.9 1998/01/27 18:37:04 curt -// Lots of updates to get back in sync with changes made over in .../Src/ -// -// Revision 1.8 1998/01/17 01:25:39 curt -// Added support for shared normals. -// -// Revision 1.7 1998/01/12 02:42:00 curt -// Average up to five triangles per vertex instead of three. -// -// Revision 1.6 1998/01/09 23:03:15 curt -// Restructured to split 1deg x 1deg dem's into 64 subsections. -// -// Revision 1.5 1997/12/08 19:17:50 curt -// Fixed a type in the normal generation code. -// -// Revision 1.4 1997/12/02 13:13:32 curt -// Fixed problem with averaged vertex normals. -// -// Revision 1.3 1997/11/15 18:05:05 curt -// minor tweaks ... -// -// Revision 1.2 1997/11/14 00:29:13 curt -// Transform scenery coordinates at this point in pipeline when scenery is -// being translated to .obj format, not when it is being loaded into the end -// renderer. Precalculate normals for each node as average of the normals -// of each containing polygon so Garoude shading is now supportable. -// -// Revision 1.1 1997/10/29 23:05:15 curt -// Initial revision. -// - diff --git a/Tools/Tri2obj/tri2obj.hxx b/Tools/Tri2obj/tri2obj.hxx deleted file mode 100644 index c7a54d159..000000000 --- a/Tools/Tri2obj/tri2obj.hxx +++ /dev/null @@ -1,68 +0,0 @@ -/* tri2obj.h -- read in a .ele/.node file pair generated by the triangle - * program and output a Wavefront .obj file. - * - * Written by Curtis Olson, started October 1997. - * - * Copyright (C) 1997 Curtis L. Olson - curt@infoplane.com - * - * 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. - * - * $Id$ - * (Log is kept at end of this file) - */ - - -#ifndef TRI2OBJ_H -#define TRI2OBJ_H - - -#include -#include - - -#define MAX_NODES 200000 -#define MAX_TRIS 400000 - - -/* Initialize a new mesh structure */ -void triload(char *basename, char *basepath); - - -#endif /* TRI2OBJ_H */ - - -/* $Log$ -/* Revision 1.1 1998/07/08 14:54:54 curt -/* renamed *.[ch] to *.[ch]xx -/* - * Revision 1.5 1998/03/03 16:01:00 curt - * More c++ compile tweaks. - * - * Revision 1.4 1998/01/17 01:25:40 curt - * Added support for shared normals. - * - * Revision 1.3 1997/11/15 18:05:06 curt - * minor tweaks ... - * - * Revision 1.2 1997/11/14 00:29:13 curt - * Transform scenery coordinates at this point in pipeline when scenery is - * being translated to .obj format, not when it is being loaded into the end - * renderer. Precalculate normals for each node as average of the normals - * of each containing polygon so Garoude shading is now supportable. - * - * Revision 1.1 1997/10/29 23:05:15 curt - * Initial revision. - * - */ diff --git a/Tools/Makedir/Makefile.am b/Tools/Utils/Makedir/Makefile.am similarity index 100% rename from Tools/Makedir/Makefile.am rename to Tools/Utils/Makedir/Makefile.am diff --git a/Tools/Makedir/makedir.cxx b/Tools/Utils/Makedir/makedir.cxx similarity index 100% rename from Tools/Makedir/makedir.cxx rename to Tools/Utils/Makedir/makedir.cxx diff --git a/Tools/Utils/Makefile.am b/Tools/Utils/Makefile.am index 5c3f005b0..6d557ffb1 100644 --- a/Tools/Utils/Makefile.am +++ b/Tools/Utils/Makefile.am @@ -1,2 +1,4 @@ SUBDIRS = \ Makedir + +EXTRA_DIST = mirror-dem diff --git a/Tools/Utils/convert.pl b/Tools/Utils/convert.pl new file mode 100755 index 000000000..fe28671ea --- /dev/null +++ b/Tools/Utils/convert.pl @@ -0,0 +1,20 @@ +#!/usr/local/bin/perl + +# do some star data file conversion + +$PI = 3.14159265358979323846; +$DEG_TO_RAD = $PI / 180.0; + +while ( <> ) { + chop; + ($name, $junk, $ra, $decl, $mag, $junk) = split(/,/); + + @RA = split(/:/, $ra); + @DECL = split(/:/, $decl); + + $new_ra = $RA[0] + ( $RA[1] / 60.0 ) + ( $RA[2] / 3600.0 ); + $new_decl = $DECL[0] + ( $DECL[1] / 60.0 ) + ( $DECL[2] / 3600.0 ); + + printf("%s,%.6f,%.6f,%.6f\n", $name, $new_ra * 15 * $DEG_TO_RAD, + $new_decl * $DEG_TO_RAD, $mag); +} diff --git a/Tools/Utils/mirror-dem b/Tools/Utils/mirror-dem new file mode 100644 index 000000000..4bd1fa7a9 --- /dev/null +++ b/Tools/Utils/mirror-dem @@ -0,0 +1,29 @@ +# Example parameter file for the Debian GNU/Linux "mirror" package +# +# This serves as an illustration for a valid mirror parameter file. See the +# man page mirror(1) and the files in /usr/doc/example/mirror/* for details. +# +# This is for illustration. It worked for me when I wrote it, but it might +# fail for you. No warranties whatsoever. Use at your own risk. +# +# Written by Dirk Eddelbuettel + +package=DEM-3-Arc-Sec + comment=USGS DEM files from ftp://edcftp.cr.usgs.gov/pub/data/DEM/250/ + # specify remote host and directory + site=edcftp.cr.usgs.gov + remote_dir=/pub/data/DEM/250/ + # specify local directory + local_dir=/stage/video/curt/DEM/250 + # inform this user about results + mail_to=curt + # compress these files (see perlre(1) for regular expressions) + compress_patt=\.*(Contents|Packages|Packages-Master)$ + # exclude these files or directories (see perlre(1) for reg. expr.) + # exclude_patt= + # preserve these files or directories (see perlre(1) for reg. expr.) + # delete_excl= + # do not delete if more than 20% of all files would vanish + max_delete_files=20% + # this speeds up the construction of the remote ls-lR by pruning + # recurse_hard=true diff --git a/Tools/Tools/process-dem.pl b/Tools/process-dem.pl similarity index 99% rename from Tools/Tools/process-dem.pl rename to Tools/process-dem.pl index 5a92c5bb5..b822e3ab2 100755 --- a/Tools/Tools/process-dem.pl +++ b/Tools/process-dem.pl @@ -544,6 +544,9 @@ sub install { #--------------------------------------------------------------------------- # $Log$ +# Revision 1.1 1999/04/05 21:32:41 curt +# Initial revision +# # Revision 1.32 1998/11/20 01:02:55 curt # Speedups for win32. # diff --git a/Tools/Tools/scenery_version.hxx b/Tools/scenery_version.hxx similarity index 94% rename from Tools/Tools/scenery_version.hxx rename to Tools/scenery_version.hxx index c5616a646..0d0e67972 100644 --- a/Tools/Tools/scenery_version.hxx +++ b/Tools/scenery_version.hxx @@ -26,6 +26,9 @@ // $Log$ +// Revision 1.1 1999/04/05 21:32:41 curt +// Initial revision +// // Revision 1.1 1999/03/25 19:13:35 curt // Initial revision. // diff --git a/configure.in b/configure.in index 1a01e004a..a54a5726f 100644 --- a/configure.in +++ b/configure.in @@ -256,12 +256,13 @@ AC_CHECK_HEADERS( gpc.h ) if test "x$ac_cv_header_gpc_h" != "xyes"; then echo echo "You need to have the GPC library installed on your system to build" - echo "some of the scenery generation tools, otherwise, they may fail." + echo "some of the scenery generation tools, otherwise you won't be able." + echo "to create scenery." echo - echo "You can get the library from:" - echo - echo " http://www.cs.man.ac.uk/aig/staff/alan/software/" + echo "Please see README.gpc for more details." echo + echo "(pausing 5 seconds)" + sleep 5 fi dnl Check if Geographic Foundation Classes library is installed